From 5798c4c7d311f8792e74b49a58963b1c173451bd Mon Sep 17 00:00:00 2001 From: Snarling <84951833+Snarling@users.noreply.github.com> Date: Sun, 28 Aug 2022 05:33:38 -0400 Subject: [PATCH 01/46] Unify error handling --- src/Augmentation/AugmentationHelpers.tsx | 6 +- src/Casino/Game.tsx | 4 +- src/Corporation/Corporation.tsx | 2 +- src/Corporation/Industry.ts | 35 +--- .../ui/modals/BribeFactionModal.tsx | 4 +- .../ui/modals/IssueNewSharesModal.tsx | 13 +- src/Corporation/ui/modals/ResearchModal.tsx | 4 +- src/Corporation/ui/modals/ThrowPartyModal.tsx | 3 +- src/Faction/FactionHelpers.tsx | 9 +- src/Locations/LocationsHelpers.tsx | 4 +- src/Locations/ui/TravelAgencyRoot.tsx | 2 +- .../{MessageHelpers.ts => MessageHelpers.tsx} | 64 ++++--- src/Netscript/APIWrapper.ts | 2 +- src/Netscript/NetscriptHelpers.ts | 53 +++--- src/Netscript/killWorkerScript.ts | 9 +- src/NetscriptJSEvaluator.ts | 9 +- src/NetscriptWorker.ts | 170 ++++-------------- src/SaveObject.tsx | 23 +-- src/Script/ScriptModule.ts | 2 +- src/UncaughtPromiseHandler.ts | 25 +-- src/ui/React/DialogBox.tsx | 30 +++- 21 files changed, 149 insertions(+), 324 deletions(-) rename src/Message/{MessageHelpers.ts => MessageHelpers.tsx} (82%) diff --git a/src/Augmentation/AugmentationHelpers.tsx b/src/Augmentation/AugmentationHelpers.tsx index a8ffa8e83..c388356f6 100644 --- a/src/Augmentation/AugmentationHelpers.tsx +++ b/src/Augmentation/AugmentationHelpers.tsx @@ -126,15 +126,15 @@ function installAugmentations(force?: boolean): boolean { if (ownedAug.name === AugmentationNames.NeuroFluxGovernor) { level = ` - ${ownedAug.level}`; } - augmentationList += aug.name + level + "
"; + augmentationList += aug.name + level + "\n"; } Player.queuedAugmentations = []; if (!force) { dialogBoxCreate( "You slowly drift to sleep as scientists put you under in order " + - "to install the following Augmentations:
" + + "to install the following Augmentations:\n" + augmentationList + - "
You wake up in your home...you feel different...", + "\nYou wake up in your home...you feel different...", ); } prestigeAugmentation(); diff --git a/src/Casino/Game.tsx b/src/Casino/Game.tsx index 1da783d28..b20eda813 100644 --- a/src/Casino/Game.tsx +++ b/src/Casino/Game.tsx @@ -11,7 +11,7 @@ export function win(p: IPlayer, n: number): void { export function reachedLimit(p: IPlayer): boolean { const reached = p.getCasinoWinnings() > gainLimit; if (reached) { - dialogBoxCreate(<>Alright cheater get out of here. You're not allowed here anymore.); + dialogBoxCreate("Alright cheater get out of here. You're not allowed here anymore."); } return reached; } @@ -24,7 +24,7 @@ export class Game extends React.Component { reachedLimit(p: IPlayer): boolean { const reached = p.getCasinoWinnings() > gainLimit; if (reached) { - dialogBoxCreate(<>Alright cheater get out of here. You're not allowed here anymore.); + dialogBoxCreate("Alright cheater get out of here. You're not allowed here anymore."); } return reached; } diff --git a/src/Corporation/Corporation.tsx b/src/Corporation/Corporation.tsx index cf6ac9125..d9643eddf 100644 --- a/src/Corporation/Corporation.tsx +++ b/src/Corporation/Corporation.tsx @@ -120,7 +120,7 @@ export class Corporation { 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.

" + + "This is a bug. Please report to game developer.\n\n" + "(Your funds have been set to $150b for the inconvenience)", ); this.funds = 150e9; diff --git a/src/Corporation/Industry.ts b/src/Corporation/Industry.ts index 8ec68f26f..affcf04e2 100644 --- a/src/Corporation/Industry.ts +++ b/src/Corporation/Industry.ts @@ -825,14 +825,7 @@ export class Industry implements IIndustry { sellAmt = eval(tmp); } catch (e) { dialogBoxCreate( - "Error evaluating your sell amount for material " + - mat.name + - " in " + - this.name + - "'s " + - city + - " office. The sell amount " + - "is being set to zero", + `Error evaluating your sell amount for material ${mat.name} in ${this.name}'s ${city} office. The sell amount is being set to zero`, ); sellAmt = 0; } @@ -879,27 +872,13 @@ export class Industry implements IIndustry { amt = eval(amtStr); } catch (e) { dialogBoxCreate( - "Calculating export for " + - mat.name + - " in " + - this.name + - "'s " + - city + - " division failed with " + - "error: " + - e, + `Calculating export for ${mat.name} in ${this.name}'s ${city} division failed with error: ${e}`, ); continue; } if (isNaN(amt)) { dialogBoxCreate( - "Error calculating export amount for " + - mat.name + - " in " + - this.name + - "'s " + - city + - " division.", + `Error calculating export amount for ${mat.name} in ${this.name}'s ${city} division.`, ); continue; } @@ -1172,13 +1151,7 @@ export class Industry implements IIndustry { tmp = eval(tmp); } catch (e) { dialogBoxCreate( - "Error evaluating your sell price expression for " + - product.name + - " in " + - this.name + - "'s " + - city + - " office. Sell price is being set to MAX", + `Error evaluating your sell price expression for ${product.name} in ${this.name}'s ${city} office. Sell price is being set to MAX`, ); tmp = product.maxsll; } diff --git a/src/Corporation/ui/modals/BribeFactionModal.tsx b/src/Corporation/ui/modals/BribeFactionModal.tsx index 87d20105d..341c56772 100644 --- a/src/Corporation/ui/modals/BribeFactionModal.tsx +++ b/src/Corporation/ui/modals/BribeFactionModal.tsx @@ -60,9 +60,7 @@ export function BribeFactionModal(props: IProps): React.ReactElement { const fac = Factions[selectedFaction]; if (disabled) return; const rep = repGain(money); - dialogBoxCreate( - "You gained " + numeralWrapper.formatReputation(rep) + " reputation with " + fac.name + " by bribing them.", - ); + dialogBoxCreate(`You gained ${numeralWrapper.formatReputation(rep)} reputation with ${fac.name} by bribing them.`); fac.playerReputation += rep; corp.funds = corp.funds - money; props.onClose(); diff --git a/src/Corporation/ui/modals/IssueNewSharesModal.tsx b/src/Corporation/ui/modals/IssueNewSharesModal.tsx index 85c7f8b97..944d58203 100644 --- a/src/Corporation/ui/modals/IssueNewSharesModal.tsx +++ b/src/Corporation/ui/modals/IssueNewSharesModal.tsx @@ -89,14 +89,11 @@ export function IssueNewSharesModal(props: IProps): React.ReactElement { let dialogContents = `Issued ${numeralWrapper.format(newShares, "0.000a")} new shares` + - ` and raised ${numeralWrapper.formatMoney(profit)}.`; - if (privateShares > 0) { - dialogContents += `
${numeralWrapper.format( - privateShares, - "0.000a", - )} of these shares were bought by private investors.`; - } - dialogContents += `

Stock price decreased to ${numeralWrapper.formatMoney(corp.sharePrice)}`; + ` and raised ${numeralWrapper.formatMoney(profit)}.` + + (privateShares > 0) + ? "\n" + numeralWrapper.format(privateShares, "0.000a") + "of these shares were bought by private investors." + : ""; + dialogContents += `\n\nStock price decreased to ${numeralWrapper.formatMoney(corp.sharePrice)}`; dialogBoxCreate(dialogContents); } diff --git a/src/Corporation/ui/modals/ResearchModal.tsx b/src/Corporation/ui/modals/ResearchModal.tsx index 40570aba5..d0c47d3aa 100644 --- a/src/Corporation/ui/modals/ResearchModal.tsx +++ b/src/Corporation/ui/modals/ResearchModal.tsx @@ -42,9 +42,7 @@ function Upgrade({ n, division }: INodeProps): React.ReactElement { } dialogBoxCreate( - `Researched ${n.text}. It may take a market cycle ` + - `(~${CorporationConstants.SecsPerMarketCycle} seconds) before the effects of ` + - `the Research apply.`, + `Researched ${n.text}. It may take a market cycle (~${CorporationConstants.SecsPerMarketCycle} seconds) before the effects of the Research apply.`, ); } diff --git a/src/Corporation/ui/modals/ThrowPartyModal.tsx b/src/Corporation/ui/modals/ThrowPartyModal.tsx index 8bbd9d3f7..4190e6b85 100644 --- a/src/Corporation/ui/modals/ThrowPartyModal.tsx +++ b/src/Corporation/ui/modals/ThrowPartyModal.tsx @@ -41,8 +41,7 @@ export function ThrowPartyModal(props: IProps): React.ReactElement { if (mult > 0) { dialogBoxCreate( - "You threw a party for the office! The morale and happiness " + - "of each employee increased by " + + "You threw a party for the office! The morale and happiness of each employee increased by " + numeralWrapper.formatPercentage(mult - 1), ); } diff --git a/src/Faction/FactionHelpers.tsx b/src/Faction/FactionHelpers.tsx index 882cba6b7..6e7d9509b 100644 --- a/src/Faction/FactionHelpers.tsx +++ b/src/Faction/FactionHelpers.tsx @@ -94,12 +94,9 @@ export function purchaseAugmentation(aug: Augmentation, fac: Faction, sing = fal return "You purchased " + aug.name; } else if (!Settings.SuppressBuyAugmentationConfirmation) { dialogBoxCreate( - "You purchased " + - aug.name + - ". Its enhancements will not take " + - "effect until they are installed. To install your augmentations, go to the " + - "'Augmentations' tab on the left-hand navigation menu. Purchasing additional " + - "augmentations will now be more expensive.", + `You purchased ${aug.name}. Its enhancements will not take effect until they are installed.` + + "To install your augmentations, go to the 'Augmentations' tab on the left-hand navigation menu." + + "Purchasing additional augmentations will now be more expensive.", ); } } else { diff --git a/src/Locations/LocationsHelpers.tsx b/src/Locations/LocationsHelpers.tsx index 30bdabe5c..86e449f2e 100644 --- a/src/Locations/LocationsHelpers.tsx +++ b/src/Locations/LocationsHelpers.tsx @@ -33,8 +33,8 @@ export function purchaseTorRouter(p: IPlayer): void { p.getHomeComputer().serversOnNetwork.push(darkweb.hostname); darkweb.serversOnNetwork.push(p.getHomeComputer().hostname); dialogBoxCreate( - "You have purchased a TOR router!
" + - "You now have access to the dark web from your home computer.
" + + "You have purchased a TOR router!\n" + + "You now have access to the dark web from your home computer.\n" + "Use the scan/scan-analyze commands to search for the dark web connection.", ); } diff --git a/src/Locations/ui/TravelAgencyRoot.tsx b/src/Locations/ui/TravelAgencyRoot.tsx index 9e3b58b06..6711b8857 100644 --- a/src/Locations/ui/TravelAgencyRoot.tsx +++ b/src/Locations/ui/TravelAgencyRoot.tsx @@ -35,7 +35,7 @@ function travel(p: IPlayer, router: IRouter, to: CityName): void { p.loseMoney(cost, "other"); p.travel(to); - dialogBoxCreate(<>You are now in {to}!); + dialogBoxCreate(`You are now in ${to}!`); router.toCity(); } diff --git a/src/Message/MessageHelpers.ts b/src/Message/MessageHelpers.tsx similarity index 82% rename from src/Message/MessageHelpers.ts rename to src/Message/MessageHelpers.tsx index 26764b72c..dc6d87d95 100644 --- a/src/Message/MessageHelpers.ts +++ b/src/Message/MessageHelpers.tsx @@ -1,3 +1,4 @@ +import React from "react"; import { Message } from "./Message"; import { AugmentationNames } from "../Augmentation/data/AugmentationNames"; import { Router } from "../ui/GameRoot"; @@ -22,15 +23,12 @@ function sendMessage(msg: Message, forced = false): void { function showMessage(name: MessageFilenames): void { const msg = Messages[name]; if (!(msg instanceof Message)) throw new Error("trying to display unexistent message"); - const txt = - "Message received from unknown sender:

" + - "" + - msg.msg + - "

" + - "This message was saved as " + - msg.filename + - " onto your home computer."; - dialogBoxCreate(txt); + dialogBoxCreate( + <> + Message received from unknown sender:{msg.msg}This message was saved as {msg.filename} onto your home + computer. + , + ); } //Adds a message to a server @@ -127,20 +125,20 @@ const Messages: Record = { MessageFilenames.Jumper0, "I know you can sense it. I know you're searching for it. " + "It's why you spend night after " + - "night at your computer.

It's real, I've seen it. And I can " + - "help you find it. But not right now. You're not ready yet.

" + - "Use this program to track your progress

" + - "The fl1ght.exe program was added to your home computer

" + + "night at your computer. \n\nIt's real, I've seen it. And I can " + + "help you find it. But not right now. You're not ready yet.\n\n" + + "Use this program to track your progress\n\n" + + "The fl1ght.exe program was added to your home computer\n\n" + "-jump3R", ), [MessageFilenames.Jumper1]: new Message( MessageFilenames.Jumper1, `Soon you will be contacted by a hacking group known as ${FactionNames.NiteSec}. ` + - "They can help you with your search.

" + + "They can help you with your search. \n\n" + "You should join them, garner their favor, and " + "exploit them for their Augmentations. But do not trust them. " + - "They are not what they seem. No one is.

" + + "They are not what they seem. No one is.\n\n" + "-jump3R", ), @@ -148,21 +146,21 @@ const Messages: Record = { MessageFilenames.Jumper2, "Do not try to save the world. There is no world to save. If " + "you want to find the truth, worry only about yourself. Ethics and " + - `morals will get you killed.

Watch out for a hacking group known as ${FactionNames.NiteSec}.` + - "

-jump3R", + `morals will get you killed. \n\nWatch out for a hacking group known as ${FactionNames.NiteSec}.` + + "\n\n-jump3R", ), [MessageFilenames.Jumper3]: new Message( MessageFilenames.Jumper3, "You must learn to walk before you can run. And you must " + - `run before you can fly. Look for ${FactionNames.TheBlackHand}.

` + - "I.I.I.I

-jump3R", + `run before you can fly. Look for ${FactionNames.TheBlackHand}. \n\n` + + "I.I.I.I \n\n-jump3R", ), [MessageFilenames.Jumper4]: new Message( MessageFilenames.Jumper4, "To find what you are searching for, you must understand the bits. " + - "The bits are all around us. The runners will help you.

" + + "The bits are all around us. The runners will help you.\n\n" + "-jump3R", ), @@ -171,8 +169,8 @@ const Messages: Record = { MessageFilenames.CyberSecTest, "We've been watching you. Your skills are very impressive. But you're wasting " + "your talents. If you join us, you can put your skills to good use and change " + - "the world for the better. If you join us, we can unlock your full potential.

" + - "But first, you must pass our test. Find and install the backdoor on our server.

" + + "the world for the better. If you join us, we can unlock your full potential. \n\n" + + "But first, you must pass our test. Find and install the backdoor on our server. \n\n" + `-${FactionNames.CyberSec}`, ), @@ -181,17 +179,17 @@ const Messages: Record = { "People say that the corrupted governments and corporations rule the world. " + "Yes, maybe they do. But do you know who everyone really fears? People " + "like us. Because they can't hide from us. Because they can't fight shadows " + - "and ideas with bullets.

" + - "Join us, and people will fear you, too.

" + + "and ideas with bullets. \n\n" + + "Join us, and people will fear you, too. \n\n" + "Find and install the backdoor on our server, avmnite-02h. Then, we will contact you again." + - `

-${FactionNames.NiteSec}`, + `\n\n-${FactionNames.NiteSec}`, ), [MessageFilenames.BitRunnersTest]: new Message( MessageFilenames.BitRunnersTest, "We know what you are doing. We know what drives you. We know " + - "what you are looking for.

" + - "We can help you find the answers.

" + + "what you are looking for. \n\n " + + "We can help you find the answers.\n\n" + "run4theh111z", ), @@ -199,18 +197,18 @@ const Messages: Record = { [MessageFilenames.TruthGazer]: new Message( MessageFilenames.TruthGazer, //"THE TRUTH CAN NO LONGER ESCAPE YOUR GAZE" - "@&*($#@&__TH3__#@A&#@*)__TRU1H__(*)&*)($#@&()E&R)W&
" + - "%@*$^$()@&$)$*@__CAN__()(@^#)@&@)#__N0__(#@&#)@&@&(
" + - "*(__LON6ER__^#)@)(()*#@)@__ESCAP3__)#(@(#@*@()@(#*$
" + + "@&*($#@&__TH3__#@A&#@*)__TRU1H__(*)&*)($#@&()E&R)W&\n" + + "%@*$^$()@&$)$*@__CAN__()(@^#)@&@)#__N0__(#@&#)@&@&(\n" + + "*(__LON6ER__^#)@)(()*#@)@__ESCAP3__)#(@(#@*@()@(#*$\n" + "()@)#$*%)$#()$#__Y0UR__(*)$#()%(&(%)*!)($__GAZ3__#(", ), [MessageFilenames.RedPill]: new Message( MessageFilenames.RedPill, //"FIND THE-CAVE" - "@)(#V%*N)@(#*)*C)@#%*)*V)@#(*%V@)(#VN%*)@#(*%
" + - ")@B(*#%)@)M#B*%V)____FIND___#$@)#%(B*)@#(*%B)
" + - "@_#(%_@#M(BDSPOMB__THE-CAVE_#)$(*@#$)@#BNBEGB
" + + "@)(#V%*N)@(#*)*C)@#%*)*V)@#(*%V@)(#VN%*)@#(*%\n" + + ")@B(*#%)@)M#B*%V)____FIND___#$@)#%(B*)@#(*%B)\n" + + "@_#(%_@#M(BDSPOMB__THE-CAVE_#)$(*@#$)@#BNBEGB\n" + "DFLSMFVMV)#@($*)@#*$MV)@#(*$V)M#(*$)M@(#*VM$)", ), }; diff --git a/src/Netscript/APIWrapper.ts b/src/Netscript/APIWrapper.ts index 3e1522e90..0bd5817d4 100644 --- a/src/Netscript/APIWrapper.ts +++ b/src/Netscript/APIWrapper.ts @@ -41,7 +41,7 @@ function wrapFunction( const functionPath = tree.join("."); const functionName = tree.pop(); if (typeof functionName !== "string") { - throw helpers.makeRuntimeRejectMsg(workerScript, "Failure occured while wrapping netscript api"); + throw helpers.makeBasicErrorMsg(workerScript, "Failure occured while wrapping netscript api"); } const ctx = { workerScript, diff --git a/src/Netscript/NetscriptHelpers.ts b/src/Netscript/NetscriptHelpers.ts index 017463737..0ca89db76 100644 --- a/src/Netscript/NetscriptHelpers.ts +++ b/src/Netscript/NetscriptHelpers.ts @@ -3,7 +3,6 @@ import { WorkerScript } from "./WorkerScript"; import { GetAllServers, GetServer } from "../Server/AllServers"; import { Player } from "../Player"; import { ScriptDeath } from "./ScriptDeath"; -import { isString } from "../utils/helpers/isString"; import { numeralWrapper } from "../ui/numeralFormat"; import { ScriptArg } from "./ScriptArg"; import { CityName } from "../Locations/data/CityNames"; @@ -40,8 +39,7 @@ export const helpers = { number, scriptArgs, argsToString, - isScriptErrorMessage, - makeRuntimeRejectMsg, + makeBasicErrorMsg, makeRuntimeErrorMsg, resolveNetscriptRequestedThreads, checkEnvFlags, @@ -114,15 +112,6 @@ function scriptArgs(ctx: NetscriptContext, args: unknown) { return args; } -/** Determines if the given msg string is an error created by makeRuntimeRejectMsg. */ -function isScriptErrorMessage(msg: string): boolean { - if (!isString(msg)) { - return false; - } - const splitMsg = msg.split("|DELIMITER|"); - return splitMsg.length == 4; -} - /** Convert multiple arguments for tprint or print into a single string. */ function argsToString(args: unknown[]): string { let out = ""; @@ -143,12 +132,11 @@ function argsToString(args: unknown[]): string { } /** Creates an error message string containing hostname, scriptname, and the error message msg */ -function makeRuntimeRejectMsg(workerScript: WorkerScript, msg: string): string { +function makeBasicErrorMsg(workerScript: WorkerScript, msg: string): string { for (const scriptUrl of workerScript.scriptRef.dependencies) { msg = msg.replace(new RegExp(scriptUrl.url, "g"), scriptUrl.filename); } - - return "|DELIMITER|" + workerScript.hostname + "|DELIMITER|" + workerScript.name + "|DELIMITER|" + msg; + return msg; } /** Creates an error message string with a stack trace. */ @@ -156,9 +144,9 @@ function makeRuntimeErrorMsg(ctx: NetscriptContext, msg: string): string { const errstack = new Error().stack; if (errstack === undefined) throw new Error("how did we not throw an error?"); const stack = errstack.split("\n").slice(1); - const workerScript = ctx.workerScript; - const caller = ctx.function; - const scripts = workerScript.getServer().scripts; + const ws = ctx.workerScript; + const caller = ctx.functionPath; + const scripts = ws.getServer().scripts; const userstack = []; for (const stackline of stack) { let filename; @@ -216,10 +204,10 @@ function makeRuntimeErrorMsg(ctx: NetscriptContext, msg: string): string { userstack.push(`${filename}:L${call.line}@${call.func}`); } - workerScript.log(caller, () => msg); + log(ctx, () => msg); let rejectMsg = `${caller}: ${msg}`; if (userstack.length !== 0) rejectMsg += `

Stack:
${userstack.join("
")}`; - return makeRuntimeRejectMsg(workerScript, rejectMsg); + return makeBasicErrorMsg(ws, rejectMsg); } /** Validate requested number of threads for h/g/w options */ @@ -230,14 +218,14 @@ function resolveNetscriptRequestedThreads(ctx: NetscriptContext, requestedThread } const requestedThreadsAsInt = requestedThreads | 0; if (isNaN(requestedThreads) || requestedThreadsAsInt < 1) { - throw makeRuntimeRejectMsg( - ctx.workerScript, + throw makeRuntimeErrorMsg( + ctx, `Invalid thread count passed to ${ctx.function}: ${requestedThreads}. Threads must be a positive number.`, ); } if (requestedThreadsAsInt > threads) { - throw makeRuntimeRejectMsg( - ctx.workerScript, + throw makeRuntimeErrorMsg( + ctx, `Too many threads requested by ${ctx.function}. Requested: ${requestedThreads}. Has: ${threads}.`, ); } @@ -258,17 +246,21 @@ function checkSingularityAccess(ctx: NetscriptContext): void { /** Create an error if a script is dead or if concurrent ns function calls are made */ function checkEnvFlags(ctx: NetscriptContext): void { const ws = ctx.workerScript; - if (ws.env.stopFlag) throw new ScriptDeath(ws); + if (ws.env.stopFlag) { + log(ctx, () => "Failed to run due to script being killed."); + throw new ScriptDeath(ws); + } if (ws.env.runningFn && ctx.function !== "asleep") { - ws.errorMessage = makeRuntimeRejectMsg( + //This one has no error message so it will not create a dialog + if (ws.delayReject) ws.delayReject(new ScriptDeath(ws)); + ws.errorMessage = makeBasicErrorMsg( ws, `Concurrent calls to Netscript functions are not allowed! Did you forget to await hack(), grow(), or some other promise-returning function? Currently running: ${ws.env.runningFn} tried to run: ${ctx.function}`, ); - if (ws.delayReject) ws.delayReject(new ScriptDeath(ws)); - throw new ScriptDeath(ws); //No idea if this is the right thing to throw + throw new ScriptDeath(ws); } } @@ -302,7 +294,8 @@ function updateDynamicRam(ctx: NetscriptContext, ramCost: number): void { } ws.dynamicRamUsage += ramCost; if (ws.dynamicRamUsage > 1.01 * ws.ramUsage) { - ws.errorMessage = makeRuntimeRejectMsg( + log(ctx, () => "Insufficient static ram available."); + ws.errorMessage = makeBasicErrorMsg( ws, `Dynamic RAM usage calculated to be greater than initial RAM usage on fn: ${fnName}. This is probably because you somehow circumvented the static RAM calculation. @@ -605,7 +598,7 @@ function getRunningScriptByArgs( scriptArgs: ScriptArg[], ): RunningScript | null { if (!Array.isArray(scriptArgs)) { - throw helpers.makeRuntimeRejectMsg( + throw helpers.makeBasicErrorMsg( ctx.workerScript, `Invalid scriptArgs argument passed into getRunningScript() from ${ctx.function}(). ` + `This is probably a bug. Please report to game developer`, diff --git a/src/Netscript/killWorkerScript.ts b/src/Netscript/killWorkerScript.ts index b90ded508..f41e179c0 100644 --- a/src/Netscript/killWorkerScript.ts +++ b/src/Netscript/killWorkerScript.ts @@ -10,7 +10,7 @@ import { WorkerScriptStartStopEventEmitter } from "./WorkerScriptStartStopEventE import { RunningScript } from "../Script/RunningScript"; import { GetServer } from "../Server/AllServers"; -import { dialogBoxCreate } from "../ui/React/DialogBox"; +import { errorDialog } from "../ui/React/DialogBox"; import { AddRecentScript } from "./RecentScripts"; import { Player } from "../Player"; import { ITutorial } from "../InteractiveTutorial"; @@ -66,12 +66,7 @@ function stopAndCleanUpWorkerScript(ws: WorkerScript): void { ws.env.stopFlag = false; ws.atExit(); } catch (e: unknown) { - let message = e instanceof ScriptDeath ? e.errorMessage : String(e); - message = message.replace(/.*\|DELIMITER\|/, ""); - dialogBoxCreate( - `Error trying to call atExit for script ${[ws.name, ...ws.args].join(" ")} on ${ws.hostname}\n ${message}`, - ); - console.error(e); + errorDialog(e, `Error during atExit ${ws.name}@${ws.hostname} (PID - ${ws.pid}\n\n`); } ws.atExit = undefined; } diff --git a/src/NetscriptJSEvaluator.ts b/src/NetscriptJSEvaluator.ts index 8e5f00861..9b384fe65 100644 --- a/src/NetscriptJSEvaluator.ts +++ b/src/NetscriptJSEvaluator.ts @@ -71,7 +71,7 @@ export async function executeJSScript( const ns = workerScript.env.vars; if (!loadedModule) { - throw helpers.makeRuntimeRejectMsg( + throw helpers.makeBasicErrorMsg( workerScript, `${script.filename} cannot be run because the script module won't load`, ); @@ -79,18 +79,19 @@ export async function executeJSScript( // TODO: putting await in a non-async function yields unhelpful // "SyntaxError: unexpected reserved word" with no line number information. if (!loadedModule.main) { - throw helpers.makeRuntimeRejectMsg( + throw helpers.makeBasicErrorMsg( workerScript, `${script.filename} cannot be run because it does not have a main function.`, ); } if (!ns) { - throw helpers.makeRuntimeRejectMsg( + throw helpers.makeBasicErrorMsg( workerScript, `${script.filename} cannot be run because the NS object hasn't been constructed properly.`, ); } - return loadedModule.main(ns); + await loadedModule.main(ns); + return; } function isDependencyOutOfDate(filename: string, scripts: Script[], scriptModuleSequenceNumber: number): boolean { diff --git a/src/NetscriptWorker.ts b/src/NetscriptWorker.ts index 7f808adc4..1d05043aa 100644 --- a/src/NetscriptWorker.ts +++ b/src/NetscriptWorker.ts @@ -24,10 +24,9 @@ import { Settings } from "./Settings/Settings"; import { generate } from "escodegen"; -import { dialogBoxCreate } from "./ui/React/DialogBox"; +import { dialogBoxCreate, errorDialog } from "./ui/React/DialogBox"; import { arrayToString } from "./utils/helpers/arrayToString"; import { roundToTwo } from "./utils/helpers/roundToTwo"; -import { isString } from "./utils/helpers/isString"; import { parse } from "acorn"; import { simple as walksimple } from "acorn-walk"; @@ -35,7 +34,6 @@ import { areFilesEqual } from "./Terminal/DirectoryHelpers"; import { Player } from "./Player"; import { Terminal } from "./Terminal"; import { ScriptArg } from "./Netscript/ScriptArg"; -import { helpers } from "./Netscript/NetscriptHelpers"; export const NetscriptPorts: Map = new Map(); @@ -54,39 +52,8 @@ export function prestigeWorkerScripts(): void { // JS script promises need a little massaging to have the same guarantees as netscript // promises. This does said massaging and kicks the script off. It returns a promise // that resolves or rejects when the corresponding worker script is done. -function startNetscript2Script(workerScript: WorkerScript): Promise { - return new Promise((resolve, reject) => { - executeJSScript(Player, workerScript.getServer().scripts, workerScript) - .then(() => { - resolve(); - }) - .catch((e) => reject(e)); - }).catch((e) => { - if (e instanceof Error) { - if (e instanceof SyntaxError) { - workerScript.errorMessage = helpers.makeRuntimeRejectMsg( - workerScript, - e.message + " (sorry we can't be more helpful)", - ); - } else { - workerScript.errorMessage = helpers.makeRuntimeRejectMsg( - workerScript, - e.message + ((e.stack && "\nstack:\n" + e.stack.toString()) || ""), - ); - } - throw new ScriptDeath(workerScript); - } else if (helpers.isScriptErrorMessage(e)) { - workerScript.errorMessage = e; - throw new ScriptDeath(workerScript); - } else if (e instanceof ScriptDeath) { - throw e; - } - - // Don't know what to do with it, let's try making an error message out of it - workerScript.errorMessage = helpers.makeRuntimeRejectMsg(workerScript, "" + e); - throw new ScriptDeath(workerScript); - }); -} +const startNetscript2Script = (workerScript: WorkerScript): Promise => + executeJSScript(Player, workerScript.getServer().scripts, workerScript); function startNetscript1Script(workerScript: WorkerScript): Promise { const code = workerScript.code; @@ -98,18 +65,16 @@ function startNetscript1Script(workerScript: WorkerScript): Promise { codeWithImports = importProcessingRes.code; codeLineOffset = importProcessingRes.lineOffset; } catch (e: unknown) { - dialogBoxCreate("Error processing Imports in " + workerScript.name + ":
" + String(e)); + dialogBoxCreate(`Error processing Imports in ${workerScript.name} on ${workerScript.hostname}:\n\n${e}`); workerScript.env.stopFlag = true; killWorkerScript(workerScript); return Promise.resolve(); } - function wrapNS1Layer(int: Interpreter, intLayer: unknown, path: string[] = []) { - //TODO: Better typing layers of interpreter scope and ns - interface BasicObject { - [key: string]: any; - } - const nsLayer = path.reduce((prev, newPath) => prev[newPath], workerScript.env.vars as BasicObject); + interface BasicObject { + [key: string]: any; + } + function wrapNS1Layer(int: Interpreter, intLayer: unknown, nsLayer = workerScript.env.vars as BasicObject) { for (const [name, entry] of Object.entries(nsLayer)) { if (typeof entry === "function") { // Async functions need to be wrapped. See JS-Interpreter documentation @@ -121,21 +86,11 @@ function startNetscript1Script(workerScript: WorkerScript): Promise { const result = await entry(...args.map((arg) => int.pseudoToNative(arg))); return callback(int.nativeToPseudo(result)); } catch (e: unknown) { - // TODO: Unify error handling, this was stolen from previous async handler - if (typeof e === "string") { - console.error(e); - const errorTextArray = e.split("|DELIMITER|"); - const hostname = errorTextArray[1]; - const scriptName = errorTextArray[2]; - const errorMsg = errorTextArray[3]; - let msg = `${scriptName}@${hostname}
`; - msg += "
"; - msg += errorMsg; - dialogBoxCreate(msg); - workerScript.env.stopFlag = true; - killWorkerScript(workerScript); - return; - } + // NS1 interpreter doesn't cleanly handle throwing. Need to show dialog here. + errorDialog(e, `RUNTIME ERROR:\n${workerScript.name}@${workerScript.hostname}\n\n`); + workerScript.env.stopFlag = true; + killWorkerScript(workerScript); + return; } }; int.setProperty(intLayer, name, int.createAsyncFunction(wrapper)); @@ -145,7 +100,7 @@ function startNetscript1Script(workerScript: WorkerScript): Promise { } else { // new object layer, e.g. bladeburner int.setProperty(intLayer, name, int.nativeToPseudo({})); - wrapNS1Layer(int, (intLayer as BasicObject).properties[name], [...path, name]); + wrapNS1Layer(int, (intLayer as BasicObject).properties[name], nsLayer[name]); } } } @@ -154,54 +109,30 @@ function startNetscript1Script(workerScript: WorkerScript): Promise { try { interpreter = new Interpreter(codeWithImports, wrapNS1Layer, codeLineOffset); } catch (e: unknown) { - dialogBoxCreate("Syntax ERROR in " + workerScript.name + ":
" + String(e)); + dialogBoxCreate(`Syntax ERROR in ${workerScript.name} on ${workerScript.hostname}:\n\n${String(e)}`); workerScript.env.stopFlag = true; killWorkerScript(workerScript); return Promise.resolve(); } - return new Promise(function (resolve, reject) { + return new Promise((resolve) => { function runInterpreter(): void { - try { - if (workerScript.env.stopFlag) { - return reject(new ScriptDeath(workerScript)); - } + if (workerScript.env.stopFlag) resolve(); - let more = true; - let i = 0; - while (i < 3 && more) { - more = more && interpreter.step(); - i++; - } - - if (more) { - setTimeout(runInterpreter, Settings.CodeInstructionRunTime); - } else { - resolve(); - } - } catch (_e: unknown) { - let e = String(_e); - if (!helpers.isScriptErrorMessage(e)) { - e = helpers.makeRuntimeRejectMsg(workerScript, e); - } - workerScript.errorMessage = e; - return reject(new ScriptDeath(workerScript)); + let more = true; + let i = 0; + while (i < 3 && more) { + more = more && interpreter.step(); + i++; } - } - try { - runInterpreter(); - } catch (e: unknown) { - if (isString(e)) { - workerScript.errorMessage = e; - return reject(new ScriptDeath(workerScript)); - } else if (e instanceof ScriptDeath) { - return reject(e); + if (more) { + setTimeout(runInterpreter, Settings.CodeInstructionRunTime); } else { - console.error(e); - return reject(new ScriptDeath(workerScript)); + resolve(); } } + runInterpreter(); }); } @@ -430,58 +361,19 @@ function createAndAddWorkerScript(runningScriptObj: RunningScript, server: BaseS // running status to false scriptExecution .then(function () { - workerScript.env.stopFlag = true; // On natural death, the earnings are transfered to the parent if it still exists. - if (parent !== undefined && !parent.env.stopFlag) { + if (parent && !parent.env.stopFlag) { parent.scriptRef.onlineExpGained += runningScriptObj.onlineExpGained; parent.scriptRef.onlineMoneyMade += runningScriptObj.onlineMoneyMade; } - killWorkerScript(workerScript); workerScript.log("", () => "Script finished running"); }) .catch(function (e) { - if (e instanceof Error) { - dialogBoxCreate("Script runtime unknown error. This is a bug please contact game developer"); - console.error("Evaluating workerscript returns an Error. THIS SHOULDN'T HAPPEN: " + e.toString()); - return; - } else if (e instanceof ScriptDeath) { - if (helpers.isScriptErrorMessage(workerScript.errorMessage)) { - const errorTextArray = workerScript.errorMessage.split("|DELIMITER|"); - if (errorTextArray.length != 4) { - console.error("ERROR: Something wrong with Error text in evaluator..."); - console.error("Error text: " + workerScript.errorMessage); - return; - } - const hostname = errorTextArray[1]; - const scriptName = errorTextArray[2]; - const errorMsg = errorTextArray[3]; - - let msg = `RUNTIME ERROR
${scriptName}@${hostname} (PID - ${workerScript.pid})
`; - if (workerScript.args.length > 0) { - msg += `Args: ${arrayToString(workerScript.args)}
`; - } - msg += "
"; - msg += errorMsg; - - dialogBoxCreate(msg); - workerScript.log("", () => "Script crashed with runtime error"); - } else { - workerScript.log("", () => "Script killed"); - return; // Already killed, so stop here - } - } else if (helpers.isScriptErrorMessage(e)) { - dialogBoxCreate("Script runtime unknown error. This is a bug please contact game developer"); - console.error( - "ERROR: Evaluating workerscript returns only error message rather than WorkerScript object. THIS SHOULDN'T HAPPEN: " + - e.toString(), - ); - return; - } else { - dialogBoxCreate("An unknown script died for an unknown reason. This is a bug please contact game dev"); - console.error(e); - } - + errorDialog(e, `RUNTIME ERROR\n${workerScript.name}@${workerScript.hostname} (PID - ${workerScript.pid})\n\n`); + let logText = "Script crashed due to an error."; + if (e instanceof ScriptDeath) logText = "Script killed."; + workerScript.log("", () => logText); killWorkerScript(workerScript); }); diff --git a/src/SaveObject.tsx b/src/SaveObject.tsx index b1cf7a872..451198ec1 100755 --- a/src/SaveObject.tsx +++ b/src/SaveObject.tsx @@ -27,7 +27,6 @@ import { AwardNFG, v1APIBreak } from "./utils/v1APIBreak"; import { AugmentationNames } from "./Augmentation/data/AugmentationNames"; import { PlayerOwnedAugmentation } from "./Augmentation/PlayerOwnedAugmentation"; import { LocationName } from "./Locations/data/LocationNames"; -import { SxProps } from "@mui/system"; import { PlayerObject } from "./PersonObjects/Player/PlayerObject"; import { pushGameSaved } from "./Electron"; import { defaultMonacoTheme } from "./ScriptEditor/ui/themes"; @@ -759,27 +758,14 @@ function createScamUpdateText(): void { } } -const resets: SxProps = { - "& h1, & h2, & h3, & h4, & p, & a, & ul": { - margin: 0, - color: Settings.theme.primary, - whiteSpace: "initial", - }, - "& ul": { - paddingLeft: "1.5em", - lineHeight: 1.5, - }, -}; - function createNewUpdateText(): void { setTimeout( () => dialogBoxCreate( - "New update!
" + + "New update!\n" + "Please report any bugs/issues through the GitHub repository " + - "or the Bitburner subreddit (reddit.com/r/bitburner).

" + + "or the Bitburner subreddit (reddit.com/r/bitburner).\n\n" + CONSTANTS.LatestUpdate, - resets, ), 1000, ); @@ -788,11 +774,10 @@ function createNewUpdateText(): void { function createBetaUpdateText(): void { dialogBoxCreate( "You are playing on the beta environment! This branch of the game " + - "features the latest developments in the game. This version may be unstable.
" + + "features the latest developments in the game. This version may be unstable.\n" + "Please report any bugs/issues through the github repository (https://github.com/danielyxie/bitburner/issues) " + - "or the Bitburner subreddit (reddit.com/r/bitburner).

" + + "or the Bitburner subreddit (reddit.com/r/bitburner).\n\n" + CONSTANTS.LatestUpdate, - resets, ); } diff --git a/src/Script/ScriptModule.ts b/src/Script/ScriptModule.ts index f5a3ee425..96da00616 100644 --- a/src/Script/ScriptModule.ts +++ b/src/Script/ScriptModule.ts @@ -1,6 +1,6 @@ import { AutocompleteData, NS } from "../ScriptEditor/NetscriptDefinitions"; export interface ScriptModule { - main?: (ns: NS) => Promise; + main?: (ns: NS) => unknown; autocomplete?: (data: AutocompleteData, flags: string[]) => unknown; } diff --git a/src/UncaughtPromiseHandler.ts b/src/UncaughtPromiseHandler.ts index e37404a33..a786c384a 100644 --- a/src/UncaughtPromiseHandler.ts +++ b/src/UncaughtPromiseHandler.ts @@ -1,24 +1,7 @@ -import { ScriptDeath } from "./Netscript/ScriptDeath"; -import { helpers } from "./Netscript/NetscriptHelpers"; -import { dialogBoxCreate } from "./ui/React/DialogBox"; +import { errorDialog } from "./ui/React/DialogBox"; export function setupUncaughtPromiseHandler(): void { - window.addEventListener("unhandledrejection", function (e) { - if (helpers.isScriptErrorMessage(e.reason)) { - const errorTextArray = e.reason.split("|DELIMITER|"); - const hostname = errorTextArray[1]; - const scriptName = errorTextArray[2]; - const errorMsg = errorTextArray[3]; - - let msg = `UNCAUGHT PROMISE ERROR
You forgot to await a promise
${scriptName}@${hostname}
`; - msg += "
"; - msg += errorMsg; - dialogBoxCreate(msg); - } else if (e.reason instanceof ScriptDeath) { - const msg = - `UNCAUGHT PROMISE ERROR
You forgot to await a promise
${e.reason.name}@${e.reason.hostname} (PID - ${e.reason.pid})
` + - `Maybe hack / grow / weaken ?`; - dialogBoxCreate(msg); - } - }); + window.addEventListener("unhandledrejection", (e) => + errorDialog(e.reason, "UNCAUGHT PROMISE ERROR\nYou forgot to await a promise\nmaybe hack / grow / weaken ?\n"), + ); } diff --git a/src/ui/React/DialogBox.tsx b/src/ui/React/DialogBox.tsx index 9ae8035f6..f4fe5216d 100644 --- a/src/ui/React/DialogBox.tsx +++ b/src/ui/React/DialogBox.tsx @@ -1,13 +1,29 @@ import { AlertEvents } from "./AlertManager"; import React from "react"; -import { SxProps } from "@mui/system"; import { Typography } from "@mui/material"; +import { ScriptDeath } from "../../Netscript/ScriptDeath"; -export function dialogBoxCreate(txt: string | JSX.Element, styles?: SxProps): void { - if (typeof txt !== "string") { - AlertEvents.emit(txt); - } else { - AlertEvents.emit(); - } +export function dialogBoxCreate(txt: string | JSX.Element): void { + AlertEvents.emit(typeof txt === "string" ? {txt} : txt); +} + +export function errorDialog(e: unknown, initialText = "") { + let errorText = ""; + if (typeof e === "string") errorText = e; + else if (e instanceof ScriptDeath) { + if (!e.errorMessage) return; //No need for a dialog for an empty ScriptDeath + errorText = e.errorMessage; + } else if (e instanceof SyntaxError) errorText = e.message + " (sorry we can't be more helpful)"; + else if (e instanceof Error) errorText = e.message + (e.stack ? `\nstack:\n${e.stack.toString()}` : ""); + else { + errorText = "An unknown error was thrown, see console."; + console.error(e); + } + + if (!initialText) { + if (e instanceof ScriptDeath) initialText = `${e.name}@${e.hostname} (PID - ${e.pid})\n\n`; + } + + dialogBoxCreate(initialText + errorText); } From 572c68738fb9aa6545308e16ae46974a4ca04e2f Mon Sep 17 00:00:00 2001 From: Snarling <84951833+Snarling@users.noreply.github.com> Date: Mon, 29 Aug 2022 02:41:17 -0400 Subject: [PATCH 02/46] Unify error handling --- src/Electron.tsx | 2 +- src/Hacknet/HacknetServer.ts | 8 +- src/Netscript/APIWrapper.ts | 3 +- src/Netscript/NetscriptHelpers.ts | 53 ++++----- src/Netscript/RamCostGenerator.ts | 17 ++- src/Netscript/killWorkerScript.ts | 5 +- src/NetscriptFunctions.ts | 28 +++-- src/NetscriptJSEvaluator.ts | 51 +-------- src/NetscriptWorker.ts | 105 +++++++----------- src/RemoteFileAPI/MessageHandlers.ts | 3 +- src/Script/RamCalculations.ts | 18 ++- src/Script/Script.ts | 15 ++- src/ScriptEditor/ui/ScriptEditorRoot.tsx | 20 +--- src/Server/BaseServer.ts | 9 +- src/Server/ServerHelpers.ts | 2 +- src/Terminal/commands/cp.ts | 2 +- src/Terminal/commands/scp.ts | 2 +- src/Terminal/commands/wget.ts | 2 +- ...termineAllPossibilitiesForTabCompletion.ts | 2 +- src/ui/GameRoot.tsx | 52 ++++----- src/ui/LoadingScreen.tsx | 4 +- src/ui/React/DialogBox.tsx | 6 +- src/utils/v1APIBreak.ts | 2 +- 23 files changed, 156 insertions(+), 255 deletions(-) diff --git a/src/Electron.tsx b/src/Electron.tsx index 32e1ad552..a07621afc 100644 --- a/src/Electron.tsx +++ b/src/Electron.tsx @@ -106,7 +106,7 @@ function initWebserver(): void { msg: "Home server does not exist.", }; } - const { success, overwritten } = home.writeToScriptFile(Player, filename, code); + const { success, overwritten } = home.writeToScriptFile(filename, code); let script; if (success) { script = home.getScript(filename); diff --git a/src/Hacknet/HacknetServer.ts b/src/Hacknet/HacknetServer.ts index 1de09e52d..e2b005dd5 100644 --- a/src/Hacknet/HacknetServer.ts +++ b/src/Hacknet/HacknetServer.ts @@ -19,7 +19,7 @@ import { import { createRandomIp } from "../utils/IPAddress"; import { Generic_fromJSON, Generic_toJSON, IReviverValue, Reviver } from "../utils/JSONReviver"; -import { IPlayer } from "../PersonObjects/IPlayer"; +import { Player } from "../Player"; interface IConstructorParams { adminRights?: boolean; @@ -123,9 +123,9 @@ export class HacknetServer extends BaseServer implements IHacknetNode { } } - updateRamUsed(ram: number, player: IPlayer): void { - super.updateRamUsed(ram, player); - this.updateHashRate(player.mults.hacknet_node_money); + updateRamUsed(ram: number): void { + super.updateRamUsed(ram); + this.updateHashRate(Player.mults.hacknet_node_money); } updateHashCapacity(): void { diff --git a/src/Netscript/APIWrapper.ts b/src/Netscript/APIWrapper.ts index 0bd5817d4..22b30ab23 100644 --- a/src/Netscript/APIWrapper.ts +++ b/src/Netscript/APIWrapper.ts @@ -1,6 +1,5 @@ import { getRamCost } from "./RamCostGenerator"; import type { WorkerScript } from "./WorkerScript"; -import { Player } from "../Player"; import { helpers } from "./NetscriptHelpers"; import { ScriptArg } from "./ScriptArg"; import { NSEnums } from "src/ScriptEditor/NetscriptDefinitions"; @@ -50,7 +49,7 @@ function wrapFunction( }; function wrappedFunction(...args: unknown[]): unknown { helpers.checkEnvFlags(ctx); - helpers.updateDynamicRam(ctx, getRamCost(Player, ...tree, ctx.function)); + helpers.updateDynamicRam(ctx, getRamCost(...tree, ctx.function)); return func(ctx)(...args); } const parent = getNestedProperty(wrappedAPI, tree); diff --git a/src/Netscript/NetscriptHelpers.ts b/src/Netscript/NetscriptHelpers.ts index 0ca89db76..9655f941a 100644 --- a/src/Netscript/NetscriptHelpers.ts +++ b/src/Netscript/NetscriptHelpers.ts @@ -57,7 +57,6 @@ export const helpers = { gangMember, gangTask, log, - getFunctionNames, getRunningScript, getRunningScriptByArgs, getCannotFindRunningScriptErrorMessage, @@ -205,8 +204,8 @@ function makeRuntimeErrorMsg(ctx: NetscriptContext, msg: string): string { } log(ctx, () => msg); - let rejectMsg = `${caller}: ${msg}`; - if (userstack.length !== 0) rejectMsg += `

Stack:
${userstack.join("
")}`; + let rejectMsg = `RUNTIME ERROR\n${ws.name}@${ws.hostname} (PID - ${ws.pid})\n\n${caller}: ${msg}`; + if (userstack.length !== 0) rejectMsg += `\n\nStack:\n${userstack.join("\n")}`; return makeBasicErrorMsg(ws, rejectMsg); } @@ -253,14 +252,15 @@ function checkEnvFlags(ctx: NetscriptContext): void { if (ws.env.runningFn && ctx.function !== "asleep") { //This one has no error message so it will not create a dialog if (ws.delayReject) ws.delayReject(new ScriptDeath(ws)); - ws.errorMessage = makeBasicErrorMsg( - ws, + ws.env.stopFlag = true; + log(ctx, () => "Failed to run due to failed concurrency check."); + throw makeRuntimeErrorMsg( + ctx, `Concurrent calls to Netscript functions are not allowed! Did you forget to await hack(), grow(), or some other promise-returning function? Currently running: ${ws.env.runningFn} tried to run: ${ctx.function}`, ); - throw new ScriptDeath(ws); } } @@ -295,9 +295,10 @@ function updateDynamicRam(ctx: NetscriptContext, ramCost: number): void { ws.dynamicRamUsage += ramCost; if (ws.dynamicRamUsage > 1.01 * ws.ramUsage) { log(ctx, () => "Insufficient static ram available."); - ws.errorMessage = makeBasicErrorMsg( - ws, - `Dynamic RAM usage calculated to be greater than initial RAM usage on fn: ${fnName}. + ws.env.stopFlag = true; + throw makeRuntimeErrorMsg( + ctx, + `Dynamic RAM usage calculated to be greater than initial RAM usage. This is probably because you somehow circumvented the static RAM calculation. Threads: ${threads} @@ -306,14 +307,13 @@ function updateDynamicRam(ctx: NetscriptContext, ramCost: number): void { One of these could be the reason: * Using eval() to get a reference to a ns function -   const myScan = eval('ns.scan'); + \u00a0\u00a0const myScan = eval('ns.scan'); * Using map access to do the same -   const myScan = ns['scan']; + \u00a0\u00a0const myScan = ns['scan']; Sorry :(`, ); - throw new ScriptDeath(ws); } } @@ -368,7 +368,7 @@ function isScriptArgs(args: unknown): args is ScriptArg[] { return Array.isArray(args) && args.every(isScriptArg); } -async function hack( +function hack( ctx: NetscriptContext, hostname: string, manual: boolean, @@ -454,7 +454,7 @@ async function hack( if (manual) { server.backdoorInstalled = true; } - return Promise.resolve(moneyGained); + return moneyGained; } else { // Player only gains 25% exp for failure? Player.gainHackingExp(expGainedOnFailure); @@ -466,7 +466,7 @@ async function hack( expGainedOnFailure, )} exp (t=${numeralWrapper.formatThreads(threads)})`, ); - return Promise.resolve(0); + return 0; } }); } @@ -598,10 +598,10 @@ function getRunningScriptByArgs( scriptArgs: ScriptArg[], ): RunningScript | null { if (!Array.isArray(scriptArgs)) { - throw helpers.makeBasicErrorMsg( - ctx.workerScript, - `Invalid scriptArgs argument passed into getRunningScript() from ${ctx.function}(). ` + - `This is probably a bug. Please report to game developer`, + throw helpers.makeRuntimeErrorMsg( + ctx, + "Invalid scriptArgs argument passed into getRunningScriptByArgs().\n" + + "This is probably a bug. Please report to game developer", ); } @@ -619,21 +619,6 @@ function getRunningScriptByArgs( return ctx.workerScript.scriptRef; } -/** Provides an array of all function names on a nested object */ -function getFunctionNames(obj: object, prefix: string): string[] { - const functionNames: string[] = []; - for (const [key, value] of Object.entries(obj)) { - if (key === "args") { - continue; - } else if (typeof value == "function") { - functionNames.push(prefix + key); - } else if (typeof value == "object") { - functionNames.push(...getFunctionNames(value, key + ".")); - } - } - return functionNames; -} - function getRunningScriptByPid(pid: number): RunningScript | null { for (const server of GetAllServers()) { const runningScript = findRunningScriptByPid(pid, server); diff --git a/src/Netscript/RamCostGenerator.ts b/src/Netscript/RamCostGenerator.ts index 28213d49a..c6b04629f 100644 --- a/src/Netscript/RamCostGenerator.ts +++ b/src/Netscript/RamCostGenerator.ts @@ -1,13 +1,12 @@ -import { IPlayer } from "src/PersonObjects/IPlayer"; +import { Player } from "../Player"; import { IMap } from "../types"; import { NS as INS } from "../ScriptEditor/NetscriptDefinitions"; - import { INetscriptExtra } from "../NetscriptFunctions/Extra"; type RamCostTree = { [Property in keyof API]: API[Property] extends () => void - ? number | ((p: IPlayer) => void) + ? number | (() => void) : API[Property] extends object ? RamCostTree : never; @@ -89,10 +88,10 @@ export const RamCostConstants: IMap = { ScriptStanekAcceptGift: 2, }; -function SF4Cost(cost: number): (player: IPlayer) => number { - return (player: IPlayer): number => { - if (player.bitNodeN === 4) return cost; - const sf4 = player.sourceFileLvl(4); +function SF4Cost(cost: number): () => number { + return () => { + if (Player.bitNodeN === 4) return cost; + const sf4 = Player.sourceFileLvl(4); if (sf4 <= 1) return cost * 16; if (sf4 === 2) return cost * 4; return cost; @@ -611,7 +610,7 @@ export const RamCosts: IMap = SourceRamCosts; // eslint-disable-next-line @typescript-eslint/no-unused-vars const _typecheck: RamCostTree = SourceRamCosts; -export function getRamCost(player: IPlayer, ...args: string[]): number { +export function getRamCost(...args: string[]): number { if (args.length === 0) { console.warn(`No arguments passed to getRamCost()`); return 0; @@ -637,7 +636,7 @@ export function getRamCost(player: IPlayer, ...args: string[]): number { } if (typeof curr === "function") { - return curr(player); + return curr(); } console.warn(`Unexpected type (${curr}) for value [${args}]`); diff --git a/src/Netscript/killWorkerScript.ts b/src/Netscript/killWorkerScript.ts index f41e179c0..c70455124 100644 --- a/src/Netscript/killWorkerScript.ts +++ b/src/Netscript/killWorkerScript.ts @@ -12,7 +12,6 @@ import { GetServer } from "../Server/AllServers"; import { errorDialog } from "../ui/React/DialogBox"; import { AddRecentScript } from "./RecentScripts"; -import { Player } from "../Player"; import { ITutorial } from "../InteractiveTutorial"; import { AlertEvents } from "../ui/React/AlertManager"; @@ -102,8 +101,8 @@ function removeWorkerScript(workerScript: WorkerScript): void { // Recalculate ram used on that server - server.updateRamUsed(0, Player); - for (const rs of server.runningScripts) server.updateRamUsed(server.ramUsed + rs.ramUsage * rs.threads, Player); + server.updateRamUsed(0); + for (const rs of server.runningScripts) server.updateRamUsed(server.ramUsed + rs.ramUsage * rs.threads); // Delete script from global pool (workerScripts) workerScripts.delete(workerScript.pid); diff --git a/src/NetscriptFunctions.ts b/src/NetscriptFunctions.ts index db76cbbbb..51a54c3c0 100644 --- a/src/NetscriptFunctions.ts +++ b/src/NetscriptFunctions.ts @@ -931,13 +931,13 @@ const base: InternalAPI = { } // Create new script if it does not already exist - const newScript = new Script(Player, file); + const newScript = new Script(file); newScript.code = sourceScript.code; newScript.ramUsage = sourceScript.ramUsage; newScript.server = destServer.hostname; destServer.scripts.push(newScript); helpers.log(ctx, () => `File '${file}' copied over to '${destServer?.hostname}'.`); - newScript.updateRamUsage(Player, destServer.scripts); + newScript.updateRamUsage(destServer.scripts); } return noFailures; @@ -1492,12 +1492,12 @@ const base: InternalAPI = { let script = ctx.workerScript.getScriptOnServer(fn, server); if (script == null) { // Create a new script - script = new Script(Player, fn, String(data), server.hostname, server.scripts); + script = new Script(fn, String(data), server.hostname, server.scripts); server.scripts.push(script); - return script.updateRamUsage(Player, server.scripts); + return script.updateRamUsage(server.scripts); } mode === "w" ? (script.code = String(data)) : (script.code += data); - return script.updateRamUsage(Player, server.scripts); + return script.updateRamUsage(server.scripts); } else { // Write to text file if (!fn.endsWith(".txt")) throw helpers.makeRuntimeErrorMsg(ctx, `Invalid filename: ${fn}`); @@ -1820,7 +1820,7 @@ const base: InternalAPI = { function (data) { let res; if (isScriptFilename(target)) { - res = s.writeToScriptFile(Player, target, data); + res = s.writeToScriptFile(target, data); } else { res = s.writeToTextFile(target, data); } @@ -1950,4 +1950,18 @@ const ns = { ...NetscriptExtra(), }; -const possibleLogs = Object.fromEntries([...helpers.getFunctionNames(ns, "")].map((a) => [a, true])); +const possibleLogs = Object.fromEntries([...getFunctionNames(ns, "")].map((a) => [a, true])); +/** Provides an array of all function names on a nested object */ +function getFunctionNames(obj: object, prefix: string): string[] { + const functionNames: string[] = []; + for (const [key, value] of Object.entries(obj)) { + if (key === "args") { + continue; + } else if (typeof value == "function") { + functionNames.push(prefix + key); + } else if (typeof value == "object") { + functionNames.push(...getFunctionNames(value, key + ".")); + } + } + return functionNames; +} diff --git a/src/NetscriptJSEvaluator.ts b/src/NetscriptJSEvaluator.ts index 9b384fe65..6cb28b16f 100644 --- a/src/NetscriptJSEvaluator.ts +++ b/src/NetscriptJSEvaluator.ts @@ -5,12 +5,9 @@ import * as walk from "acorn-walk"; import { parse } from "acorn"; -import { helpers } from "./Netscript/NetscriptHelpers"; import { ScriptUrl } from "./Script/ScriptUrl"; -import { WorkerScript } from "./Netscript/WorkerScript"; import { Script } from "./Script/Script"; import { areImportsEquals } from "./Terminal/DirectoryHelpers"; -import { IPlayer } from "./PersonObjects/IPlayer"; import { ScriptModule } from "./Script/ScriptModule"; // Acorn type def is straight up incomplete so we have to fill with our own. @@ -21,7 +18,7 @@ function makeScriptBlob(code: string): Blob { return new Blob([code], { type: "text/javascript" }); } -export async function compile(player: IPlayer, script: Script, scripts: Script[]): Promise { +export async function compile(script: Script, scripts: Script[]): Promise { //!shouldCompile ensures that script.module is non-null, hence the "as". if (!shouldCompile(script, scripts)) return script.module as Promise; script.queueCompile = true; @@ -31,7 +28,7 @@ export async function compile(player: IPlayer, script: Script, scripts: Script[] //If multiple compiles were called on the same script before a compilation could be completed this ensures only one complilation is actually performed. if (!script.queueCompile) return script.module as Promise; script.queueCompile = false; - script.updateRamUsage(player, scripts); + script.updateRamUsage(scripts); const uurls = _getScriptUrls(script, scripts, []); const url = uurls[uurls.length - 1].url; if (script.url && script.url !== url) URL.revokeObjectURL(script.url); @@ -50,50 +47,6 @@ export async function compile(player: IPlayer, script: Script, scripts: Script[] return script.module; } -// Begin executing a user JS script, and return a promise that resolves -// or rejects when the script finishes. -// - script is a script to execute (see Script.js). We depend only on .filename and .code. -// scripts is an array of other scripts on the server. -// env is the global environment that should be visible to all the scripts -// (i.e. hack, grow, etc.). -// When the promise returned by this resolves, we'll have finished -// running the main function of the script. -export async function executeJSScript( - player: IPlayer, - scripts: Script[] = [], - workerScript: WorkerScript, -): Promise { - const script = workerScript.getScript(); - if (script === null) throw new Error("script is null"); - const loadedModule = await compile(player, script, scripts); - workerScript.ramUsage = script.ramUsage; - - const ns = workerScript.env.vars; - - if (!loadedModule) { - throw helpers.makeBasicErrorMsg( - workerScript, - `${script.filename} cannot be run because the script module won't load`, - ); - } - // TODO: putting await in a non-async function yields unhelpful - // "SyntaxError: unexpected reserved word" with no line number information. - if (!loadedModule.main) { - throw helpers.makeBasicErrorMsg( - workerScript, - `${script.filename} cannot be run because it does not have a main function.`, - ); - } - if (!ns) { - throw helpers.makeBasicErrorMsg( - workerScript, - `${script.filename} cannot be run because the NS object hasn't been constructed properly.`, - ); - } - await loadedModule.main(ns); - return; -} - function isDependencyOutOfDate(filename: string, scripts: Script[], scriptModuleSequenceNumber: number): boolean { const depScript = scripts.find((s) => s.filename == filename); diff --git a/src/NetscriptWorker.ts b/src/NetscriptWorker.ts index 1d05043aa..22c63fad6 100644 --- a/src/NetscriptWorker.ts +++ b/src/NetscriptWorker.ts @@ -12,7 +12,7 @@ import { generateNextPid } from "./Netscript/Pid"; import { CONSTANTS } from "./Constants"; import { Interpreter } from "./ThirdParty/JSInterpreter"; import { NetscriptFunctions } from "./NetscriptFunctions"; -import { executeJSScript, Node } from "./NetscriptJSEvaluator"; +import { compile, Node } from "./NetscriptJSEvaluator"; import { IPort } from "./NetscriptPort"; import { RunningScript } from "./Script/RunningScript"; import { getRamUsageFromRunningScript } from "./Script/RunningScriptHelpers"; @@ -31,7 +31,6 @@ import { roundToTwo } from "./utils/helpers/roundToTwo"; import { parse } from "acorn"; import { simple as walksimple } from "acorn-walk"; import { areFilesEqual } from "./Terminal/DirectoryHelpers"; -import { Player } from "./Player"; import { Terminal } from "./Terminal"; import { ScriptArg } from "./Netscript/ScriptArg"; @@ -49,14 +48,26 @@ export function prestigeWorkerScripts(): void { workerScripts.clear(); } -// JS script promises need a little massaging to have the same guarantees as netscript -// promises. This does said massaging and kicks the script off. It returns a promise -// that resolves or rejects when the corresponding worker script is done. -const startNetscript2Script = (workerScript: WorkerScript): Promise => - executeJSScript(Player, workerScript.getServer().scripts, workerScript); +async function startNetscript2Script(workerScript: WorkerScript): Promise { + const scripts = workerScript.getServer().scripts; + const script = workerScript.getScript(); + if (script === null) throw "workerScript had no associated script. This is a bug."; + const loadedModule = await compile(script, scripts); + workerScript.ramUsage = script.ramUsage; + const ns = workerScript.env.vars; -function startNetscript1Script(workerScript: WorkerScript): Promise { + if (!loadedModule) throw `${script.filename} cannot be run because the script module won't load`; + // TODO: Better error for "unexpected reserved word" when using await in non-async function? + if (typeof loadedModule.main !== "function") + throw `${script.filename} cannot be run because it does not have a main function.`; + if (!ns) throw `${script.filename} cannot be run because the NS object hasn't been constructed properly.`; + await loadedModule.main(ns); + return; +} + +async function startNetscript1Script(workerScript: WorkerScript): Promise { const code = workerScript.code; + let errorToThrow: unknown; //Process imports let codeWithImports, codeLineOffset; @@ -65,10 +76,7 @@ function startNetscript1Script(workerScript: WorkerScript): Promise { codeWithImports = importProcessingRes.code; codeLineOffset = importProcessingRes.lineOffset; } catch (e: unknown) { - dialogBoxCreate(`Error processing Imports in ${workerScript.name} on ${workerScript.hostname}:\n\n${e}`); - workerScript.env.stopFlag = true; - killWorkerScript(workerScript); - return Promise.resolve(); + throw `Error processing Imports in ${workerScript.name}@${workerScript.hostname}:\n\n${e}`; } interface BasicObject { @@ -77,20 +85,14 @@ function startNetscript1Script(workerScript: WorkerScript): Promise { function wrapNS1Layer(int: Interpreter, intLayer: unknown, nsLayer = workerScript.env.vars as BasicObject) { for (const [name, entry] of Object.entries(nsLayer)) { if (typeof entry === "function") { - // Async functions need to be wrapped. See JS-Interpreter documentation const wrapper = async (...args: unknown[]) => { - // This async wrapper is sent a resolver function as an extra arg. - // See JSInterpreter.js:3209 try { + // Sent a resolver function as an extra arg. See createAsyncFunction JSInterpreter.js:3209 const callback = args.pop() as (value: unknown) => void; const result = await entry(...args.map((arg) => int.pseudoToNative(arg))); return callback(int.nativeToPseudo(result)); } catch (e: unknown) { - // NS1 interpreter doesn't cleanly handle throwing. Need to show dialog here. - errorDialog(e, `RUNTIME ERROR:\n${workerScript.name}@${workerScript.hostname}\n\n`); - workerScript.env.stopFlag = true; - killWorkerScript(workerScript); - return; + errorToThrow = e; } }; int.setProperty(intLayer, name, int.createAsyncFunction(wrapper)); @@ -109,31 +111,16 @@ function startNetscript1Script(workerScript: WorkerScript): Promise { try { interpreter = new Interpreter(codeWithImports, wrapNS1Layer, codeLineOffset); } catch (e: unknown) { - dialogBoxCreate(`Syntax ERROR in ${workerScript.name} on ${workerScript.hostname}:\n\n${String(e)}`); - workerScript.env.stopFlag = true; - killWorkerScript(workerScript); - return Promise.resolve(); + throw `Syntax ERROR in ${workerScript.name}@${workerScript.hostname}:\n\n${String(e)}`; } - return new Promise((resolve) => { - function runInterpreter(): void { - if (workerScript.env.stopFlag) resolve(); - - let more = true; - let i = 0; - while (i < 3 && more) { - more = more && interpreter.step(); - i++; - } - - if (more) { - setTimeout(runInterpreter, Settings.CodeInstructionRunTime); - } else { - resolve(); - } - } - runInterpreter(); - }); + let more = true; + while (more) { + if (errorToThrow) throw errorToThrow; + if (workerScript.env.stopFlag) return; + for (let i = 0; more && i < 3; i++) more = interpreter.step(); + if (more) await new Promise((r) => setTimeout(r, Settings.CodeInstructionRunTime)); + } } /* Since the JS Interpreter used for Netscript 1.0 only supports ES5, the keyword @@ -326,7 +313,7 @@ function createAndAddWorkerScript(runningScriptObj: RunningScript, server: BaseS return false; } - server.updateRamUsed(roundToTwo(server.ramUsed + ramUsage), Player); + server.updateRamUsed(roundToTwo(server.ramUsed + ramUsage)); // Get the pid const pid = generateNextPid(); @@ -346,20 +333,10 @@ function createAndAddWorkerScript(runningScriptObj: RunningScript, server: BaseS workerScripts.set(pid, workerScript); WorkerScriptStartStopEventEmitter.emit(); - // Start the script's execution - let scriptExecution: Promise | null = null; // Script's resulting promise - if (workerScript.name.endsWith(".js")) { - scriptExecution = startNetscript2Script(workerScript); - } else { - scriptExecution = startNetscript1Script(workerScript); - if (!(scriptExecution instanceof Promise)) { - return false; - } - } - - // Once the code finishes (either resolved or rejected, doesnt matter), set its - // running status to false - scriptExecution + // Start the script's execution using the correct function for file type + (workerScript.name.endsWith(".js") ? startNetscript2Script : startNetscript1Script)(workerScript) + // Once the code finishes (either resolved or rejected, doesnt matter), set its + // running status to false .then(function () { // On natural death, the earnings are transfered to the parent if it still exists. if (parent && !parent.env.stopFlag) { @@ -370,13 +347,15 @@ function createAndAddWorkerScript(runningScriptObj: RunningScript, server: BaseS workerScript.log("", () => "Script finished running"); }) .catch(function (e) { - errorDialog(e, `RUNTIME ERROR\n${workerScript.name}@${workerScript.hostname} (PID - ${workerScript.pid})\n\n`); - let logText = "Script crashed due to an error."; - if (e instanceof ScriptDeath) logText = "Script killed."; - workerScript.log("", () => logText); + let initialText = `ERROR\n${workerScript.name}@${workerScript.hostname} (PID - ${workerScript.pid})\n\n`; + if (e instanceof SyntaxError) e = `SYNTAX ${initialText}${e.message} (sorry we can't be more helpful)`; + else if (e instanceof Error) { + e = `RUNTIME ${initialText}${e.message}${e.stack ? `\nstack:\n${e.stack.toString()}` : ""}`; + } + errorDialog(e, typeof e === "string" && e.includes(initialText) ? "" : initialText); + workerScript.log("", () => (e instanceof ScriptDeath ? "Script killed." : "Script crashed due to an error.")); killWorkerScript(workerScript); }); - return true; } diff --git a/src/RemoteFileAPI/MessageHandlers.ts b/src/RemoteFileAPI/MessageHandlers.ts index a9e3dc3fc..d527d0198 100644 --- a/src/RemoteFileAPI/MessageHandlers.ts +++ b/src/RemoteFileAPI/MessageHandlers.ts @@ -1,4 +1,3 @@ -import { Player } from "../Player"; import { isScriptFilename } from "../Script/isScriptFilename"; import { GetServer } from "../Server/AllServers"; import { isValidFilePath } from "../Terminal/DirectoryHelpers"; @@ -29,7 +28,7 @@ export const RFARequestHandler: Record void | R const server = GetServer(fileData.server); if (!server) return error("Server hostname invalid", msg); - if (isScriptFilename(fileData.filename)) server.writeToScriptFile(Player, fileData.filename, fileData.content); + if (isScriptFilename(fileData.filename)) server.writeToScriptFile(fileData.filename, fileData.content); // Assume it's a text file else server.writeToTextFile(fileData.filename, fileData.content); diff --git a/src/Script/RamCalculations.ts b/src/Script/RamCalculations.ts index 61538bf4b..aae7dcf17 100644 --- a/src/Script/RamCalculations.ts +++ b/src/Script/RamCalculations.ts @@ -13,7 +13,6 @@ import { RamCalculationErrorCode } from "./RamCalculationErrorCodes"; import { RamCosts, RamCostConstants } from "../Netscript/RamCostGenerator"; import { Script } from "./Script"; import { areImportsEquals } from "../Terminal/DirectoryHelpers"; -import { IPlayer } from "../PersonObjects/IPlayer"; import { Node } from "../NetscriptJSEvaluator"; export interface RamUsageEntry { @@ -40,11 +39,8 @@ const memCheckGlobalKey = ".__GLOBAL__"; * Parses code into an AST and walks through it recursively to calculate * RAM usage. Also accounts for imported modules. * @param {Script[]} otherScripts - All other scripts on the server. Used to account for imported scripts - * @param {string} codeCopy - The code being parsed - * @param {WorkerScript} workerScript - Object containing RAM costs of Netscript functions. Also used to - * keep track of what functions have/havent been accounted for - */ -function parseOnlyRamCalculate(player: IPlayer, otherScripts: Script[], code: string): RamCalculation { + * @param {string} code - The code being parsed */ +function parseOnlyRamCalculate(otherScripts: Script[], code: string): RamCalculation { try { /** * Maps dependent identifiers to their dependencies. @@ -157,11 +153,11 @@ function parseOnlyRamCalculate(player: IPlayer, otherScripts: Script[], code: st // Check if this identifier is a function in the workerScript environment. // If it is, then we need to get its RAM cost. try { - function applyFuncRam(cost: number | ((p: IPlayer) => number)): number { + function applyFuncRam(cost: number | (() => number)): number { if (typeof cost === "number") { return cost; } else if (typeof cost === "function") { - return cost(player); + return cost(); } else { return 0; } @@ -178,7 +174,7 @@ function parseOnlyRamCalculate(player: IPlayer, otherScripts: Script[], code: st prefix: string, obj: object, ref: string, - ): { func: (p: IPlayer) => number | number; refDetail: string } | undefined => { + ): { func: () => number | number; refDetail: string } | undefined => { if (!obj) return; const elem = Object.entries(obj).find(([key]) => key === ref); if (elem !== undefined && (typeof elem[1] === "function" || typeof elem[1] === "number")) { @@ -381,9 +377,9 @@ function parseOnlyCalculateDeps(code: string, currentModule: string): ParseDepsR * @param {Script[]} otherScripts - All other scripts on the server. * Used to account for imported scripts */ -export function calculateRamUsage(player: IPlayer, codeCopy: string, otherScripts: Script[]): RamCalculation { +export function calculateRamUsage(codeCopy: string, otherScripts: Script[]): RamCalculation { try { - return parseOnlyRamCalculate(player, otherScripts, codeCopy); + return parseOnlyRamCalculate(otherScripts, codeCopy); } catch (e) { console.error(`Failed to parse script for RAM calculations:`); console.error(e); diff --git a/src/Script/Script.ts b/src/Script/Script.ts index e70c0433b..a28b81634 100644 --- a/src/Script/Script.ts +++ b/src/Script/Script.ts @@ -9,7 +9,6 @@ import { ScriptUrl } from "./ScriptUrl"; import { Generic_fromJSON, Generic_toJSON, IReviverValue, Reviver } from "../utils/JSONReviver"; import { roundToTwo } from "../utils/helpers/roundToTwo"; -import { IPlayer } from "../PersonObjects/IPlayer"; import { ScriptModule } from "./ScriptModule"; let globalModuleSequenceNumber = 0; @@ -52,13 +51,13 @@ export class Script { // hostname of server that this script is on. server = ""; - constructor(player: IPlayer | null = null, fn = "", code = "", server = "", otherScripts: Script[] = []) { + constructor(fn = "", code = "", server = "", otherScripts: Script[] = []) { this.filename = fn; this.code = code; this.server = server; // hostname of server this script is on this.moduleSequenceNumber = ++globalModuleSequenceNumber; - if (this.code !== "" && player !== null) { - this.updateRamUsage(player, otherScripts); + if (this.code !== "") { + this.updateRamUsage(otherScripts); } } @@ -94,13 +93,13 @@ export class Script { * @param {string} code - The new contents of the script * @param {Script[]} otherScripts - Other scripts on the server. Used to process imports */ - saveScript(player: IPlayer, filename: string, code: string, hostname: string, otherScripts: Script[]): void { + saveScript(filename: string, code: string, hostname: string, otherScripts: Script[]): void { // Update code and filename this.code = Script.formatCode(code); this.filename = filename; this.server = hostname; - this.updateRamUsage(player, otherScripts); + this.updateRamUsage(otherScripts); this.markUpdated(); for (const dependent of this.dependents) { const [dependentScript] = otherScripts.filter( @@ -114,8 +113,8 @@ export class Script { * Calculates and updates the script's RAM usage based on its code * @param {Script[]} otherScripts - Other scripts on the server. Used to process imports */ - updateRamUsage(player: IPlayer, otherScripts: Script[]): void { - const res = calculateRamUsage(player, this.code, otherScripts); + updateRamUsage(otherScripts: Script[]): void { + const res = calculateRamUsage(this.code, otherScripts); if (res.cost > 0) { this.ramUsage = roundToTwo(res.cost); this.ramUsageEntries = res.entries; diff --git a/src/ScriptEditor/ui/ScriptEditorRoot.tsx b/src/ScriptEditor/ui/ScriptEditorRoot.tsx index 3cb10e3bd..f6f46f21e 100644 --- a/src/ScriptEditor/ui/ScriptEditorRoot.tsx +++ b/src/ScriptEditor/ui/ScriptEditorRoot.tsx @@ -252,7 +252,7 @@ export function Root(props: IProps): React.ReactElement { return; } const codeCopy = newCode + ""; - const ramUsage = calculateRamUsage(props.player, codeCopy, props.player.getCurrentServer().scripts); + const ramUsage = calculateRamUsage(codeCopy, props.player.getCurrentServer().scripts); if (ramUsage.cost > 0) { const entries = ramUsage.entries?.sort((a, b) => b.cost - a.cost) ?? []; const entriesDisp = []; @@ -466,7 +466,6 @@ export function Root(props: IProps): React.ReactElement { for (let i = 0; i < server.scripts.length; i++) { if (scriptToSave.fileName == server.scripts[i].filename) { server.scripts[i].saveScript( - props.player, scriptToSave.fileName, scriptToSave.code, props.player.currentServer, @@ -480,13 +479,7 @@ export function Root(props: IProps): React.ReactElement { //If the current script does NOT exist, create a new one const script = new Script(); - script.saveScript( - props.player, - scriptToSave.fileName, - scriptToSave.code, - props.player.currentServer, - server.scripts, - ); + script.saveScript(scriptToSave.fileName, scriptToSave.code, props.player.currentServer, server.scripts); server.scripts.push(script); } else if (scriptToSave.isTxt) { for (let i = 0; i < server.textFiles.length; ++i) { @@ -555,7 +548,6 @@ export function Root(props: IProps): React.ReactElement { for (let i = 0; i < server.scripts.length; i++) { if (currentScript.fileName == server.scripts[i].filename) { server.scripts[i].saveScript( - props.player, currentScript.fileName, currentScript.code, props.player.currentServer, @@ -569,13 +561,7 @@ export function Root(props: IProps): React.ReactElement { //If the current script does NOT exist, create a new one const script = new Script(); - script.saveScript( - props.player, - currentScript.fileName, - currentScript.code, - props.player.currentServer, - server.scripts, - ); + script.saveScript(currentScript.fileName, currentScript.code, props.player.currentServer, server.scripts); server.scripts.push(script); } else if (currentScript.isTxt) { for (let i = 0; i < server.textFiles.length; ++i) { diff --git a/src/Server/BaseServer.ts b/src/Server/BaseServer.ts index 85b6e77fc..6e00e71fd 100644 --- a/src/Server/BaseServer.ts +++ b/src/Server/BaseServer.ts @@ -12,7 +12,6 @@ import { isScriptFilename } from "../Script/isScriptFilename"; import { createRandomIp } from "../utils/IPAddress"; import { compareArrays } from "../utils/helpers/compareArrays"; -import { IPlayer } from "../PersonObjects/IPlayer"; import { ScriptArg } from "../Netscript/ScriptArg"; interface IConstructorParams { @@ -245,7 +244,7 @@ export class BaseServer { } // eslint-disable-next-line @typescript-eslint/no-unused-vars - updateRamUsed(ram: number, player: IPlayer): void { + updateRamUsed(ram: number): void { this.ramUsed = ram; } @@ -266,7 +265,7 @@ export class BaseServer { * Write to a script file * Overwrites existing files. Creates new files if the script does not eixst */ - writeToScriptFile(player: IPlayer, fn: string, code: string): writeResult { + writeToScriptFile(fn: string, code: string): writeResult { const ret = { success: false, overwritten: false }; if (!isValidFilePath(fn) || !isScriptFilename(fn)) { return ret; @@ -277,7 +276,7 @@ export class BaseServer { if (fn === this.scripts[i].filename) { const script = this.scripts[i]; script.code = code; - script.updateRamUsage(player, this.scripts); + script.updateRamUsage(this.scripts); script.markUpdated(); ret.overwritten = true; ret.success = true; @@ -286,7 +285,7 @@ export class BaseServer { } // Otherwise, create a new script - const newScript = new Script(player, fn, code, this.hostname, this.scripts); + const newScript = new Script(fn, code, this.hostname, this.scripts); this.scripts.push(newScript); ret.success = true; return ret; diff --git a/src/Server/ServerHelpers.ts b/src/Server/ServerHelpers.ts index 5196f7261..979ec91a3 100644 --- a/src/Server/ServerHelpers.ts +++ b/src/Server/ServerHelpers.ts @@ -326,7 +326,7 @@ export function prestigeHomeComputer(player: IPlayer, homeComp: Server): void { //Update RAM usage on all scripts homeComp.scripts.forEach(function (script) { - script.updateRamUsage(player, homeComp.scripts); + script.updateRamUsage(homeComp.scripts); }); homeComp.messages.length = 0; //Remove .lit and .msg files diff --git a/src/Terminal/commands/cp.ts b/src/Terminal/commands/cp.ts index e33f6a9fd..021e9c60d 100644 --- a/src/Terminal/commands/cp.ts +++ b/src/Terminal/commands/cp.ts @@ -89,7 +89,7 @@ export function cp( return; } - const sRes = server.writeToScriptFile(player, dst, sourceScript.code); + const sRes = server.writeToScriptFile(dst, sourceScript.code); if (!sRes.success) { terminal.error(`cp failed`); return; diff --git a/src/Terminal/commands/scp.ts b/src/Terminal/commands/scp.ts index 89d87e74e..d5def4d68 100644 --- a/src/Terminal/commands/scp.ts +++ b/src/Terminal/commands/scp.ts @@ -94,7 +94,7 @@ export function scp( return; } - const sRes = destServer.writeToScriptFile(player, scriptname, sourceScript.code); + const sRes = destServer.writeToScriptFile(scriptname, sourceScript.code); if (!sRes.success) { terminal.error(`scp failed`); return; diff --git a/src/Terminal/commands/wget.ts b/src/Terminal/commands/wget.ts index d6eaf141d..77e3444bc 100644 --- a/src/Terminal/commands/wget.ts +++ b/src/Terminal/commands/wget.ts @@ -28,7 +28,7 @@ export function wget( function (data: unknown) { let res; if (isScriptFilename(target)) { - res = server.writeToScriptFile(player, target, String(data)); + res = server.writeToScriptFile(target, String(data)); } else { res = server.writeToTextFile(target, String(data)); } diff --git a/src/Terminal/determineAllPossibilitiesForTabCompletion.ts b/src/Terminal/determineAllPossibilitiesForTabCompletion.ts index 7355c7d1d..df32766a3 100644 --- a/src/Terminal/determineAllPossibilitiesForTabCompletion.ts +++ b/src/Terminal/determineAllPossibilitiesForTabCompletion.ts @@ -286,7 +286,7 @@ export async function determineAllPossibilitiesForTabCompletion( }); if (!script) return; // Doesn't exist. //Will return the already compiled module if recompilation not needed. - const loadedModule = await compile(p, script, currServ.scripts); + const loadedModule = await compile(script, currServ.scripts); if (!loadedModule || !loadedModule.autocomplete) return; // Doesn't have an autocomplete function. const runArgs = { "--tail": Boolean, "-t": Number }; diff --git a/src/ui/GameRoot.tsx b/src/ui/GameRoot.tsx index 66dd4e7ac..933521ac3 100644 --- a/src/ui/GameRoot.tsx +++ b/src/ui/GameRoot.tsx @@ -1,8 +1,8 @@ import React, { useState, useEffect } from "react"; -import { IPlayer } from "../PersonObjects/IPlayer"; -import { IEngine } from "../IEngine"; -import { ITerminal } from "../Terminal/ITerminal"; +import { Player } from "../Player"; +import { Engine } from "../engine"; +import { Terminal } from "../Terminal"; import { installAugmentations } from "../Augmentation/AugmentationHelpers"; import { saveObject } from "../SaveObject"; import { onExport } from "../ExportBonus"; @@ -84,12 +84,6 @@ import { V2Modal } from "../utils/V2Modal"; const htmlLocation = location; -interface IProps { - terminal: ITerminal; - player: IPlayer; - engine: IEngine; -} - const useStyles = makeStyles((theme: Theme) => createStyles({ root: { @@ -148,20 +142,20 @@ export let Router: IRouter = { toImportSave: uninitialized, }; -function determineStartPage(player: IPlayer): Page { +function determineStartPage(): Page { if (RecoveryMode) return Page.Recovery; - if (player.currentWork !== null) return Page.Work; + if (Player.currentWork !== null) return Page.Work; return Page.Terminal; } -export function GameRoot({ player, engine, terminal }: IProps): React.ReactElement { +export function GameRoot(): React.ReactElement { const classes = useStyles(); const [{ files, vim }, setEditorOptions] = useState({ files: {}, vim: false }); - const [page, setPage] = useState(determineStartPage(player)); + const [page, setPage] = useState(determineStartPage()); const setRerender = useState(0)[1]; const [augPage, setAugPage] = useState(false); const [faction, setFaction] = useState( - isFactionWork(player.currentWork) ? Factions[player.currentWork.factionName] : (undefined as unknown as Faction), + isFactionWork(Player.currentWork) ? Factions[Player.currentWork.factionName] : (undefined as unknown as Faction), ); if (faction === undefined && page === Page.Faction) throw new Error("Trying to go to a page without the proper setup"); @@ -243,7 +237,7 @@ export function GameRoot({ player, engine, terminal }: IProps): React.ReactEleme setPage(Page.City); }, toTravel: () => { - player.gotoLocation(LocationName.TravelAgency); + Player.gotoLocation(LocationName.TravelAgency); setPage(Page.Travel); }, toBitVerse: (flume: boolean, quick: boolean) => { @@ -347,7 +341,7 @@ export function GameRoot({ player, engine, terminal }: IProps): React.ReactEleme break; } case Page.Terminal: { - mainPage = ; + mainPage = ; break; } case Page.Sleeves: { @@ -366,8 +360,8 @@ export function GameRoot({ player, engine, terminal }: IProps): React.ReactEleme mainPage = ( @@ -379,7 +373,7 @@ export function GameRoot({ player, engine, terminal }: IProps): React.ReactEleme break; } case Page.Hacknet: { - mainPage = ; + mainPage = ; break; } case Page.CreateProgram: { @@ -387,7 +381,7 @@ export function GameRoot({ player, engine, terminal }: IProps): React.ReactEleme break; } case Page.Factions: { - mainPage = ; + mainPage = ; break; } case Page.Faction: { @@ -395,7 +389,7 @@ export function GameRoot({ player, engine, terminal }: IProps): React.ReactEleme break; } case Page.Milestones: { - mainPage = ; + mainPage = ; break; } case Page.Tutorial: { @@ -411,7 +405,7 @@ export function GameRoot({ player, engine, terminal }: IProps): React.ReactEleme break; } case Page.DevMenu: { - mainPage = ; + mainPage = ; break; } case Page.Gang: { @@ -431,11 +425,11 @@ export function GameRoot({ player, engine, terminal }: IProps): React.ReactEleme break; } case Page.Travel: { - mainPage = ; + mainPage = ; break; } case Page.StockMarket: { - mainPage = ; + mainPage = ; break; } case Page.City: { @@ -450,12 +444,12 @@ export function GameRoot({ player, engine, terminal }: IProps): React.ReactEleme case Page.Options: { mainPage = ( saveObject.saveGame()} export={() => { // Apply the export bonus before saving the game - onExport(player); + onExport(Player); saveObject.exportGame(); }} forceKill={killAllScripts} @@ -469,7 +463,7 @@ export function GameRoot({ player, engine, terminal }: IProps): React.ReactEleme { // Apply the export bonus before saving the game - onExport(player); + onExport(Player); saveObject.exportGame(); }} installAugmentationsFn={() => { @@ -496,7 +490,7 @@ export function GameRoot({ player, engine, terminal }: IProps): React.ReactEleme } return ( - + @@ -511,7 +505,7 @@ export function GameRoot({ player, engine, terminal }: IProps): React.ReactEleme {withSidebar ? ( + ) : ( diff --git a/src/ui/React/DialogBox.tsx b/src/ui/React/DialogBox.tsx index f4fe5216d..bcbdd88f2 100644 --- a/src/ui/React/DialogBox.tsx +++ b/src/ui/React/DialogBox.tsx @@ -14,8 +14,10 @@ export function errorDialog(e: unknown, initialText = "") { else if (e instanceof ScriptDeath) { if (!e.errorMessage) return; //No need for a dialog for an empty ScriptDeath errorText = e.errorMessage; - } else if (e instanceof SyntaxError) errorText = e.message + " (sorry we can't be more helpful)"; - else if (e instanceof Error) errorText = e.message + (e.stack ? `\nstack:\n${e.stack.toString()}` : ""); + if (!e.errorMessage.includes(`${e.name}@${e.hostname}`)) { + initialText += `${e.name}@${e.hostname} (PID - ${e.pid})\n\n`; + } + } else if (e instanceof Error) errorText = "Original error message:\n" + e.message; else { errorText = "An unknown error was thrown, see console."; console.error(e); diff --git a/src/utils/v1APIBreak.ts b/src/utils/v1APIBreak.ts index e9f3bde1f..524432d79 100644 --- a/src/utils/v1APIBreak.ts +++ b/src/utils/v1APIBreak.ts @@ -126,7 +126,7 @@ export function v1APIBreak(): void { for (const script of server.scripts) { if (!hasChanges(script.code)) continue; const prefix = script.filename.includes("/") ? "/BACKUP_" : "BACKUP_"; - backups.push(new Script(Player, prefix + script.filename, script.code, script.server)); + backups.push(new Script(prefix + script.filename, script.code, script.server)); script.code = convert(script.code); } server.scripts = server.scripts.concat(backups); From ad356cf28f354cc0e54e97d96174f90f7404a23b Mon Sep 17 00:00:00 2001 From: Snarling <84951833+Snarling@users.noreply.github.com> Date: Mon, 29 Aug 2022 02:48:00 -0400 Subject: [PATCH 03/46] format/lint --- src/NetscriptWorker.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/NetscriptWorker.ts b/src/NetscriptWorker.ts index 22c63fad6..e134ded37 100644 --- a/src/NetscriptWorker.ts +++ b/src/NetscriptWorker.ts @@ -347,7 +347,7 @@ function createAndAddWorkerScript(runningScriptObj: RunningScript, server: BaseS workerScript.log("", () => "Script finished running"); }) .catch(function (e) { - let initialText = `ERROR\n${workerScript.name}@${workerScript.hostname} (PID - ${workerScript.pid})\n\n`; + const initialText = `ERROR\n${workerScript.name}@${workerScript.hostname} (PID - ${workerScript.pid})\n\n`; if (e instanceof SyntaxError) e = `SYNTAX ${initialText}${e.message} (sorry we can't be more helpful)`; else if (e instanceof Error) { e = `RUNTIME ${initialText}${e.message}${e.stack ? `\nstack:\n${e.stack.toString()}` : ""}`; From caf1a99c1d673febb10836fbc9df665a1773c4cf Mon Sep 17 00:00:00 2001 From: Snarling <84951833+Snarling@users.noreply.github.com> Date: Mon, 29 Aug 2022 03:31:30 -0400 Subject: [PATCH 04/46] More reliable error message for ScriptDeaths --- src/ui/React/DialogBox.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/ui/React/DialogBox.tsx b/src/ui/React/DialogBox.tsx index bcbdd88f2..00fc5b4cf 100644 --- a/src/ui/React/DialogBox.tsx +++ b/src/ui/React/DialogBox.tsx @@ -23,9 +23,9 @@ export function errorDialog(e: unknown, initialText = "") { console.error(e); } - if (!initialText) { - if (e instanceof ScriptDeath) initialText = `${e.name}@${e.hostname} (PID - ${e.pid})\n\n`; + if (!initialText && e instanceof ScriptDeath) { + const basicHeader = `ERROR\n${e.name}@${e.hostname} (PID - ${e.pid})\n\n`; + if (e.errorMessage.includes(basicHeader)) initialText = basicHeader; } - dialogBoxCreate(initialText + errorText); } From 74be61cbdd769261cf95e3e323f7af651066d546 Mon Sep 17 00:00:00 2001 From: Snarling <84951833+Snarling@users.noreply.github.com> Date: Mon, 29 Aug 2022 03:34:38 -0400 Subject: [PATCH 05/46] remove unnecessary return --- src/NetscriptWorker.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/NetscriptWorker.ts b/src/NetscriptWorker.ts index e134ded37..8d39e9a71 100644 --- a/src/NetscriptWorker.ts +++ b/src/NetscriptWorker.ts @@ -62,7 +62,6 @@ async function startNetscript2Script(workerScript: WorkerScript): Promise throw `${script.filename} cannot be run because it does not have a main function.`; if (!ns) throw `${script.filename} cannot be run because the NS object hasn't been constructed properly.`; await loadedModule.main(ns); - return; } async function startNetscript1Script(workerScript: WorkerScript): Promise { From b8496b4c2cec8a99243451e5c827142e7aaef546 Mon Sep 17 00:00:00 2001 From: Snarling <84951833+Snarling@users.noreply.github.com> Date: Mon, 29 Aug 2022 03:47:56 -0400 Subject: [PATCH 06/46] remove duplicate handling --- src/ui/React/DialogBox.tsx | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/ui/React/DialogBox.tsx b/src/ui/React/DialogBox.tsx index 00fc5b4cf..6974dfb94 100644 --- a/src/ui/React/DialogBox.tsx +++ b/src/ui/React/DialogBox.tsx @@ -22,10 +22,5 @@ export function errorDialog(e: unknown, initialText = "") { errorText = "An unknown error was thrown, see console."; console.error(e); } - - if (!initialText && e instanceof ScriptDeath) { - const basicHeader = `ERROR\n${e.name}@${e.hostname} (PID - ${e.pid})\n\n`; - if (e.errorMessage.includes(basicHeader)) initialText = basicHeader; - } dialogBoxCreate(initialText + errorText); } From 8d0347577d98415586671586c554f0a10a0483ab Mon Sep 17 00:00:00 2001 From: Snarling <84951833+Snarling@users.noreply.github.com> Date: Mon, 5 Sep 2022 08:56:39 -0400 Subject: [PATCH 07/46] Less hardcoding --- src/Netscript/APIWrapper.ts | 2 +- src/Netscript/NetscriptHelpers.ts | 6 +++--- src/NetscriptWorker.ts | 15 ++++++++++----- 3 files changed, 14 insertions(+), 9 deletions(-) diff --git a/src/Netscript/APIWrapper.ts b/src/Netscript/APIWrapper.ts index 22b30ab23..b91501ab5 100644 --- a/src/Netscript/APIWrapper.ts +++ b/src/Netscript/APIWrapper.ts @@ -40,7 +40,7 @@ function wrapFunction( const functionPath = tree.join("."); const functionName = tree.pop(); if (typeof functionName !== "string") { - throw helpers.makeBasicErrorMsg(workerScript, "Failure occured while wrapping netscript api"); + throw helpers.makeBasicErrorMsg(workerScript, "Failure occured while wrapping netscript api", "INITIALIZATION"); } const ctx = { workerScript, diff --git a/src/Netscript/NetscriptHelpers.ts b/src/Netscript/NetscriptHelpers.ts index 9655f941a..6b06926e2 100644 --- a/src/Netscript/NetscriptHelpers.ts +++ b/src/Netscript/NetscriptHelpers.ts @@ -131,11 +131,11 @@ function argsToString(args: unknown[]): string { } /** Creates an error message string containing hostname, scriptname, and the error message msg */ -function makeBasicErrorMsg(workerScript: WorkerScript, msg: string): string { +function makeBasicErrorMsg(workerScript: WorkerScript, msg: string, type = "RUNTIME"): string { for (const scriptUrl of workerScript.scriptRef.dependencies) { msg = msg.replace(new RegExp(scriptUrl.url, "g"), scriptUrl.filename); } - return msg; + return `${type} ERROR\n${workerScript.name}@${workerScript.hostname} (PID - ${workerScript.pid})\n\n${msg}`; } /** Creates an error message string with a stack trace. */ @@ -204,7 +204,7 @@ function makeRuntimeErrorMsg(ctx: NetscriptContext, msg: string): string { } log(ctx, () => msg); - let rejectMsg = `RUNTIME ERROR\n${ws.name}@${ws.hostname} (PID - ${ws.pid})\n\n${caller}: ${msg}`; + let rejectMsg = `${caller}: ${msg}`; if (userstack.length !== 0) rejectMsg += `\n\nStack:\n${userstack.join("\n")}`; return makeBasicErrorMsg(ws, rejectMsg); } diff --git a/src/NetscriptWorker.ts b/src/NetscriptWorker.ts index 8d39e9a71..d75402576 100644 --- a/src/NetscriptWorker.ts +++ b/src/NetscriptWorker.ts @@ -33,6 +33,7 @@ import { simple as walksimple } from "acorn-walk"; import { areFilesEqual } from "./Terminal/DirectoryHelpers"; import { Terminal } from "./Terminal"; import { ScriptArg } from "./Netscript/ScriptArg"; +import { helpers } from "./Netscript/NetscriptHelpers"; export const NetscriptPorts: Map = new Map(); @@ -346,12 +347,16 @@ function createAndAddWorkerScript(runningScriptObj: RunningScript, server: BaseS workerScript.log("", () => "Script finished running"); }) .catch(function (e) { - const initialText = `ERROR\n${workerScript.name}@${workerScript.hostname} (PID - ${workerScript.pid})\n\n`; - if (e instanceof SyntaxError) e = `SYNTAX ${initialText}${e.message} (sorry we can't be more helpful)`; - else if (e instanceof Error) { - e = `RUNTIME ${initialText}${e.message}${e.stack ? `\nstack:\n${e.stack.toString()}` : ""}`; + if (typeof e === "string") { + const headerText = helpers.makeBasicErrorMsg(workerScript, "", ""); + //Add header info if it is not present; + if (!e.includes(headerText)) e = helpers.makeBasicErrorMsg(workerScript, e); + } else if (e instanceof SyntaxError) { + e = helpers.makeBasicErrorMsg(workerScript, `${e.message} (sorry we can't be more helpful)`, "SYNTAX"); + } else if (e instanceof Error) { + e = helpers.makeBasicErrorMsg(workerScript, `${e.message}${e.stack ? `\nstack:\n${e.stack.toString()}` : ""}`); } - errorDialog(e, typeof e === "string" && e.includes(initialText) ? "" : initialText); + errorDialog(e); workerScript.log("", () => (e instanceof ScriptDeath ? "Script killed." : "Script crashed due to an error.")); killWorkerScript(workerScript); }); From 7d3773605873201a6f556abd02be46c5dbd34bc0 Mon Sep 17 00:00:00 2001 From: Snarling <84951833+Snarling@users.noreply.github.com> Date: Mon, 5 Sep 2022 09:55:57 -0400 Subject: [PATCH 08/46] unified errors --- src/Netscript/NetscriptHelpers.ts | 41 ++++++++++++++++++++++++++----- src/Netscript/killWorkerScript.ts | 25 +++++-------------- src/NetscriptWorker.ts | 15 +++-------- src/UncaughtPromiseHandler.ts | 12 ++++++--- src/ui/React/DialogBox.tsx | 18 -------------- 5 files changed, 52 insertions(+), 59 deletions(-) diff --git a/src/Netscript/NetscriptHelpers.ts b/src/Netscript/NetscriptHelpers.ts index 6b06926e2..909c2d60d 100644 --- a/src/Netscript/NetscriptHelpers.ts +++ b/src/Netscript/NetscriptHelpers.ts @@ -33,6 +33,7 @@ import { RunningScript as IRunningScript } from "../ScriptEditor/NetscriptDefini import { arrayToString } from "../utils/helpers/arrayToString"; import { HacknetServer } from "../Hacknet/HacknetServer"; import { BaseServer } from "../Server/BaseServer"; +import { dialogBoxCreate } from "../ui/React/DialogBox"; export const helpers = { string, @@ -131,11 +132,13 @@ function argsToString(args: unknown[]): string { } /** Creates an error message string containing hostname, scriptname, and the error message msg */ -function makeBasicErrorMsg(workerScript: WorkerScript, msg: string, type = "RUNTIME"): string { - for (const scriptUrl of workerScript.scriptRef.dependencies) { - msg = msg.replace(new RegExp(scriptUrl.url, "g"), scriptUrl.filename); +function makeBasicErrorMsg(ws: WorkerScript | ScriptDeath, msg: string, type = "RUNTIME"): string { + if (ws instanceof WorkerScript) { + for (const scriptUrl of ws.scriptRef.dependencies) { + msg = msg.replace(new RegExp(scriptUrl.url, "g"), scriptUrl.filename); + } } - return `${type} ERROR\n${workerScript.name}@${workerScript.hostname} (PID - ${workerScript.pid})\n\n${msg}`; + return `${type} ERROR\n${ws.name}@${ws.hostname} (PID - ${ws.pid})\n\n${msg}`; } /** Creates an error message string with a stack trace. */ @@ -250,8 +253,7 @@ function checkEnvFlags(ctx: NetscriptContext): void { throw new ScriptDeath(ws); } if (ws.env.runningFn && ctx.function !== "asleep") { - //This one has no error message so it will not create a dialog - if (ws.delayReject) ws.delayReject(new ScriptDeath(ws)); + ws.delayReject?.(new ScriptDeath(ws)); ws.env.stopFlag = true; log(ctx, () => "Failed to run due to failed concurrency check."); throw makeRuntimeErrorMsg( @@ -692,3 +694,30 @@ function failOnHacknetServer(ctx: NetscriptContext, server: BaseServer, callingF return false; } } + +/** Generate an error dialog when workerscript is known */ +export function handleUnknownError(e: unknown, ws: WorkerScript | ScriptDeath | null = null, initialText = "") { + if (e instanceof ScriptDeath) { + //No dialog for an empty ScriptDeath + if (e.errorMessage === "") return; + if (!ws) { + ws = e; + e = ws.errorMessage; + } + } + if (ws && typeof e === "string") { + const headerText = makeBasicErrorMsg(ws, "", ""); + if (!e.includes(headerText)) e = makeBasicErrorMsg(ws, e); + } else if (e instanceof SyntaxError) { + const msg = `${e.message} (sorry we can't be more helpful)`; + e = ws ? makeBasicErrorMsg(ws, msg, "SYNTAX") : `SYNTAX ERROR:\n\n${msg}`; + } else if (e instanceof Error) { + const msg = `${e.message}${e.stack ? `\nstack:\n${e.stack.toString()}` : ""}`; + e = ws ? makeBasicErrorMsg(ws, msg) : `RUNTIME ERROR:\n\n${msg}`; + } + if (typeof e !== "string") { + console.error("Unexpected error type:", e); + e = "Unexpected type of error thrown. See console output."; + } + dialogBoxCreate(initialText + e); +} diff --git a/src/Netscript/killWorkerScript.ts b/src/Netscript/killWorkerScript.ts index c70455124..84224ca49 100644 --- a/src/Netscript/killWorkerScript.ts +++ b/src/Netscript/killWorkerScript.ts @@ -10,10 +10,10 @@ import { WorkerScriptStartStopEventEmitter } from "./WorkerScriptStartStopEventE import { RunningScript } from "../Script/RunningScript"; import { GetServer } from "../Server/AllServers"; -import { errorDialog } from "../ui/React/DialogBox"; import { AddRecentScript } from "./RecentScripts"; import { ITutorial } from "../InteractiveTutorial"; import { AlertEvents } from "../ui/React/AlertManager"; +import { handleUnknownError } from "./NetscriptHelpers"; export type killScriptParams = WorkerScript | number | { runningScript: RunningScript; hostname: string }; @@ -59,13 +59,16 @@ function killWorkerScriptByPid(pid: number): boolean { } function stopAndCleanUpWorkerScript(ws: WorkerScript): void { - killNetscriptDelay(ws); + //Clean up any ongoing netscriptDelay + if (ws.delay) clearTimeout(ws.delay); + ws.delayReject?.(new ScriptDeath(ws)); + if (typeof ws.atExit === "function") { try { ws.env.stopFlag = false; ws.atExit(); } catch (e: unknown) { - errorDialog(e, `Error during atExit ${ws.name}@${ws.hostname} (PID - ${ws.pid}\n\n`); + handleUnknownError(e, ws, "Error running atExit function.\n\n"); } ws.atExit = undefined; } @@ -115,19 +118,3 @@ function removeWorkerScript(workerScript: WorkerScript): void { WorkerScriptStartStopEventEmitter.emit(); } - -/** - * Helper function that interrupts a script's delay if it is in the middle of a - * timed, blocked operation (like hack(), sleep(), etc.). This allows scripts to - * be killed immediately even if they're in the middle of one of those long operations - */ -function killNetscriptDelay(workerScript: WorkerScript): void { - if (workerScript instanceof WorkerScript) { - if (workerScript.delay) { - clearTimeout(workerScript.delay); - if (workerScript.delayReject) { - workerScript.delayReject(new ScriptDeath(workerScript)); - } - } - } -} diff --git a/src/NetscriptWorker.ts b/src/NetscriptWorker.ts index d75402576..a69548656 100644 --- a/src/NetscriptWorker.ts +++ b/src/NetscriptWorker.ts @@ -24,7 +24,7 @@ import { Settings } from "./Settings/Settings"; import { generate } from "escodegen"; -import { dialogBoxCreate, errorDialog } from "./ui/React/DialogBox"; +import { dialogBoxCreate } from "./ui/React/DialogBox"; import { arrayToString } from "./utils/helpers/arrayToString"; import { roundToTwo } from "./utils/helpers/roundToTwo"; @@ -33,7 +33,7 @@ import { simple as walksimple } from "acorn-walk"; import { areFilesEqual } from "./Terminal/DirectoryHelpers"; import { Terminal } from "./Terminal"; import { ScriptArg } from "./Netscript/ScriptArg"; -import { helpers } from "./Netscript/NetscriptHelpers"; +import { handleUnknownError } from "./Netscript/NetscriptHelpers"; export const NetscriptPorts: Map = new Map(); @@ -347,16 +347,7 @@ function createAndAddWorkerScript(runningScriptObj: RunningScript, server: BaseS workerScript.log("", () => "Script finished running"); }) .catch(function (e) { - if (typeof e === "string") { - const headerText = helpers.makeBasicErrorMsg(workerScript, "", ""); - //Add header info if it is not present; - if (!e.includes(headerText)) e = helpers.makeBasicErrorMsg(workerScript, e); - } else if (e instanceof SyntaxError) { - e = helpers.makeBasicErrorMsg(workerScript, `${e.message} (sorry we can't be more helpful)`, "SYNTAX"); - } else if (e instanceof Error) { - e = helpers.makeBasicErrorMsg(workerScript, `${e.message}${e.stack ? `\nstack:\n${e.stack.toString()}` : ""}`); - } - errorDialog(e); + handleUnknownError(e, workerScript); workerScript.log("", () => (e instanceof ScriptDeath ? "Script killed." : "Script crashed due to an error.")); killWorkerScript(workerScript); }); diff --git a/src/UncaughtPromiseHandler.ts b/src/UncaughtPromiseHandler.ts index a786c384a..d9ddc29d6 100644 --- a/src/UncaughtPromiseHandler.ts +++ b/src/UncaughtPromiseHandler.ts @@ -1,7 +1,11 @@ -import { errorDialog } from "./ui/React/DialogBox"; +import { handleUnknownError } from "./Netscript/NetscriptHelpers"; export function setupUncaughtPromiseHandler(): void { - window.addEventListener("unhandledrejection", (e) => - errorDialog(e.reason, "UNCAUGHT PROMISE ERROR\nYou forgot to await a promise\nmaybe hack / grow / weaken ?\n"), - ); + window.addEventListener("unhandledrejection", (e) => { + handleUnknownError( + e.reason, + null, + "UNCAUGHT PROMISE ERROR\nYou forgot to await a promise\nmaybe hack / grow / weaken ?\n\n", + ); + }); } diff --git a/src/ui/React/DialogBox.tsx b/src/ui/React/DialogBox.tsx index 6974dfb94..3d32dbe9b 100644 --- a/src/ui/React/DialogBox.tsx +++ b/src/ui/React/DialogBox.tsx @@ -2,25 +2,7 @@ import { AlertEvents } from "./AlertManager"; import React from "react"; import { Typography } from "@mui/material"; -import { ScriptDeath } from "../../Netscript/ScriptDeath"; export function dialogBoxCreate(txt: string | JSX.Element): void { AlertEvents.emit(typeof txt === "string" ? {txt} : txt); } - -export function errorDialog(e: unknown, initialText = "") { - let errorText = ""; - if (typeof e === "string") errorText = e; - else if (e instanceof ScriptDeath) { - if (!e.errorMessage) return; //No need for a dialog for an empty ScriptDeath - errorText = e.errorMessage; - if (!e.errorMessage.includes(`${e.name}@${e.hostname}`)) { - initialText += `${e.name}@${e.hostname} (PID - ${e.pid})\n\n`; - } - } else if (e instanceof Error) errorText = "Original error message:\n" + e.message; - else { - errorText = "An unknown error was thrown, see console."; - console.error(e); - } - dialogBoxCreate(initialText + errorText); -} From 83c62bbc638fa2b6097bf6f50821c5e629d73192 Mon Sep 17 00:00:00 2001 From: Snarling <84951833+Snarling@users.noreply.github.com> Date: Mon, 5 Sep 2022 10:25:28 -0400 Subject: [PATCH 09/46] silent fail for tabcompletion compile error --- .../determineAllPossibilitiesForTabCompletion.ts | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/Terminal/determineAllPossibilitiesForTabCompletion.ts b/src/Terminal/determineAllPossibilitiesForTabCompletion.ts index df32766a3..54393f894 100644 --- a/src/Terminal/determineAllPossibilitiesForTabCompletion.ts +++ b/src/Terminal/determineAllPossibilitiesForTabCompletion.ts @@ -285,8 +285,14 @@ export async function determineAllPossibilitiesForTabCompletion( return processFilepath(script.filename) === fn || script.filename === "/" + fn; }); if (!script) return; // Doesn't exist. - //Will return the already compiled module if recompilation not needed. - const loadedModule = await compile(script, currServ.scripts); + let loadedModule; + try { + //Will return the already compiled module if recompilation not needed. + loadedModule = await compile(script, currServ.scripts); + } catch (e) { + //fail silently if the script fails to compile (e.g. syntax error) + return; + } if (!loadedModule || !loadedModule.autocomplete) return; // Doesn't have an autocomplete function. const runArgs = { "--tail": Boolean, "-t": Number }; From 824d8db653391cbff2a070af1beeb19c9891ec20 Mon Sep 17 00:00:00 2001 From: Snarling <84951833+Snarling@users.noreply.github.com> Date: Mon, 5 Sep 2022 10:35:12 -0400 Subject: [PATCH 10/46] simplify/dehardcode failOnHacknetServer --- src/Netscript/NetscriptHelpers.ts | 4 ++-- src/NetscriptFunctions.ts | 22 +++++++++++----------- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/Netscript/NetscriptHelpers.ts b/src/Netscript/NetscriptHelpers.ts index 909c2d60d..2b45ce1d9 100644 --- a/src/Netscript/NetscriptHelpers.ts +++ b/src/Netscript/NetscriptHelpers.ts @@ -686,9 +686,9 @@ function createPublicRunningScript(runningScript: RunningScript): IRunningScript * @param {string} callingFn - Name of calling function. For logging purposes * @returns {boolean} True if the server is a Hacknet Server, false otherwise */ -function failOnHacknetServer(ctx: NetscriptContext, server: BaseServer, callingFn = ""): boolean { +function failOnHacknetServer(ctx: NetscriptContext, server: BaseServer): boolean { if (server instanceof HacknetServer) { - ctx.workerScript.log(callingFn, () => `Does not work on Hacknet Servers`); + log(ctx, () => `Does not work on Hacknet Servers`); return true; } else { return false; diff --git a/src/NetscriptFunctions.ts b/src/NetscriptFunctions.ts index 51a54c3c0..fa22e8fef 100644 --- a/src/NetscriptFunctions.ts +++ b/src/NetscriptFunctions.ts @@ -1110,7 +1110,7 @@ const base: InternalAPI = { helpers.log(ctx, () => "Cannot be executed on this server."); return 0; } - if (helpers.failOnHacknetServer(ctx, server, "getServerMoneyAvailable")) { + if (helpers.failOnHacknetServer(ctx, server)) { return 0; } if (server.hostname == "home") { @@ -1130,7 +1130,7 @@ const base: InternalAPI = { helpers.log(ctx, () => "Cannot be executed on this server."); return 1; } - if (helpers.failOnHacknetServer(ctx, server, "getServerSecurityLevel")) { + if (helpers.failOnHacknetServer(ctx, server)) { return 1; } helpers.log( @@ -1149,7 +1149,7 @@ const base: InternalAPI = { helpers.log(ctx, () => "Cannot be executed on this server."); return 1; } - if (helpers.failOnHacknetServer(ctx, server, "getServerBaseSecurityLevel")) { + if (helpers.failOnHacknetServer(ctx, server)) { return 1; } helpers.log( @@ -1167,7 +1167,7 @@ const base: InternalAPI = { helpers.log(ctx, () => "Cannot be executed on this server."); return 1; } - if (helpers.failOnHacknetServer(ctx, server, "getServerMinSecurityLevel")) { + if (helpers.failOnHacknetServer(ctx, server)) { return 1; } helpers.log( @@ -1185,7 +1185,7 @@ const base: InternalAPI = { helpers.log(ctx, () => "Cannot be executed on this server."); return 1; } - if (helpers.failOnHacknetServer(ctx, server, "getServerRequiredHackingLevel")) { + if (helpers.failOnHacknetServer(ctx, server)) { return 1; } helpers.log( @@ -1203,7 +1203,7 @@ const base: InternalAPI = { helpers.log(ctx, () => "Cannot be executed on this server."); return 0; } - if (helpers.failOnHacknetServer(ctx, server, "getServerMaxMoney")) { + if (helpers.failOnHacknetServer(ctx, server)) { return 0; } helpers.log(ctx, () => `returned ${numeralWrapper.formatMoney(server.moneyMax)} for '${server.hostname}'`); @@ -1218,7 +1218,7 @@ const base: InternalAPI = { helpers.log(ctx, () => "Cannot be executed on this server."); return 1; } - if (helpers.failOnHacknetServer(ctx, server, "getServerGrowth")) { + if (helpers.failOnHacknetServer(ctx, server)) { return 1; } helpers.log(ctx, () => `returned ${server.serverGrowth} for '${server.hostname}'`); @@ -1233,7 +1233,7 @@ const base: InternalAPI = { helpers.log(ctx, () => "Cannot be executed on this server."); return 5; } - if (helpers.failOnHacknetServer(ctx, server, "getServerNumPortsRequired")) { + if (helpers.failOnHacknetServer(ctx, server)) { return 5; } helpers.log(ctx, () => `returned ${server.numOpenPortsRequired} for '${server.hostname}'`); @@ -1679,7 +1679,7 @@ const base: InternalAPI = { helpers.log(ctx, () => "invalid for this kind of server"); return Infinity; } - if (helpers.failOnHacknetServer(ctx, server, "getHackTime")) { + if (helpers.failOnHacknetServer(ctx, server)) { return Infinity; } @@ -1694,7 +1694,7 @@ const base: InternalAPI = { helpers.log(ctx, () => "invalid for this kind of server"); return Infinity; } - if (helpers.failOnHacknetServer(ctx, server, "getGrowTime")) { + if (helpers.failOnHacknetServer(ctx, server)) { return Infinity; } @@ -1709,7 +1709,7 @@ const base: InternalAPI = { helpers.log(ctx, () => "invalid for this kind of server"); return Infinity; } - if (helpers.failOnHacknetServer(ctx, server, "getWeakenTime")) { + if (helpers.failOnHacknetServer(ctx, server)) { return Infinity; } From cc2246213f079d72b887b02845c1dffa3ef5a290 Mon Sep 17 00:00:00 2001 From: Snarling <84951833+Snarling@users.noreply.github.com> Date: Mon, 5 Sep 2022 14:12:48 -0400 Subject: [PATCH 11/46] Add more error types --- src/Netscript/NetscriptHelpers.ts | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/src/Netscript/NetscriptHelpers.ts b/src/Netscript/NetscriptHelpers.ts index 2b45ce1d9..4657cd81c 100644 --- a/src/Netscript/NetscriptHelpers.ts +++ b/src/Netscript/NetscriptHelpers.ts @@ -91,7 +91,7 @@ const debugType = (v: unknown): string => { function string(ctx: NetscriptContext, argName: string, v: unknown): string { if (typeof v === "string") return v; if (typeof v === "number") return v + ""; // cast to string; - throw makeRuntimeErrorMsg(ctx, `'${argName}' should be a string. ${debugType(v)}`); + throw makeRuntimeErrorMsg(ctx, `'${argName}' should be a string. ${debugType(v)}`, "TYPE"); } /** Convert provided value v for argument argName to number. Throw if could not convert to a non-NaN number. */ @@ -103,12 +103,12 @@ function number(ctx: NetscriptContext, argName: string, v: unknown): number { if (isNaN(v)) throw makeRuntimeErrorMsg(ctx, `'${argName}' is NaN.`); return v; } - throw makeRuntimeErrorMsg(ctx, `'${argName}' should be a number. ${debugType(v)}`); + throw makeRuntimeErrorMsg(ctx, `'${argName}' should be a number. ${debugType(v)}`, "TYPE"); } /** Returns args back if it is a ScriptArg[]. Throws an error if it is not. */ function scriptArgs(ctx: NetscriptContext, args: unknown) { - if (!isScriptArgs(args)) throw makeRuntimeErrorMsg(ctx, "'args' is not an array of script args"); + if (!isScriptArgs(args)) throw makeRuntimeErrorMsg(ctx, "'args' is not an array of script args", "TYPE"); return args; } @@ -142,7 +142,7 @@ function makeBasicErrorMsg(ws: WorkerScript | ScriptDeath, msg: string, type = " } /** Creates an error message string with a stack trace. */ -function makeRuntimeErrorMsg(ctx: NetscriptContext, msg: string): string { +function makeRuntimeErrorMsg(ctx: NetscriptContext, msg: string, type = "RUNTIME"): string { const errstack = new Error().stack; if (errstack === undefined) throw new Error("how did we not throw an error?"); const stack = errstack.split("\n").slice(1); @@ -209,7 +209,7 @@ function makeRuntimeErrorMsg(ctx: NetscriptContext, msg: string): string { log(ctx, () => msg); let rejectMsg = `${caller}: ${msg}`; if (userstack.length !== 0) rejectMsg += `\n\nStack:\n${userstack.join("\n")}`; - return makeBasicErrorMsg(ws, rejectMsg); + return makeBasicErrorMsg(ws, rejectMsg, type); } /** Validate requested number of threads for h/g/w options */ @@ -241,6 +241,7 @@ function checkSingularityAccess(ctx: NetscriptContext): void { ctx, `This singularity function requires Source-File 4 to run. A power up you obtain later in the game. It will be very obvious when and how you can obtain it.`, + "API ACCESS", ); } } @@ -262,6 +263,7 @@ function checkEnvFlags(ctx: NetscriptContext): void { Did you forget to await hack(), grow(), or some other promise-returning function? Currently running: ${ws.env.runningFn} tried to run: ${ctx.function}`, + "CONCURRENCY", ); } } @@ -304,8 +306,8 @@ function updateDynamicRam(ctx: NetscriptContext, ramCost: number): void { This is probably because you somehow circumvented the static RAM calculation. Threads: ${threads} - Dynamic RAM Usage: ${numeralWrapper.formatRAM(ws.dynamicRamUsage)} - Static RAM Usage: ${numeralWrapper.formatRAM(ws.ramUsage)} + Dynamic RAM Usage: ${numeralWrapper.formatRAM(ws.dynamicRamUsage)} per thread + Static RAM Usage: ${numeralWrapper.formatRAM(ws.ramUsage)} per thread One of these could be the reason: * Using eval() to get a reference to a ns function @@ -315,6 +317,7 @@ function updateDynamicRam(ctx: NetscriptContext, ramCost: number): void { \u00a0\u00a0const myScan = ns['scan']; Sorry :(`, + "RAM USAGE", ); } } @@ -346,7 +349,7 @@ function scriptIdentifier( args, }; } - throw new Error("not implemented"); + throw makeRuntimeErrorMsg(ctx, "An unknown type of input was provided as a script identifier.", "TYPE"); } /** @@ -514,7 +517,7 @@ function player(ctx: NetscriptContext, p: unknown): IPlayer { hasCorporation: undefined, entropy: undefined, }; - if (!roughlyIs(fakePlayer, p)) throw makeRuntimeErrorMsg(ctx, `player should be a Player.`); + if (!roughlyIs(fakePlayer, p)) throw makeRuntimeErrorMsg(ctx, `player should be a Player.`, "TYPE"); return p as IPlayer; } @@ -545,7 +548,7 @@ function server(ctx: NetscriptContext, s: unknown): Server { requiredHackingSkill: undefined, serverGrowth: undefined, }; - if (!roughlyIs(fakeServer, s)) throw makeRuntimeErrorMsg(ctx, `server should be a Server.`); + if (!roughlyIs(fakeServer, s)) throw makeRuntimeErrorMsg(ctx, `server should be a Server.`, "TYPE"); return s as Server; } @@ -563,18 +566,18 @@ function roughlyIs(expect: object, actual: unknown): boolean { function gang(ctx: NetscriptContext, g: unknown): FormulaGang { if (!roughlyIs({ respect: 0, territory: 0, wantedLevel: 0 }, g)) - throw makeRuntimeErrorMsg(ctx, `gang should be a Gang.`); + throw makeRuntimeErrorMsg(ctx, `gang should be a Gang.`, "TYPE"); return g as FormulaGang; } function gangMember(ctx: NetscriptContext, m: unknown): GangMember { - if (!roughlyIs(new GangMember(), m)) throw makeRuntimeErrorMsg(ctx, `member should be a GangMember.`); + if (!roughlyIs(new GangMember(), m)) throw makeRuntimeErrorMsg(ctx, `member should be a GangMember.`, "TYPE"); return m as GangMember; } function gangTask(ctx: NetscriptContext, t: unknown): GangMemberTask { if (!roughlyIs(new GangMemberTask("", "", false, false, { hackWeight: 100 }), t)) - throw makeRuntimeErrorMsg(ctx, `task should be a GangMemberTask.`); + throw makeRuntimeErrorMsg(ctx, `task should be a GangMemberTask.`, "TYPE"); return t as GangMemberTask; } From 83d357e758031b0eb25d00031c3006d6c7146757 Mon Sep 17 00:00:00 2001 From: Snarling <84951833+Snarling@users.noreply.github.com> Date: Tue, 6 Sep 2022 09:07:12 -0400 Subject: [PATCH 12/46] commit1 --- src/Achievements/Achievements.ts | 18 +- src/Augmentation/Augmentation.tsx | 22 +- src/Augmentation/ui/AugmentationsRoot.tsx | 26 +- .../ui/PurchasableAugmentations.tsx | 35 +- .../ui/PurchaseAugmentationModal.tsx | 2 +- src/BitNode/BitNode.tsx | 6 +- src/Bladeburner/Bladeburner.tsx | 117 +++--- src/Bladeburner/IBladeburner.ts | 39 +- src/Bladeburner/ui/ActionLevel.tsx | 4 +- src/Bladeburner/ui/AllPages.tsx | 10 +- src/Bladeburner/ui/BlackOpElem.tsx | 5 +- src/Bladeburner/ui/BlackOpList.tsx | 4 +- src/Bladeburner/ui/BlackOpPage.tsx | 4 +- src/Bladeburner/ui/BladeburnerRoot.tsx | 6 +- src/Bladeburner/ui/Console.tsx | 4 +- src/Bladeburner/ui/ContractElem.tsx | 5 +- src/Bladeburner/ui/ContractList.tsx | 4 +- src/Bladeburner/ui/ContractPage.tsx | 4 +- src/Bladeburner/ui/GeneralActionElem.tsx | 7 +- src/Bladeburner/ui/GeneralActionList.tsx | 4 +- src/Bladeburner/ui/GeneralActionPage.tsx | 4 +- src/Bladeburner/ui/OperationElem.tsx | 5 +- src/Bladeburner/ui/OperationList.tsx | 4 +- src/Bladeburner/ui/OperationPage.tsx | 4 +- src/Bladeburner/ui/StartButton.tsx | 2 +- src/Bladeburner/ui/Stats.tsx | 16 +- src/Casino/Blackjack.tsx | 26 +- src/Casino/CoinFlip.tsx | 15 +- src/Casino/Game.ts | 16 + src/Casino/Game.tsx | 31 -- src/Casino/Roulette.tsx | 13 +- src/Casino/SlotMachine.tsx | 18 +- src/Corporation/Actions.ts | 11 +- src/Corporation/Corporation.tsx | 10 +- src/Corporation/ui/Industry.tsx | 1 - src/Corporation/ui/IndustryWarehouse.tsx | 2 - .../ui/modals/BuybackSharesModal.tsx | 2 +- .../ui/modals/CreateCorporationModal.tsx | 2 +- src/Corporation/ui/modals/SellSharesModal.tsx | 2 +- src/Crime/CrimeHelpers.ts | 6 +- src/DevMenu.tsx | 44 +-- src/DevMenu/ui/Achievements.tsx | 33 +- src/DevMenu/ui/Augmentations.tsx | 16 +- src/DevMenu/ui/Bladeburner.tsx | 14 +- src/DevMenu/ui/Corporation.tsx | 40 +- src/DevMenu/ui/Entropy.tsx | 26 +- src/DevMenu/ui/Factions.tsx | 12 +- src/DevMenu/ui/Gang.tsx | 20 +- src/DevMenu/ui/General.tsx | 29 +- src/DevMenu/ui/Programs.tsx | 16 +- src/DevMenu/ui/Sleeves.tsx | 28 +- src/DevMenu/ui/SourceFiles.tsx | 24 +- src/DevMenu/ui/Stats.tsx | 88 ++--- src/DevMenu/ui/TimeSkip.tsx | 15 +- src/ExportBonus.tsx | 6 +- src/Faction/FactionHelpers.tsx | 13 +- src/Faction/formulas/donation.ts | 6 +- src/Faction/ui/AugmentationsPage.tsx | 29 +- src/Faction/ui/DonateOption.tsx | 13 +- src/Faction/ui/FactionRoot.tsx | 35 +- src/Faction/ui/FactionsRoot.tsx | 57 +-- src/GameOptions/ui/GameOptionsRoot.tsx | 6 - src/GameOptions/ui/GameOptionsSidebar.tsx | 11 +- src/Hacking.ts | 38 +- src/Hacking/netscriptCanHack.ts | 6 +- src/Hacknet/HacknetHelpers.tsx | 229 ++++++----- src/Hacknet/ui/HacknetNodeElem.tsx | 39 +- src/Hacknet/ui/HacknetRoot.tsx | 43 +- src/Hacknet/ui/HacknetServerElem.tsx | 61 ++- src/Hacknet/ui/HacknetUpgradeElem.tsx | 5 +- src/Hacknet/ui/HashUpgradeModal.tsx | 17 +- src/Hacknet/ui/PlayerInfo.tsx | 10 +- src/Hacknet/ui/PurchaseButton.tsx | 8 +- src/Hospital/Hospital.ts | 18 +- src/Locations/LocationsHelpers.tsx | 40 -- src/Locations/ui/CasinoLocation.tsx | 15 +- src/Locations/ui/CoresButton.tsx | 15 +- src/Locations/ui/GenericLocation.tsx | 14 +- src/Locations/ui/GymLocation.tsx | 20 +- src/Locations/ui/HospitalLocation.tsx | 24 +- src/Locations/ui/PurchaseServerModal.tsx | 4 +- src/Locations/ui/RamButton.tsx | 13 +- src/Locations/ui/TechVendorLocation.tsx | 14 +- src/Locations/ui/TorButton.tsx | 44 ++- src/Locations/ui/TravelAgencyRoot.tsx | 36 +- src/Locations/ui/TravelConfirmationModal.tsx | 2 +- src/Locations/ui/UniversityLocation.tsx | 10 +- src/Milestones/ui/MilestonesRoot.tsx | 16 +- src/Netscript/NetscriptHelpers.ts | 2 +- src/NetscriptFunctions/Bladeburner.ts | 154 +++----- src/NetscriptFunctions/Corporation.ts | 4 +- src/NetscriptFunctions/Formulas.ts | 6 +- src/NetscriptFunctions/Grafting.ts | 11 +- src/NetscriptFunctions/Hacknet.ts | 44 +-- src/NetscriptFunctions/Singularity.ts | 371 +++++++++--------- src/NetscriptFunctions/Sleeve.ts | 60 +-- .../Grafting/EntropyAccumulation.ts | 64 +-- src/PersonObjects/Grafting/GraftingHelpers.ts | 14 +- .../Grafting/ui/GraftingRoot.tsx | 50 +-- .../Player/PlayerObjectAugmentationMethods.ts | 2 +- .../Player/PlayerObjectBladeburnerMethods.ts | 2 +- .../Player/PlayerObjectGeneralMethods.ts | 14 +- .../Player/PlayerObjectWorkMethods.ts | 6 +- src/PersonObjects/Sleeve/Sleeve.ts | 93 +++-- src/PersonObjects/Sleeve/SleeveHelpers.ts | 15 +- .../Sleeve/Work/SleeveBladeburnerWork.ts | 32 +- .../Sleeve/Work/SleeveClassWork.ts | 10 +- .../Sleeve/Work/SleeveCompanyWork.ts | 10 +- .../Sleeve/Work/SleeveCrimeWork.ts | 8 +- .../Sleeve/Work/SleeveFactionWork.ts | 14 +- .../Sleeve/Work/SleeveInfiltrateWork.ts | 8 +- .../Sleeve/Work/SleeveRecoveryWork.ts | 5 +- .../Sleeve/Work/SleeveSupportWork.ts | 10 +- .../Sleeve/Work/SleeveSynchroWork.ts | 8 +- src/PersonObjects/Sleeve/Work/Work.ts | 12 +- .../Sleeve/ui/CovenantPurchasesRoot.tsx | 6 +- .../Sleeve/ui/CovenantSleeveMemoryUpgrade.tsx | 11 +- .../Sleeve/ui/SleeveAugmentationsModal.tsx | 14 +- src/PersonObjects/Sleeve/ui/SleeveElem.tsx | 29 +- src/PersonObjects/Sleeve/ui/StatsElement.tsx | 6 +- src/PersonObjects/Sleeve/ui/TaskSelector.tsx | 101 +++-- src/PersonObjects/Sleeve/ui/TravelModal.tsx | 11 +- src/Prestige.ts | 12 +- src/Programs/Program.ts | 9 +- src/Programs/ProgramHelpers.ts | 8 +- src/Programs/data/ProgramsMetadata.ts | 137 ++++--- src/Programs/ui/ProgramsRoot.tsx | 33 +- src/ScriptEditor/ui/ScriptEditorRoot.tsx | 32 +- src/Server/ServerPurchases.ts | 24 +- src/Sidebar/ui/SidebarRoot.tsx | 93 +++-- src/StockMarket/ui/InfoAndPurchases.tsx | 63 ++- src/StockMarket/ui/StockMarketRoot.tsx | 7 +- src/StockMarket/ui/StockTicker.tsx | 15 +- src/StockMarket/ui/StockTickerHeaderText.tsx | 5 +- src/StockMarket/ui/StockTickerOrderList.tsx | 3 - .../ui/StockTickerPositionText.tsx | 5 +- src/StockMarket/ui/StockTickers.tsx | 7 +- src/Terminal/ITerminal.tsx | 44 +-- src/Terminal/Terminal.ts | 153 ++++---- src/Terminal/commands/alias.ts | 19 +- src/Terminal/commands/analyze.ts | 17 +- src/Terminal/commands/backdoor.ts | 29 +- src/Terminal/commands/buy.ts | 36 +- src/Terminal/commands/cat.ts | 24 +- src/Terminal/commands/cd.ts | 27 +- src/Terminal/commands/check.ts | 20 +- src/Terminal/commands/common/editor.ts | 43 +- src/Terminal/commands/connect.ts | 24 +- src/Terminal/commands/cp.ts | 49 ++- src/Terminal/commands/download.ts | 26 +- src/Terminal/commands/expr.ts | 19 +- src/Terminal/commands/free.ts | 30 +- src/Terminal/commands/grow.ts | 24 +- src/Terminal/commands/hack.ts | 24 +- src/Terminal/commands/help.ts | 21 +- src/Terminal/commands/history.ts | 26 +- src/Terminal/commands/home.ts | 22 +- src/Terminal/commands/hostname.ts | 16 +- src/Terminal/commands/kill.ts | 26 +- src/Terminal/commands/killall.ts | 8 +- src/Terminal/commands/ls.tsx | 49 ++- src/Terminal/commands/lscpu.ts | 9 +- src/Terminal/commands/mem.ts | 29 +- src/Terminal/commands/mv.ts | 50 +-- src/Terminal/commands/nano.ts | 13 +- src/Terminal/commands/ps.ts | 18 +- src/Terminal/commands/rm.ts | 18 +- src/Terminal/commands/run.ts | 17 +- src/Terminal/commands/runProgram.ts | 28 +- src/Terminal/commands/runScript.ts | 29 +- src/Terminal/commands/scan.ts | 17 +- src/Terminal/commands/scananalyze.ts | 32 +- src/Terminal/commands/scp.ts | 86 ++-- src/Terminal/commands/sudov.ts | 15 +- src/Terminal/commands/tail.ts | 30 +- src/Terminal/commands/top.ts | 15 +- src/Terminal/commands/unalias.ts | 15 +- src/Terminal/commands/vim.ts | 13 +- src/Terminal/commands/weaken.ts | 27 +- src/Terminal/commands/wget.ts | 23 +- src/Terminal/ui/TerminalInput.tsx | 65 ++- src/Terminal/ui/TerminalRoot.tsx | 31 +- src/Themes/ui/ThemeBrowser.tsx | 9 +- src/Themes/ui/ThemeEditorButton.tsx | 9 +- src/Themes/ui/ThemeEditorModal.tsx | 5 +- src/Work/ClassWork.tsx | 12 +- src/Work/CompanyWork.tsx | 16 +- src/Work/CreateProgramWork.ts | 32 +- src/Work/CrimeWork.ts | 32 +- src/Work/FactionWork.tsx | 26 +- src/Work/GraftingWork.tsx | 25 +- src/Work/Work.ts | 5 +- src/Work/WorkStats.ts | 5 +- src/Work/formulas/Class.ts | 19 +- src/Work/formulas/Company.ts | 8 +- src/engine.tsx | 20 +- src/ui/ErrorBoundary.tsx | 15 +- src/ui/GameRoot.tsx | 42 +- src/ui/React/CharacterOverview.tsx | 4 +- src/ui/React/ImportSaveRoot.tsx | 9 +- src/ui/React/Money.tsx | 11 +- src/ui/React/RecoveryRoot.tsx | 7 +- src/ui/WorkInProgressRoot.tsx | 116 +++--- 203 files changed, 2263 insertions(+), 3018 deletions(-) create mode 100644 src/Casino/Game.ts delete mode 100644 src/Casino/Game.tsx delete mode 100644 src/Locations/LocationsHelpers.tsx diff --git a/src/Achievements/Achievements.ts b/src/Achievements/Achievements.ts index 2085a031e..acbf35dd8 100644 --- a/src/Achievements/Achievements.ts +++ b/src/Achievements/Achievements.ts @@ -347,18 +347,18 @@ export const achievements: IMap = { FIRST_HACKNET_NODE: { ...achievementData["FIRST_HACKNET_NODE"], Icon: "node", - Condition: () => !hasHacknetServers(Player) && Player.hacknetNodes.length > 0, + Condition: () => !hasHacknetServers() && Player.hacknetNodes.length > 0, }, "30_HACKNET_NODE": { ...achievementData["30_HACKNET_NODE"], Icon: "hacknet-all", - Condition: () => !hasHacknetServers(Player) && Player.hacknetNodes.length >= 30, + Condition: () => !hasHacknetServers() && Player.hacknetNodes.length >= 30, }, MAX_HACKNET_NODE: { ...achievementData["MAX_HACKNET_NODE"], Icon: "hacknet-max", Condition: (): boolean => { - if (hasHacknetServers(Player)) return false; + if (hasHacknetServers()) return false; for (const h of Player.hacknetNodes) { if (!(h instanceof HacknetNode)) return false; if ( @@ -374,7 +374,7 @@ export const achievements: IMap = { HACKNET_NODE_10M: { ...achievementData["HACKNET_NODE_10M"], Icon: "hacknet-10m", - Condition: () => !hasHacknetServers(Player) && Player.moneySourceB.hacknet >= 10e6, + Condition: () => !hasHacknetServers() && Player.moneySourceB.hacknet >= 10e6, }, REPUTATION_10M: { ...achievementData["REPUTATION_10M"], @@ -515,14 +515,14 @@ export const achievements: IMap = { ...achievementData["FIRST_HACKNET_SERVER"], Icon: "HASHNET", Visible: () => hasAccessToSF(Player, 9), - Condition: () => hasHacknetServers(Player) && Player.hacknetNodes.length > 0, + Condition: () => hasHacknetServers() && Player.hacknetNodes.length > 0, AdditionalUnlock: [achievementData.FIRST_HACKNET_NODE.ID], }, ALL_HACKNET_SERVER: { ...achievementData["ALL_HACKNET_SERVER"], Icon: "HASHNETALL", Visible: () => hasAccessToSF(Player, 9), - Condition: () => hasHacknetServers(Player) && Player.hacknetNodes.length === HacknetServerConstants.MaxServers, + Condition: () => hasHacknetServers() && Player.hacknetNodes.length === HacknetServerConstants.MaxServers, AdditionalUnlock: [achievementData["30_HACKNET_NODE"].ID], }, MAX_HACKNET_SERVER: { @@ -530,7 +530,7 @@ export const achievements: IMap = { Icon: "HASHNETALL", Visible: () => hasAccessToSF(Player, 9), Condition: (): boolean => { - if (!hasHacknetServers(Player)) return false; + if (!hasHacknetServers()) return false; for (const h of Player.hacknetNodes) { if (typeof h !== "string") return false; const hs = GetServer(h); @@ -551,7 +551,7 @@ export const achievements: IMap = { ...achievementData["HACKNET_SERVER_1B"], Icon: "HASHNETMONEY", Visible: () => hasAccessToSF(Player, 9), - Condition: () => hasHacknetServers(Player) && Player.moneySourceB.hacknet >= 1e9, + Condition: () => hasHacknetServers() && Player.moneySourceB.hacknet >= 1e9, AdditionalUnlock: [achievementData.HACKNET_NODE_10M.ID], }, MAX_CACHE: { @@ -559,7 +559,7 @@ export const achievements: IMap = { Icon: "HASHNETCAP", Visible: () => hasAccessToSF(Player, 9), Condition: () => - hasHacknetServers(Player) && + hasHacknetServers() && Player.hashManager.hashes === Player.hashManager.capacity && Player.hashManager.capacity > 0, }, diff --git a/src/Augmentation/Augmentation.tsx b/src/Augmentation/Augmentation.tsx index e1154bb5c..9dafe06e0 100644 --- a/src/Augmentation/Augmentation.tsx +++ b/src/Augmentation/Augmentation.tsx @@ -8,7 +8,7 @@ import { Money } from "../ui/React/Money"; import { Generic_fromJSON, Generic_toJSON, IReviverValue, Reviver } from "../utils/JSONReviver"; import { FactionNames } from "../Faction/data/FactionNames"; -import { IPlayer } from "../PersonObjects/IPlayer"; +import { Player } from "../Player"; import { AugmentationNames } from "./data/AugmentationNames"; import { CONSTANTS } from "../Constants"; import { StaticAugmentations } from "./StaticAugmentations"; @@ -531,26 +531,26 @@ export class Augmentation { } } - getCost(player: IPlayer): AugmentationCosts { + getCost(): AugmentationCosts { const augmentationReference = StaticAugmentations[this.name]; let moneyCost = augmentationReference.baseCost; let repCost = augmentationReference.baseRepRequirement; if (augmentationReference.name === AugmentationNames.NeuroFluxGovernor) { - let nextLevel = this.getLevel(player); + let nextLevel = this.getLevel(); --nextLevel; const multiplier = Math.pow(CONSTANTS.NeuroFluxGovernorLevelMult, nextLevel); repCost = augmentationReference.baseRepRequirement * multiplier * BitNodeMultipliers.AugmentationRepCost; moneyCost = augmentationReference.baseCost * multiplier * BitNodeMultipliers.AugmentationMoneyCost; - for (let i = 0; i < player.queuedAugmentations.length; ++i) { + for (let i = 0; i < Player.queuedAugmentations.length; ++i) { moneyCost *= getBaseAugmentationPriceMultiplier(); } } else if (augmentationReference.factions.includes(FactionNames.ShadowsOfAnarchy)) { const soaAugmentationNames = initSoAAugmentations().map((augmentation) => augmentation.name); const soaMultiplier = Math.pow( CONSTANTS.SoACostMult, - soaAugmentationNames.filter((augmentationName) => player.hasAugmentation(augmentationName)).length, + soaAugmentationNames.filter((augmentationName) => Player.hasAugmentation(augmentationName)).length, ); moneyCost = augmentationReference.baseCost * soaMultiplier; if (soaAugmentationNames.find((augmentationName) => augmentationName === augmentationReference.name)) { @@ -566,19 +566,19 @@ export class Augmentation { return { moneyCost, repCost }; } - getLevel(player: IPlayer): number { + getLevel(): number { // Get current Neuroflux level based on Player's augmentations if (this.name === AugmentationNames.NeuroFluxGovernor) { let currLevel = 0; - for (let i = 0; i < player.augmentations.length; ++i) { - if (player.augmentations[i].name === AugmentationNames.NeuroFluxGovernor) { - currLevel = player.augmentations[i].level; + for (let i = 0; i < Player.augmentations.length; ++i) { + if (Player.augmentations[i].name === AugmentationNames.NeuroFluxGovernor) { + currLevel = Player.augmentations[i].level; } } // Account for purchased but uninstalled Augmentations - for (let i = 0; i < player.queuedAugmentations.length; ++i) { - if (player.queuedAugmentations[i].name == AugmentationNames.NeuroFluxGovernor) { + for (let i = 0; i < Player.queuedAugmentations.length; ++i) { + if (Player.queuedAugmentations[i].name == AugmentationNames.NeuroFluxGovernor) { ++currLevel; } } diff --git a/src/Augmentation/ui/AugmentationsRoot.tsx b/src/Augmentation/ui/AugmentationsRoot.tsx index 033ac95d6..f5d024c86 100644 --- a/src/Augmentation/ui/AugmentationsRoot.tsx +++ b/src/Augmentation/ui/AugmentationsRoot.tsx @@ -20,7 +20,7 @@ import Paper from "@mui/material/Paper"; import Container from "@mui/material/Container"; import { Settings } from "../../Settings/Settings"; import { ConfirmationModal } from "../../ui/React/ConfirmationModal"; -import { IPlayer } from "../../PersonObjects/IPlayer"; +import { Player } from "../../Player"; import { AugmentationNames } from "../data/AugmentationNames"; import { StaticAugmentations } from "../StaticAugmentations"; import { CONSTANTS } from "../../Constants"; @@ -29,12 +29,8 @@ import { Info } from "@mui/icons-material"; import { Link } from "@mui/material"; import { AlertEvents } from "../../ui/React/AlertManager"; -interface NFGDisplayProps { - player: IPlayer; -} - -const NeuroFluxDisplay = ({ player }: NFGDisplayProps): React.ReactElement => { - const level = player.augmentations.find((e) => e.name === AugmentationNames.NeuroFluxGovernor)?.level ?? 0; +const NeuroFluxDisplay = (): React.ReactElement => { + const level = Player.augmentations.find((e) => e.name === AugmentationNames.NeuroFluxGovernor)?.level ?? 0; const openBloodDonation = () => { AlertEvents.emit( @@ -67,18 +63,14 @@ const NeuroFluxDisplay = ({ player }: NFGDisplayProps): React.ReactElement => { ); }; -interface EntropyDisplayProps { - player: IPlayer; -} - -const EntropyDisplay = ({ player }: EntropyDisplayProps): React.ReactElement => { - return player.entropy > 0 ? ( +const EntropyDisplay = (): React.ReactElement => { + return Player.entropy > 0 ? ( - Entropy Virus - Level {player.entropy} + Entropy Virus - Level {Player.entropy} - All multipliers decreased by: {formatNumber((1 - CONSTANTS.EntropyEffect ** player.entropy) * 100, 3)}% + All multipliers decreased by: {formatNumber((1 - CONSTANTS.EntropyEffect ** Player.entropy) * 100, 3)}% (multiplicative) @@ -222,8 +214,8 @@ export function AugmentationsRoot(props: IProps): React.ReactElement { gap: 1, }} > - - + + diff --git a/src/Augmentation/ui/PurchasableAugmentations.tsx b/src/Augmentation/ui/PurchasableAugmentations.tsx index 27a8f927b..4b97c261e 100644 --- a/src/Augmentation/ui/PurchasableAugmentations.tsx +++ b/src/Augmentation/ui/PurchasableAugmentations.tsx @@ -6,7 +6,7 @@ import { CheckBox, CheckBoxOutlineBlank, CheckCircle, NewReleases, Report } from import { Box, Button, Container, Paper, Tooltip, Typography } from "@mui/material"; import React, { useState } from "react"; import { Faction } from "../../Faction/Faction"; -import { IPlayer } from "../../PersonObjects/IPlayer"; +import { Player } from "../../Player"; import { Settings } from "../../Settings/Settings"; import { numeralWrapper } from "../../ui/numeralFormat"; import { Augmentation } from "../Augmentation"; @@ -15,12 +15,11 @@ import { StaticAugmentations } from "../StaticAugmentations"; import { PurchaseAugmentationModal } from "./PurchaseAugmentationModal"; interface IPreReqsProps { - player: IPlayer; aug: Augmentation; } const PreReqs = (props: IPreReqsProps): React.ReactElement => { - const ownedPreReqs = props.aug.prereqs.filter((aug) => props.player.hasAugmentation(aug)); + const ownedPreReqs = props.aug.prereqs.filter((aug) => Player.hasAugmentation(aug)); const hasPreReqs = props.aug.prereqs.length > 0 && ownedPreReqs.length === props.aug.prereqs.length; return ( @@ -32,7 +31,7 @@ const PreReqs = (props: IPreReqsProps): React.ReactElement => {
{props.aug.prereqs.map((preAug) => ( { }; interface IExclusiveProps { - player: IPlayer; aug: Augmentation; } @@ -85,12 +83,12 @@ const Exclusive = (props: IExclusiveProps): React.ReactElement => {
  • {props.aug.factions[0]} faction
  • - {props.player.isAwareOfGang() && !props.aug.isSpecial && ( + {Player.isAwareOfGang() && !props.aug.isSpecial && (
  • Certain gangs
  • )} - {props.player.canAccessGrafting() && + {Player.canAccessGrafting() && !props.aug.isSpecial && props.aug.name !== AugmentationNames.TheRedPill && (
  • @@ -130,10 +128,9 @@ const Requirement = (props: IReqProps): React.ReactElement => { interface IPurchasableAugsProps { augNames: string[]; ownedAugNames: string[]; - player: IPlayer; - canPurchase: (player: IPlayer, aug: Augmentation) => boolean; - purchaseAugmentation: (player: IPlayer, aug: Augmentation, showModal: (open: boolean) => void) => void; + canPurchase: (aug: Augmentation) => boolean; + purchaseAugmentation: (aug: Augmentation, showModal: (open: boolean) => void) => void; rep?: number; sleeveAugs?: boolean; @@ -167,7 +164,7 @@ export function PurchasableAugmentation(props: IPurchasableAugProps): React.Reac const [open, setOpen] = useState(false); const aug = StaticAugmentations[props.augName]; - const augCosts = aug.getCost(props.parent.player); + const augCosts = aug.getCost(); const cost = props.parent.sleeveAugs ? aug.baseCost : augCosts.moneyCost; const repCost = augCosts.repCost; const info = typeof aug.info === "string" ? {aug.info} : aug.info; @@ -195,11 +192,11 @@ export function PurchasableAugmentation(props: IPurchasableAugProps): React.Reac ) : ( - + )} ); diff --git a/src/Bladeburner/ui/BladeburnerRoot.tsx b/src/Bladeburner/ui/BladeburnerRoot.tsx index 593874a62..ca19f4c93 100644 --- a/src/Bladeburner/ui/BladeburnerRoot.tsx +++ b/src/Bladeburner/ui/BladeburnerRoot.tsx @@ -24,11 +24,11 @@ export function BladeburnerRoot(): React.ReactElement { return ( - - + + - + ); } diff --git a/src/Bladeburner/ui/Console.tsx b/src/Bladeburner/ui/Console.tsx index 8a6a82935..bcc07b447 100644 --- a/src/Bladeburner/ui/Console.tsx +++ b/src/Bladeburner/ui/Console.tsx @@ -2,7 +2,6 @@ import React, { useState, useRef, useEffect } from "react"; import { IBladeburner } from "../IBladeburner"; import { KEY } from "../../utils/helpers/keyCodes"; -import { IPlayer } from "../../PersonObjects/IPlayer"; import Paper from "@mui/material/Paper"; import List from "@mui/material/List"; import ListItem from "@mui/material/ListItem"; @@ -50,7 +49,6 @@ function Line(props: ILineProps): React.ReactElement { interface IProps { bladeburner: IBladeburner; - player: IPlayer; } export function Console(props: IProps): React.ReactElement { @@ -81,7 +79,7 @@ export function Console(props: IProps): React.ReactElement { event.preventDefault(); if (command.length > 0) { props.bladeburner.postToConsole("> " + command); - props.bladeburner.executeConsoleCommands(props.player, command); + props.bladeburner.executeConsoleCommands(command); setConsoleHistoryIndex(props.bladeburner.consoleHistory.length); setCommand(""); } diff --git a/src/Bladeburner/ui/ContractElem.tsx b/src/Bladeburner/ui/ContractElem.tsx index 5edf04842..376236ca7 100644 --- a/src/Bladeburner/ui/ContractElem.tsx +++ b/src/Bladeburner/ui/ContractElem.tsx @@ -5,7 +5,7 @@ import { formatNumber, convertTimeMsToTimeElapsedString } from "../../utils/Stri import { Contracts } from "../data/Contracts"; import { IBladeburner } from "../IBladeburner"; import { IAction } from "../IAction"; -import { IPlayer } from "../../PersonObjects/IPlayer"; +import { Player } from "../../Player"; import { SuccessChance } from "./SuccessChance"; import { CopyableText } from "../../ui/React/CopyableText"; import { ActionLevel } from "./ActionLevel"; @@ -17,7 +17,6 @@ import Paper from "@mui/material/Paper"; interface IProps { bladeburner: IBladeburner; - player: IPlayer; action: IAction; } @@ -32,7 +31,7 @@ export function ContractElem(props: IProps): React.ReactElement { props.bladeburner.actionTimeCurrent + props.bladeburner.actionTimeOverflow, props.bladeburner.actionTimeToComplete, ); - const actionTime = props.action.getActionTime(props.bladeburner, props.player); + const actionTime = props.action.getActionTime(props.bladeburner, Player); const actionData = Contracts[props.action.name]; if (actionData === undefined) { diff --git a/src/Bladeburner/ui/ContractList.tsx b/src/Bladeburner/ui/ContractList.tsx index 7bd24c53b..499a437fe 100644 --- a/src/Bladeburner/ui/ContractList.tsx +++ b/src/Bladeburner/ui/ContractList.tsx @@ -1,11 +1,9 @@ import React from "react"; import { ContractElem } from "./ContractElem"; import { IBladeburner } from "../IBladeburner"; -import { IPlayer } from "../../PersonObjects/IPlayer"; interface IProps { bladeburner: IBladeburner; - player: IPlayer; } export function ContractList(props: IProps): React.ReactElement { @@ -14,7 +12,7 @@ export function ContractList(props: IProps): React.ReactElement { return ( <> {names.map((name: string) => ( - + ))} ); diff --git a/src/Bladeburner/ui/ContractPage.tsx b/src/Bladeburner/ui/ContractPage.tsx index 9a3e96a6d..0af07e41c 100644 --- a/src/Bladeburner/ui/ContractPage.tsx +++ b/src/Bladeburner/ui/ContractPage.tsx @@ -1,12 +1,10 @@ import * as React from "react"; import { ContractList } from "./ContractList"; import { IBladeburner } from "../IBladeburner"; -import { IPlayer } from "../../PersonObjects/IPlayer"; import Typography from "@mui/material/Typography"; interface IProps { bladeburner: IBladeburner; - player: IPlayer; } export function ContractPage(props: IProps): React.ReactElement { @@ -20,7 +18,7 @@ export function ContractPage(props: IProps): React.ReactElement { You can unlock higher-level contracts by successfully completing them. Higher-level contracts are more difficult, but grant more rank, experience, and money. - + ); } diff --git a/src/Bladeburner/ui/GeneralActionElem.tsx b/src/Bladeburner/ui/GeneralActionElem.tsx index b064b298d..09b1de249 100644 --- a/src/Bladeburner/ui/GeneralActionElem.tsx +++ b/src/Bladeburner/ui/GeneralActionElem.tsx @@ -5,7 +5,7 @@ import { formatNumber, convertTimeMsToTimeElapsedString } from "../../utils/Stri import { IBladeburner } from "../IBladeburner"; import { IAction } from "../IAction"; import { GeneralActions } from "../data/GeneralActions"; -import { IPlayer } from "../../PersonObjects/IPlayer"; +import { Player } from "../../Player"; import { CopyableText } from "../../ui/React/CopyableText"; import { StartButton } from "./StartButton"; @@ -16,7 +16,6 @@ import Paper from "@mui/material/Paper"; interface IProps { bladeburner: IBladeburner; - player: IPlayer; action: IAction; } @@ -40,13 +39,13 @@ export function GeneralActionElem(props: IProps): React.ReactElement { case "Incite Violence": return 60; case "Recruitment": - return props.bladeburner.getRecruitmentTime(props.player); + return props.bladeburner.getRecruitmentTime(Player); } return -1; // dead code })(); const successChance = props.action.name === "Recruitment" - ? Math.max(0, Math.min(props.bladeburner.getRecruitmentSuccessChance(props.player), 1)) + ? Math.max(0, Math.min(props.bladeburner.getRecruitmentSuccessChance(Player), 1)) : -1; const actionData = GeneralActions[props.action.name]; diff --git a/src/Bladeburner/ui/GeneralActionList.tsx b/src/Bladeburner/ui/GeneralActionList.tsx index 5693d4925..27e52fbc9 100644 --- a/src/Bladeburner/ui/GeneralActionList.tsx +++ b/src/Bladeburner/ui/GeneralActionList.tsx @@ -3,11 +3,9 @@ import { GeneralActionElem } from "./GeneralActionElem"; import { Action } from "../Action"; import { GeneralActions } from "../GeneralActions"; import { IBladeburner } from "../IBladeburner"; -import { IPlayer } from "../../PersonObjects/IPlayer"; interface IProps { bladeburner: IBladeburner; - player: IPlayer; } export function GeneralActionList(props: IProps): React.ReactElement { @@ -20,7 +18,7 @@ export function GeneralActionList(props: IProps): React.ReactElement { return ( <> {actions.map((action: Action) => ( - + ))} ); diff --git a/src/Bladeburner/ui/GeneralActionPage.tsx b/src/Bladeburner/ui/GeneralActionPage.tsx index 9893f210c..10d27a86d 100644 --- a/src/Bladeburner/ui/GeneralActionPage.tsx +++ b/src/Bladeburner/ui/GeneralActionPage.tsx @@ -1,19 +1,17 @@ import * as React from "react"; import { GeneralActionList } from "./GeneralActionList"; import { IBladeburner } from "../IBladeburner"; -import { IPlayer } from "../../PersonObjects/IPlayer"; import Typography from "@mui/material/Typography"; interface IProps { bladeburner: IBladeburner; - player: IPlayer; } export function GeneralActionPage(props: IProps): React.ReactElement { return ( <> These are generic actions that will assist you in your Bladeburner duties. - + ); } diff --git a/src/Bladeburner/ui/OperationElem.tsx b/src/Bladeburner/ui/OperationElem.tsx index e217e4225..ea39d68d6 100644 --- a/src/Bladeburner/ui/OperationElem.tsx +++ b/src/Bladeburner/ui/OperationElem.tsx @@ -10,7 +10,7 @@ import { TeamSizeButton } from "./TeamSizeButton"; import { IBladeburner } from "../IBladeburner"; import { Operation } from "../Operation"; import { Operations } from "../data/Operations"; -import { IPlayer } from "../../PersonObjects/IPlayer"; +import { Player } from "../../Player"; import { CopyableText } from "../../ui/React/CopyableText"; import Typography from "@mui/material/Typography"; @@ -18,7 +18,6 @@ import Paper from "@mui/material/Paper"; interface IProps { bladeburner: IBladeburner; - player: IPlayer; action: Operation; } @@ -33,7 +32,7 @@ export function OperationElem(props: IProps): React.ReactElement { props.bladeburner.actionTimeCurrent + props.bladeburner.actionTimeOverflow, props.bladeburner.actionTimeToComplete, ); - const actionTime = props.action.getActionTime(props.bladeburner, props.player); + const actionTime = props.action.getActionTime(props.bladeburner, Player); const actionData = Operations[props.action.name]; if (actionData === undefined) { diff --git a/src/Bladeburner/ui/OperationList.tsx b/src/Bladeburner/ui/OperationList.tsx index e18b8cdc4..eacb779bc 100644 --- a/src/Bladeburner/ui/OperationList.tsx +++ b/src/Bladeburner/ui/OperationList.tsx @@ -1,11 +1,9 @@ import React from "react"; import { OperationElem } from "./OperationElem"; import { IBladeburner } from "../IBladeburner"; -import { IPlayer } from "../../PersonObjects/IPlayer"; interface IProps { bladeburner: IBladeburner; - player: IPlayer; } export function OperationList(props: IProps): React.ReactElement { @@ -14,7 +12,7 @@ export function OperationList(props: IProps): React.ReactElement { return ( <> {names.map((name: string) => ( - + ))} ); diff --git a/src/Bladeburner/ui/OperationPage.tsx b/src/Bladeburner/ui/OperationPage.tsx index 4b5b0a261..3557a8867 100644 --- a/src/Bladeburner/ui/OperationPage.tsx +++ b/src/Bladeburner/ui/OperationPage.tsx @@ -1,12 +1,10 @@ import * as React from "react"; import { OperationList } from "./OperationList"; import { IBladeburner } from "../IBladeburner"; -import { IPlayer } from "../../PersonObjects/IPlayer"; import Typography from "@mui/material/Typography"; interface IProps { bladeburner: IBladeburner; - player: IPlayer; } export function OperationPage(props: IProps): React.ReactElement { @@ -29,7 +27,7 @@ export function OperationPage(props: IProps): React.ReactElement { You can unlock higher-level operations by successfully completing them. Higher-level operations are more difficult, but grant more rank and experience. - + ); } diff --git a/src/Bladeburner/ui/StartButton.tsx b/src/Bladeburner/ui/StartButton.tsx index 18f30b869..2bbedb947 100644 --- a/src/Bladeburner/ui/StartButton.tsx +++ b/src/Bladeburner/ui/StartButton.tsx @@ -34,7 +34,7 @@ export function StartButton(props: IProps): React.ReactElement { props.bladeburner.action.type = props.type; props.bladeburner.action.name = props.name; if (!player.hasAugmentation(AugmentationNames.BladesSimulacrum, true)) player.finishWork(true); - props.bladeburner.startAction(player, props.bladeburner.action); + props.bladeburner.startAction(props.bladeburner.action); props.rerender(); } diff --git a/src/Bladeburner/ui/Stats.tsx b/src/Bladeburner/ui/Stats.tsx index 477852b61..a9d1d0930 100644 --- a/src/Bladeburner/ui/Stats.tsx +++ b/src/Bladeburner/ui/Stats.tsx @@ -1,11 +1,11 @@ import React, { useState, useEffect } from "react"; import { formatNumber, convertTimeMsToTimeElapsedString } from "../../utils/StringHelperFunctions"; import { BladeburnerConstants } from "../data/Constants"; -import { IPlayer } from "../../PersonObjects/IPlayer"; +import { Player } from "../../Player"; import { Money } from "../../ui/React/Money"; import { numeralWrapper } from "../../ui/numeralFormat"; import { Factions } from "../../Faction/Factions"; -import { IRouter } from "../../ui/Router"; +import { Router } from "../../ui/GameRoot"; import { joinFaction } from "../../Faction/FactionHelpers"; import { IBladeburner } from "../IBladeburner"; @@ -19,8 +19,6 @@ import { FactionNames } from "../../Faction/data/FactionNames"; interface IProps { bladeburner: IBladeburner; - router: IRouter; - player: IPlayer; } export function Stats(props: IProps): React.ReactElement { @@ -40,7 +38,7 @@ export function Stats(props: IProps): React.ReactElement { joinFaction(faction); } - props.router.toFaction(faction); + Router.toFaction(faction); } return ( @@ -170,13 +168,13 @@ export function Stats(props: IProps): React.ReactElement { Skill Points: {formatNumber(props.bladeburner.skillPoints, 0)}
    - Aug. Success Chance mult: {formatNumber(props.player.mults.bladeburner_success_chance * 100, 1)}% + Aug. Success Chance mult: {formatNumber(Player.mults.bladeburner_success_chance * 100, 1)}%
    - Aug. Max Stamina mult: {formatNumber(props.player.mults.bladeburner_max_stamina * 100, 1)}% + Aug. Max Stamina mult: {formatNumber(Player.mults.bladeburner_max_stamina * 100, 1)}%
    - Aug. Stamina Gain mult: {formatNumber(props.player.mults.bladeburner_stamina_gain * 100, 1)}% + Aug. Stamina Gain mult: {formatNumber(Player.mults.bladeburner_stamina_gain * 100, 1)}%
    - Aug. Field Analysis mult: {formatNumber(props.player.mults.bladeburner_analysis * 100, 1)}% + Aug. Field Analysis mult: {formatNumber(Player.mults.bladeburner_analysis * 100, 1)}%
    diff --git a/src/Casino/Blackjack.tsx b/src/Casino/Blackjack.tsx index 542989e0d..54eb13b85 100644 --- a/src/Casino/Blackjack.tsx +++ b/src/Casino/Blackjack.tsx @@ -1,8 +1,8 @@ import * as React from "react"; -import { IPlayer } from "../PersonObjects/IPlayer"; +import { Player } from "../Player"; import { Money } from "../ui/React/Money"; -import { Game, reachedLimit } from "./Game"; +import { win, reachedLimit } from "./Game"; import { Deck } from "./CardDeck/Deck"; import { Hand } from "./CardDeck/Hand"; import { InputAdornment } from "@mui/material"; @@ -24,10 +24,6 @@ enum Result { Tie = "Push! (Tie)", } -type Props = { - p: IPlayer; -}; - type State = { playerHand: Hand; dealerHand: Hand; @@ -40,11 +36,11 @@ type State = { wagerInvalidHelperText: string; }; -export class Blackjack extends Game { +export class Blackjack extends React.Component<{},State> { deck: Deck; - constructor(props: Props) { - super(props); + constructor() { + super({}); this.deck = new Deck(DECK_COUNT); @@ -64,20 +60,19 @@ export class Blackjack extends Game { } canStartGame = (): boolean => { - const { p } = this.props; const { bet } = this.state; - return p.canAfford(bet); + return Player.canAfford(bet); }; startGame = (): void => { - if (!this.canStartGame() || reachedLimit(this.props.p)) { + if (!this.canStartGame() || reachedLimit()) { return; } // 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) TODO: Save/Restore the RNG state to limit the value of save-scumming. - this.props.p.loseMoney(this.state.bet, "casino"); + win(-this.state.bet); const playerHand = new Hand([this.deck.safeDrawCard(), this.deck.safeDrawCard()]); const dealerHand = new Hand([this.deck.safeDrawCard(), this.deck.safeDrawCard()]); @@ -230,7 +225,7 @@ export class Blackjack extends Game { : (() => { throw new Error(`Unexpected result: ${result}`); })(); // This can't happen, right? - this.win(this.props.p, gains); + win(gains); this.setState({ gameInProgress: false, result, @@ -239,7 +234,6 @@ export class Blackjack extends Game { }; wagerOnChange = (event: React.ChangeEvent): void => { - const { p } = this.props; const betInput = event.target.value; const wager = Math.round(parseFloat(betInput)); if (isNaN(wager)) { @@ -263,7 +257,7 @@ export class Blackjack extends Game { wagerInvalid: true, wagerInvalidHelperText: "Exceeds max bet", }); - } else if (!p.canAfford(wager)) { + } else if (!Player.canAfford(wager)) { this.setState({ bet: 0, betInput, diff --git a/src/Casino/CoinFlip.tsx b/src/Casino/CoinFlip.tsx index 17b09488c..32fdae274 100644 --- a/src/Casino/CoinFlip.tsx +++ b/src/Casino/CoinFlip.tsx @@ -5,7 +5,6 @@ */ import React, { useState } from "react"; -import { IPlayer } from "../PersonObjects/IPlayer"; import { BadRNG } from "./RNG"; import { win, reachedLimit } from "./Game"; import { trusted } from "./utils"; @@ -15,14 +14,10 @@ import TextField from "@mui/material/TextField"; import Button from "@mui/material/Button"; import Box from "@mui/material/Box"; -type IProps = { - p: IPlayer; -}; - const minPlay = 0; const maxPlay = 10e3; -export function CoinFlip(props: IProps): React.ReactElement { +export function CoinFlip(): React.ReactElement { const [investment, setInvestment] = useState(1000); const [result, setResult] = useState( ); const [status, setStatus] = useState(""); @@ -43,7 +38,7 @@ export function CoinFlip(props: IProps): React.ReactElement { } function play(guess: string): void { - if (reachedLimit(props.p)) return; + if (reachedLimit()) return; const v = BadRNG.random(); let letter: string; if (v < 0.5) { @@ -65,11 +60,11 @@ export function CoinFlip(props: IProps): React.ReactElement { setTimeout(() => setPlayLock(false), 250); if (correct) { - win(props.p, investment); + win(investment); } else { - win(props.p, -investment); + win(-investment); } - if (reachedLimit(props.p)) return; + if (reachedLimit()) return; } return ( diff --git a/src/Casino/Game.ts b/src/Casino/Game.ts new file mode 100644 index 000000000..378f4f0cd --- /dev/null +++ b/src/Casino/Game.ts @@ -0,0 +1,16 @@ +import { Player } from "../Player"; +import { dialogBoxCreate } from "../ui/React/DialogBox"; + +const gainLimit = 10e9; + +export function win(n: number): void { + Player.gainMoney(n, "casino"); +} + +export function reachedLimit(): boolean { + const reached = Player.getCasinoWinnings() > gainLimit; + if (reached) { + dialogBoxCreate("Alright cheater get out of here. You're not allowed here anymore."); + } + return reached; +} \ No newline at end of file diff --git a/src/Casino/Game.tsx b/src/Casino/Game.tsx deleted file mode 100644 index b20eda813..000000000 --- a/src/Casino/Game.tsx +++ /dev/null @@ -1,31 +0,0 @@ -import * as React from "react"; -import { IPlayer } from "../PersonObjects/IPlayer"; -import { dialogBoxCreate } from "../ui/React/DialogBox"; - -const gainLimit = 10e9; - -export function win(p: IPlayer, n: number): void { - p.gainMoney(n, "casino"); -} - -export function reachedLimit(p: IPlayer): boolean { - const reached = p.getCasinoWinnings() > gainLimit; - if (reached) { - dialogBoxCreate("Alright cheater get out of here. You're not allowed here anymore."); - } - return reached; -} - -export class Game extends React.Component { - win(p: IPlayer, n: number): void { - p.gainMoney(n, "casino"); - } - - reachedLimit(p: IPlayer): boolean { - const reached = p.getCasinoWinnings() > gainLimit; - if (reached) { - dialogBoxCreate("Alright cheater get out of here. You're not allowed here anymore."); - } - return reached; - } -} diff --git a/src/Casino/Roulette.tsx b/src/Casino/Roulette.tsx index da1dd59d2..f45af1cb3 100644 --- a/src/Casino/Roulette.tsx +++ b/src/Casino/Roulette.tsx @@ -1,6 +1,5 @@ import React, { useState, useEffect } from "react"; -import { IPlayer } from "../PersonObjects/IPlayer"; import { Money } from "../ui/React/Money"; import { win, reachedLimit } from "./Game"; import { WHRNG } from "./RNG"; @@ -9,10 +8,6 @@ import Typography from "@mui/material/Typography"; import Button from "@mui/material/Button"; import TextField from "@mui/material/TextField"; -type IProps = { - p: IPlayer; -}; - const minPlay = 0; const maxPlay = 1e7; @@ -111,7 +106,7 @@ function Single(s: number): Strategy { }; } -export function Roulette(props: IProps): React.ReactElement { +export function Roulette(): React.ReactElement { const [rng] = useState(new WHRNG(new Date().getTime())); const [investment, setInvestment] = useState(1000); const [canPlay, setCanPlay] = useState(true); @@ -151,7 +146,7 @@ export function Roulette(props: IProps): React.ReactElement { } function play(strategy: Strategy): void { - if (reachedLimit(props.p)) return; + if (reachedLimit()) return; setCanPlay(false); setLock(false); @@ -184,14 +179,14 @@ export function Roulette(props: IProps): React.ReactElement { ); } - win(props.p, gain); + win(gain); setCanPlay(true); setLock(true); setStatus(status); setN(n); - reachedLimit(props.p); + reachedLimit(); }, 1600); } diff --git a/src/Casino/SlotMachine.tsx b/src/Casino/SlotMachine.tsx index a7fdbd083..6655f041b 100644 --- a/src/Casino/SlotMachine.tsx +++ b/src/Casino/SlotMachine.tsx @@ -1,6 +1,6 @@ import React, { useState, useEffect } from "react"; -import { IPlayer } from "../PersonObjects/IPlayer"; +import { Player } from "../Player"; import { Money } from "../ui/React/Money"; import { WHRNG } from "./RNG"; import { win, reachedLimit } from "./Game"; @@ -9,10 +9,6 @@ import Typography from "@mui/material/Typography"; import TextField from "@mui/material/TextField"; import Button from "@mui/material/Button"; -type IProps = { - p: IPlayer; -}; - // statically shuffled array of symbols. const symbols = [ "D", @@ -141,8 +137,8 @@ const payLines = [ const minPlay = 0; const maxPlay = 1e6; -export function SlotMachine(props: IProps): React.ReactElement { - const [rng] = useState(new WHRNG(props.p.totalPlaytime)); +export function SlotMachine(): React.ReactElement { + const [rng] = useState(new WHRNG(Player.totalPlaytime)); const [index, setIndex] = useState([0, 0, 0, 0, 0]); const [locks, setLocks] = useState([0, 0, 0, 0, 0]); const [investment, setInvestment] = useState(1000); @@ -191,9 +187,9 @@ export function SlotMachine(props: IProps): React.ReactElement { } function play(): void { - if (reachedLimit(props.p)) return; + if (reachedLimit()) return; setStatus("playing"); - win(props.p, -investment); + win(-investment); if (!canPlay) return; unlock(); setTimeout(lock, rng.random() * 2000 + 1000); @@ -235,7 +231,7 @@ export function SlotMachine(props: IProps): React.ReactElement { if (count < 3) continue; const payout = getPayout(data[0], count - 3); gains += investment * payout; - win(props.p, investment * payout); + win(investment * payout); } setStatus( @@ -244,7 +240,7 @@ export function SlotMachine(props: IProps): React.ReactElement { , ); setCanPlay(true); - if (reachedLimit(props.p)) return; + if (reachedLimit()) return; } function unlock(): void { diff --git a/src/Corporation/Actions.ts b/src/Corporation/Actions.ts index bf53d1e2f..07e475b6f 100644 --- a/src/Corporation/Actions.ts +++ b/src/Corporation/Actions.ts @@ -1,5 +1,4 @@ import { Player } from "../Player"; -import { IPlayer } from "src/PersonObjects/IPlayer"; import { MaterialSizes } from "./MaterialSizes"; import { ICorporation } from "./ICorporation"; import { Corporation } from "./Corporation"; @@ -271,7 +270,7 @@ export function BulkPurchase(corp: ICorporation, warehouse: Warehouse, material: } } -export function SellShares(corporation: ICorporation, player: IPlayer, numShares: number): number { +export function SellShares(corporation: ICorporation, numShares: number): number { if (isNaN(numShares)) throw new Error("Invalid value for number of shares"); if (numShares < 0) throw new Error("Invalid value for number of shares"); if (numShares > corporation.numShares) throw new Error("You don't have that many shares to sell!"); @@ -287,20 +286,20 @@ export function SellShares(corporation: ICorporation, player: IPlayer, numShares corporation.sharePrice = newSharePrice; corporation.shareSalesUntilPriceUpdate = newSharesUntilUpdate; corporation.shareSaleCooldown = CorporationConstants.SellSharesCooldown; - player.gainMoney(profit, "corporation"); + Player.gainMoney(profit, "corporation"); return profit; } -export function BuyBackShares(corporation: ICorporation, player: IPlayer, numShares: number): boolean { +export function BuyBackShares(corporation: ICorporation, numShares: number): boolean { if (isNaN(numShares)) throw new Error("Invalid value for number of shares"); if (numShares < 0) throw new Error("Invalid value for number of shares"); if (numShares > corporation.issuedShares) throw new Error("You don't have that many shares to buy!"); if (!corporation.public) throw new Error("You haven't gone public!"); const buybackPrice = corporation.sharePrice * 1.1; - if (player.money < numShares * buybackPrice) throw new Error("You cant afford that many shares!"); + if (Player.money < numShares * buybackPrice) throw new Error("You cant afford that many shares!"); corporation.numShares += numShares; corporation.issuedShares -= numShares; - player.loseMoney(numShares * buybackPrice, "corporation"); + Player.loseMoney(numShares * buybackPrice, "corporation"); return true; } diff --git a/src/Corporation/Corporation.tsx b/src/Corporation/Corporation.tsx index d9643eddf..edb3314e0 100644 --- a/src/Corporation/Corporation.tsx +++ b/src/Corporation/Corporation.tsx @@ -8,7 +8,7 @@ import { Industry } from "./Industry"; import { BitNodeMultipliers } from "../BitNode/BitNodeMultipliers"; import { showLiterature } from "../Literature/LiteratureHelpers"; import { LiteratureNames } from "../Literature/data/LiteratureNames"; -import { IPlayer } from "../PersonObjects/IPlayer"; +import { Player } from "../Player"; import { dialogBoxCreate } from "../ui/React/DialogBox"; import { Reviver, Generic_toJSON, Generic_fromJSON, IReviverValue } from "../utils/JSONReviver"; @@ -76,7 +76,7 @@ export class Corporation { this.storedCycles += numCycles; } - process(player: IPlayer): void { + process(): void { if (this.storedCycles >= CorporationConstants.CyclesPerIndustryStateCycle) { const state = this.getState(); const marketCycles = 1; @@ -139,7 +139,7 @@ export class Corporation { } else { const totalDividends = this.dividendRate * cycleProfit; const retainedEarnings = cycleProfit - totalDividends; - player.gainMoney(this.getCycleDividends(), "corporation"); + Player.gainMoney(this.getCycleDividends(), "corporation"); this.addFunds(retainedEarnings); } } else { @@ -428,9 +428,9 @@ export class Corporation { // Adds the Corporation Handbook (Starter Guide) to the player's home computer. // This is a lit file that gives introductory info to the player // This occurs when the player clicks the "Getting Started Guide" button on the overview panel - getStarterGuide(player: IPlayer): void { + getStarterGuide(): void { // Check if player already has Corporation Handbook - const homeComp = player.getHomeComputer(); + const homeComp = Player.getHomeComputer(); let hasHandbook = false; const handbookFn = LiteratureNames.CorporationManagementHandbook; for (let i = 0; i < homeComp.messages.length; ++i) { diff --git a/src/Corporation/ui/Industry.tsx b/src/Corporation/ui/Industry.tsx index 9c1fafadf..c02643db8 100644 --- a/src/Corporation/ui/Industry.tsx +++ b/src/Corporation/ui/Industry.tsx @@ -31,7 +31,6 @@ export function Industry(props: IProps): React.ReactElement { void; } diff --git a/src/Corporation/ui/modals/BuybackSharesModal.tsx b/src/Corporation/ui/modals/BuybackSharesModal.tsx index 5d6b33e49..2e92cdcd9 100644 --- a/src/Corporation/ui/modals/BuybackSharesModal.tsx +++ b/src/Corporation/ui/modals/BuybackSharesModal.tsx @@ -35,7 +35,7 @@ export function BuybackSharesModal(props: IProps): React.ReactElement { function buy(): void { if (disabled) return; try { - BuyBackShares(corp, player, shares); + BuyBackShares(corp, shares); } catch (err) { dialogBoxCreate(err + ""); } diff --git a/src/Corporation/ui/modals/CreateCorporationModal.tsx b/src/Corporation/ui/modals/CreateCorporationModal.tsx index 2c63baf4e..9e77fcc14 100644 --- a/src/Corporation/ui/modals/CreateCorporationModal.tsx +++ b/src/Corporation/ui/modals/CreateCorporationModal.tsx @@ -72,7 +72,7 @@ export function CreateCorporationModal(props: IProps): React.ReactElement { )} ); diff --git a/src/Corporation/ui/modals/SellSharesModal.tsx b/src/Corporation/ui/modals/SellSharesModal.tsx index 5a414d0d7..fdb178029 100644 --- a/src/Corporation/ui/modals/SellSharesModal.tsx +++ b/src/Corporation/ui/modals/SellSharesModal.tsx @@ -49,7 +49,7 @@ export function SellSharesModal(props: IProps): React.ReactElement { function sell(): void { if (disabled) return; try { - const profit = SellShares(corp, player, shares); + const profit = SellShares(corp, shares); props.onClose(); dialogBoxCreate( <> diff --git a/src/Crime/CrimeHelpers.ts b/src/Crime/CrimeHelpers.ts index dbbec2f35..56cbe7bc6 100644 --- a/src/Crime/CrimeHelpers.ts +++ b/src/Crime/CrimeHelpers.ts @@ -1,16 +1,16 @@ import { Crimes } from "./Crimes"; import { Crime } from "./Crime"; -import { IPlayer } from "../PersonObjects/IPlayer"; +import { Player } from "../Player"; import { dialogBoxCreate } from "../ui/React/DialogBox"; -export function determineCrimeSuccess(p: IPlayer, type: string): boolean { +export function determineCrimeSuccess(type: string): boolean { let chance = 0; let found = false; for (const i of Object.keys(Crimes)) { const crime = Crimes[i]; if (crime.type === type) { - chance = crime.successRate(p); + chance = crime.successRate(Player); found = true; break; } diff --git a/src/DevMenu.tsx b/src/DevMenu.tsx index 6bcb2eab3..b590fc6df 100644 --- a/src/DevMenu.tsx +++ b/src/DevMenu.tsx @@ -1,7 +1,5 @@ -import { IPlayer } from "./PersonObjects/IPlayer"; +import { Player } from "./Player"; import { Bladeburner } from "./Bladeburner/Bladeburner"; -import { IEngine } from "./IEngine"; -import { IRouter } from "./ui/Router"; import { AugmentationNames } from "./Augmentation/data/AugmentationNames"; import React, { useEffect } from "react"; @@ -28,44 +26,38 @@ import { Entropy } from "./DevMenu/ui/Entropy"; import Typography from "@mui/material/Typography"; import { Exploit } from "./Exploits/Exploit"; -interface IProps { - player: IPlayer; - engine: IEngine; - router: IRouter; -} - -export function DevMenuRoot(props: IProps): React.ReactElement { +export function DevMenuRoot(): React.ReactElement { useEffect(() => { - props.player.giveExploit(Exploit.YoureNotMeantToAccessThis); + Player.giveExploit(Exploit.YoureNotMeantToAccessThis); }, []); return ( <> Development Menu - Only meant to be used for testing/debugging - - - - - - + + + + + + - {props.player.bladeburner instanceof Bladeburner && } + {Player.bladeburner instanceof Bladeburner && } - {props.player.inGang() && } + {Player.inGang() && } - {props.player.hasCorporation() && } + {Player.hasCorporation() && } - {props.player.hasWseAccount && } + {Player.hasWseAccount && } - {props.player.sleeves.length > 0 && } - {props.player.augmentations.some((aug) => aug.name === AugmentationNames.StaneksGift1) && } + {Player.sleeves.length > 0 && } + {Player.augmentations.some((aug) => aug.name === AugmentationNames.StaneksGift1) && } - - - + + + ); diff --git a/src/DevMenu/ui/Achievements.tsx b/src/DevMenu/ui/Achievements.tsx index 1bba149ed..3cb2bdad3 100644 --- a/src/DevMenu/ui/Achievements.tsx +++ b/src/DevMenu/ui/Achievements.tsx @@ -11,44 +11,39 @@ import { Tooltip } from "@mui/material"; import LockIcon from "@mui/icons-material/Lock"; import LockOpenIcon from "@mui/icons-material/LockOpen"; -import { IPlayer } from "../../PersonObjects/IPlayer"; +import { Player } from "../../Player"; import { achievements } from "../../Achievements/Achievements"; -import { IEngine } from "../../IEngine"; +import { Engine } from "../../engine"; -interface IProps { - player: IPlayer; - engine: IEngine; -} - -export function Achievements(props: IProps): React.ReactElement { - const [playerAchievement, setPlayerAchievements] = useState(props.player.achievements.map((m) => m.ID)); +export function Achievements(): React.ReactElement { + const [playerAchievement, setPlayerAchievements] = useState(Player.achievements.map((m) => m.ID)); function grantAchievement(id: string): void { - props.player.giveAchievement(id); - setPlayerAchievements(props.player.achievements.map((m) => m.ID)); + Player.giveAchievement(id); + setPlayerAchievements(Player.achievements.map((m) => m.ID)); } function grantAllAchievements(): void { - Object.values(achievements).forEach((a) => props.player.giveAchievement(a.ID)); - setPlayerAchievements(props.player.achievements.map((m) => m.ID)); + Object.values(achievements).forEach((a) => Player.giveAchievement(a.ID)); + setPlayerAchievements(Player.achievements.map((m) => m.ID)); } function removeAchievement(id: string): void { - props.player.achievements = props.player.achievements.filter((a) => a.ID !== id); - setPlayerAchievements(props.player.achievements.map((m) => m.ID)); + Player.achievements = Player.achievements.filter((a) => a.ID !== id); + setPlayerAchievements(Player.achievements.map((m) => m.ID)); } function clearAchievements(): void { - props.player.achievements = []; - setPlayerAchievements(props.player.achievements.map((m) => m.ID)); + Player.achievements = []; + setPlayerAchievements(Player.achievements.map((m) => m.ID)); } function disableEngine(): void { - props.engine.Counters.achievementsCounter = Number.MAX_VALUE; + Engine.Counters.achievementsCounter = Number.MAX_VALUE; } function enableEngine(): void { - props.engine.Counters.achievementsCounter = 0; + Engine.Counters.achievementsCounter = 0; } return ( diff --git a/src/DevMenu/ui/Augmentations.tsx b/src/DevMenu/ui/Augmentations.tsx index 7f129495c..caa174bd6 100644 --- a/src/DevMenu/ui/Augmentations.tsx +++ b/src/DevMenu/ui/Augmentations.tsx @@ -12,34 +12,30 @@ import { } from "@mui/material"; import React, { useState } from "react"; import { AugmentationNames } from "../../Augmentation/data/AugmentationNames"; -import { IPlayer } from "../../PersonObjects/IPlayer"; +import { Player } from "../../Player"; -interface IProps { - player: IPlayer; -} - -export function Augmentations(props: IProps): React.ReactElement { +export function Augmentations(): React.ReactElement { const [augmentation, setAugmentation] = useState("Augmented Targeting I"); function setAugmentationDropdown(event: SelectChangeEvent): void { setAugmentation(event.target.value); } function queueAug(): void { - props.player.queueAugmentation(augmentation); + Player.queueAugmentation(augmentation); } function queueAllAugs(): void { for (const augName of Object.values(AugmentationNames)) { - props.player.queueAugmentation(augName); + Player.queueAugmentation(augName); } } function clearAugs(): void { - props.player.augmentations = []; + Player.augmentations = []; } function clearQueuedAugs(): void { - props.player.queuedAugmentations = []; + Player.queuedAugmentations = []; } return ( diff --git a/src/DevMenu/ui/Bladeburner.tsx b/src/DevMenu/ui/Bladeburner.tsx index 6726167a3..538fe8a78 100644 --- a/src/DevMenu/ui/Bladeburner.tsx +++ b/src/DevMenu/ui/Bladeburner.tsx @@ -7,21 +7,17 @@ import AccordionDetails from "@mui/material/AccordionDetails"; import ExpandMoreIcon from "@mui/icons-material/ExpandMore"; import { Adjuster } from "./Adjuster"; -import { IPlayer } from "../../PersonObjects/IPlayer"; +import { Player } from "../../Player"; const bigNumber = 1e27; -interface IProps { - player: IPlayer; -} - -export function Bladeburner(props: IProps): React.ReactElement { - const bladeburner = props.player.bladeburner; +export function Bladeburner(): React.ReactElement { + const bladeburner = Player.bladeburner; if (bladeburner === null) return <>; function modifyBladeburnerRank(modify: number): (x: number) => void { return function (rank: number): void { if (!bladeburner) return; - bladeburner.changeRank(props.player, rank * modify); + bladeburner.changeRank(Player, rank * modify); }; } @@ -34,7 +30,7 @@ export function Bladeburner(props: IProps): React.ReactElement { function addTonsBladeburnerRank(): void { if (!bladeburner) return; - bladeburner.changeRank(props.player, bigNumber); + bladeburner.changeRank(Player, bigNumber); } function modifyBladeburnerCycles(modify: number): (x: number) => void { diff --git a/src/DevMenu/ui/Corporation.tsx b/src/DevMenu/ui/Corporation.tsx index ce4250a91..9dbd3ac9b 100644 --- a/src/DevMenu/ui/Corporation.tsx +++ b/src/DevMenu/ui/Corporation.tsx @@ -8,58 +8,54 @@ import ExpandMoreIcon from "@mui/icons-material/ExpandMore"; import Typography from "@mui/material/Typography"; import Button from "@mui/material/Button"; import { Adjuster } from "./Adjuster"; -import { IPlayer } from "../../PersonObjects/IPlayer"; +import { Player } from "../../Player"; const bigNumber = 1e27; -interface IProps { - player: IPlayer; -} - -export function Corporation(props: IProps): React.ReactElement { +export function Corporation(): React.ReactElement { function addTonsCorporationFunds(): void { - if (props.player.corporation) { - props.player.corporation.funds = props.player.corporation.funds + bigNumber; + if (Player.corporation) { + Player.corporation.funds = Player.corporation.funds + bigNumber; } } function modifyCorporationFunds(modify: number): (x: number) => void { return function (funds: number): void { - if (props.player.corporation) { - props.player.corporation.funds += funds * modify; + if (Player.corporation) { + Player.corporation.funds += funds * modify; } }; } function resetCorporationFunds(): void { - if (props.player.corporation) { - props.player.corporation.funds = props.player.corporation.funds - props.player.corporation.funds; + if (Player.corporation) { + Player.corporation.funds = Player.corporation.funds - Player.corporation.funds; } } function addTonsCorporationCycles(): void { - if (props.player.corporation) { - props.player.corporation.storedCycles = bigNumber; + if (Player.corporation) { + Player.corporation.storedCycles = bigNumber; } } function modifyCorporationCycles(modify: number): (x: number) => void { return function (cycles: number): void { - if (props.player.corporation) { - props.player.corporation.storedCycles += cycles * modify; + if (Player.corporation) { + Player.corporation.storedCycles += cycles * modify; } }; } function resetCorporationCycles(): void { - if (props.player.corporation) { - props.player.corporation.storedCycles = 0; + if (Player.corporation) { + Player.corporation.storedCycles = 0; } } function finishCorporationProducts(): void { - if (!props.player.corporation) return; - props.player.corporation.divisions.forEach((div) => { + if (!Player.corporation) return; + Player.corporation.divisions.forEach((div) => { Object.keys(div.products).forEach((prod) => { const product = div.products[prod]; if (product === undefined) throw new Error("Impossible product undefined"); @@ -69,8 +65,8 @@ export function Corporation(props: IProps): React.ReactElement { } function addCorporationResearch(): void { - if (!props.player.corporation) return; - props.player.corporation.divisions.forEach((div) => { + if (!Player.corporation) return; + Player.corporation.divisions.forEach((div) => { div.sciResearch.qty += 1e10; }); } diff --git a/src/DevMenu/ui/Entropy.tsx b/src/DevMenu/ui/Entropy.tsx index acac53af0..47d90d9a6 100644 --- a/src/DevMenu/ui/Entropy.tsx +++ b/src/DevMenu/ui/Entropy.tsx @@ -6,18 +6,12 @@ import AccordionDetails from "@mui/material/AccordionDetails"; import ExpandMoreIcon from "@mui/icons-material/ExpandMore"; import Typography from "@mui/material/Typography"; -import { IPlayer } from "../../PersonObjects/IPlayer"; +import { Player } from "../../Player"; import { Adjuster } from "./Adjuster"; -import { IEngine } from "../../IEngine"; // Update as additional BitNodes get implemented -interface IProps { - player: IPlayer; - engine: IEngine; -} - -export function Entropy(props: IProps): React.ReactElement { +export function Entropy(): React.ReactElement { return ( }> @@ -28,20 +22,20 @@ export function Entropy(props: IProps): React.ReactElement { label="Set entropy" placeholder="entropy" add={(num) => { - props.player.entropy += num; - props.player.applyEntropy(props.player.entropy); + Player.entropy += num; + Player.applyEntropy(Player.entropy); }} subtract={(num) => { - props.player.entropy -= num; - props.player.applyEntropy(props.player.entropy); + Player.entropy -= num; + Player.applyEntropy(Player.entropy); }} tons={() => { - props.player.entropy += 1e12; - props.player.applyEntropy(props.player.entropy); + Player.entropy += 1e12; + Player.applyEntropy(Player.entropy); }} reset={() => { - props.player.entropy = 0; - props.player.applyEntropy(props.player.entropy); + Player.entropy = 0; + Player.applyEntropy(Player.entropy); }} /> diff --git a/src/DevMenu/ui/Factions.tsx b/src/DevMenu/ui/Factions.tsx index 6f1453ac1..d305c672c 100644 --- a/src/DevMenu/ui/Factions.tsx +++ b/src/DevMenu/ui/Factions.tsx @@ -9,7 +9,7 @@ import Typography from "@mui/material/Typography"; import Button from "@mui/material/Button"; import Select, { SelectChangeEvent } from "@mui/material/Select"; import { Adjuster } from "./Adjuster"; -import { IPlayer } from "../../PersonObjects/IPlayer"; +import { Player } from "../../Player"; import { Factions as AllFaction } from "../../Faction/Factions"; import FormControl from "@mui/material/FormControl"; import MenuItem from "@mui/material/MenuItem"; @@ -21,11 +21,7 @@ import { FactionNames } from "../../Faction/data/FactionNames"; const bigNumber = 1e12; -interface IProps { - player: IPlayer; -} - -export function Factions(props: IProps): React.ReactElement { +export function Factions(): React.ReactElement { const [faction, setFaction] = useState(FactionNames.Illuminati as string); function setFactionDropdown(event: SelectChangeEvent): void { @@ -33,11 +29,11 @@ export function Factions(props: IProps): React.ReactElement { } function receiveInvite(): void { - props.player.receiveInvite(faction); + Player.receiveInvite(faction); } function receiveAllInvites(): void { - Object.values(FactionNames).forEach((faction) => props.player.receiveInvite(faction)); + Object.values(FactionNames).forEach((faction) => Player.receiveInvite(faction)); } function modifyFactionRep(modifier: number): (x: number) => void { diff --git a/src/DevMenu/ui/Gang.tsx b/src/DevMenu/ui/Gang.tsx index cef6bd24d..3b0566738 100644 --- a/src/DevMenu/ui/Gang.tsx +++ b/src/DevMenu/ui/Gang.tsx @@ -7,32 +7,28 @@ import AccordionDetails from "@mui/material/AccordionDetails"; import ExpandMoreIcon from "@mui/icons-material/ExpandMore"; import { Adjuster } from "./Adjuster"; -import { IPlayer } from "../../PersonObjects/IPlayer"; +import { Player } from "../../Player"; const bigNumber = 1e27; -interface IProps { - player: IPlayer; -} - -export function Gang(props: IProps): React.ReactElement { +export function Gang(): React.ReactElement { function addTonsGangCycles(): void { - if (props.player.gang) { - props.player.gang.storedCycles = bigNumber; + if (Player.gang) { + Player.gang.storedCycles = bigNumber; } } function modifyGangCycles(modify: number): (x: number) => void { return function (cycles: number): void { - if (props.player.gang) { - props.player.gang.storedCycles += cycles * modify; + if (Player.gang) { + Player.gang.storedCycles += cycles * modify; } }; } function resetGangCycles(): void { - if (props.player.gang) { - props.player.gang.storedCycles = 0; + if (Player.gang) { + Player.gang.storedCycles = 0; } } diff --git a/src/DevMenu/ui/General.tsx b/src/DevMenu/ui/General.tsx index 9b96e8326..2c0b39902 100644 --- a/src/DevMenu/ui/General.tsx +++ b/src/DevMenu/ui/General.tsx @@ -8,61 +8,56 @@ import ExpandMoreIcon from "@mui/icons-material/ExpandMore"; import Typography from "@mui/material/Typography"; import Button from "@mui/material/Button"; import { Money } from "../../ui/React/Money"; -import { IPlayer } from "../../PersonObjects/IPlayer"; -import { IRouter } from "../../ui/Router"; +import { Player } from "../../Player"; +import { Router } from "../../ui/GameRoot"; import { MenuItem, SelectChangeEvent, TextField, Select } from "@mui/material"; import { Bladeburner } from "../../Bladeburner/Bladeburner"; import { GangConstants } from "../../Gang/data/Constants"; import { FactionNames } from "../../Faction/data/FactionNames"; import { checkForMessagesToSend } from "../../Message/MessageHelpers"; -interface IProps { - player: IPlayer; - router: IRouter; -} - -export function General(props: IProps): React.ReactElement { +export function General(): React.ReactElement { const [error, setError] = useState(false); const [corporationName, setCorporationName] = useState(""); const [gangFaction, setGangFaction] = useState(""); function addMoney(n: number) { return function () { - props.player.gainMoney(n, "other"); + Player.gainMoney(n, "other"); }; } function upgradeRam(): void { - props.player.getHomeComputer().maxRam *= 2; + Player.getHomeComputer().maxRam *= 2; } function quickB1tFlum3(): void { - props.router.toBitVerse(true, true); + Router.toBitVerse(true, true); } function b1tflum3(): void { - props.router.toBitVerse(true, false); + Router.toBitVerse(true, false); } function quickHackW0r1dD43m0n(): void { - props.router.toBitVerse(false, true); + Router.toBitVerse(false, true); } function hackW0r1dD43m0n(): void { - props.router.toBitVerse(false, false); + Router.toBitVerse(false, false); } function createCorporation(): void { - props.player.startCorporation(corporationName); + Player.startCorporation(corporationName); } function joinBladeburner(): void { - props.player.bladeburner = new Bladeburner(props.player); + Player.bladeburner = new Bladeburner(); } function startGang(): void { const isHacking = gangFaction === FactionNames.NiteSec || gangFaction === FactionNames.TheBlackHand; - props.player.startGang(gangFaction, isHacking); + Player.startGang(gangFaction, isHacking); } function setGangFactionDropdown(event: SelectChangeEvent): void { diff --git a/src/DevMenu/ui/Programs.tsx b/src/DevMenu/ui/Programs.tsx index 830a99b2e..b32f5e870 100644 --- a/src/DevMenu/ui/Programs.tsx +++ b/src/DevMenu/ui/Programs.tsx @@ -8,29 +8,25 @@ import ExpandMoreIcon from "@mui/icons-material/ExpandMore"; import Typography from "@mui/material/Typography"; import Button from "@mui/material/Button"; import Select, { SelectChangeEvent } from "@mui/material/Select"; -import { IPlayer } from "../../PersonObjects/IPlayer"; +import { Player } from "../../Player"; import { Programs as AllPrograms } from "../../Programs/Programs"; import MenuItem from "@mui/material/MenuItem"; -interface IProps { - player: IPlayer; -} - -export function Programs(props: IProps): React.ReactElement { +export function Programs(): React.ReactElement { const [program, setProgram] = useState("NUKE.exe"); function setProgramDropdown(event: SelectChangeEvent): void { setProgram(event.target.value); } function addProgram(): void { - if (!props.player.hasProgram(program)) { - props.player.getHomeComputer().programs.push(program); + if (!Player.hasProgram(program)) { + Player.getHomeComputer().programs.push(program); } } function addAllPrograms(): void { for (const i of Object.keys(AllPrograms)) { - if (!props.player.hasProgram(AllPrograms[i].name)) { - props.player.getHomeComputer().programs.push(AllPrograms[i].name); + if (!Player.hasProgram(AllPrograms[i].name)) { + Player.getHomeComputer().programs.push(AllPrograms[i].name); } } } diff --git a/src/DevMenu/ui/Sleeves.tsx b/src/DevMenu/ui/Sleeves.tsx index 5dcbcf455..fa1941ed6 100644 --- a/src/DevMenu/ui/Sleeves.tsx +++ b/src/DevMenu/ui/Sleeves.tsx @@ -7,41 +7,37 @@ import ExpandMoreIcon from "@mui/icons-material/ExpandMore"; import Button from "@mui/material/Button"; import Typography from "@mui/material/Typography"; -import { IPlayer } from "../../PersonObjects/IPlayer"; +import { Player } from "../../Player"; import { Adjuster } from "./Adjuster"; -interface IProps { - player: IPlayer; -} - -export function Sleeves(props: IProps): React.ReactElement { +export function Sleeves(): React.ReactElement { function sleeveMaxAllShock(): void { - for (let i = 0; i < props.player.sleeves.length; ++i) { - props.player.sleeves[i].shock = 0; + for (let i = 0; i < Player.sleeves.length; ++i) { + Player.sleeves[i].shock = 0; } } function sleeveClearAllShock(): void { - for (let i = 0; i < props.player.sleeves.length; ++i) { - props.player.sleeves[i].shock = 100; + for (let i = 0; i < Player.sleeves.length; ++i) { + Player.sleeves[i].shock = 100; } } function sleeveSyncMaxAll(): void { - for (let i = 0; i < props.player.sleeves.length; ++i) { - props.player.sleeves[i].sync = 100; + for (let i = 0; i < Player.sleeves.length; ++i) { + Player.sleeves[i].sync = 100; } } function sleeveSyncClearAll(): void { - for (let i = 0; i < props.player.sleeves.length; ++i) { - props.player.sleeves[i].sync = 0; + for (let i = 0; i < Player.sleeves.length; ++i) { + Player.sleeves[i].sync = 0; } } function sleeveSetStoredCycles(cycles: number): void { - for (let i = 0; i < props.player.sleeves.length; ++i) { - props.player.sleeves[i].storedCycles = cycles; + for (let i = 0; i < Player.sleeves.length; ++i) { + Player.sleeves[i].storedCycles = cycles; } } diff --git a/src/DevMenu/ui/SourceFiles.tsx b/src/DevMenu/ui/SourceFiles.tsx index cab4440a6..fa4576135 100644 --- a/src/DevMenu/ui/SourceFiles.tsx +++ b/src/DevMenu/ui/SourceFiles.tsx @@ -8,35 +8,31 @@ import ExpandMoreIcon from "@mui/icons-material/ExpandMore"; import Typography from "@mui/material/Typography"; import Button from "@mui/material/Button"; import { PlayerOwnedSourceFile } from "../../SourceFile/PlayerOwnedSourceFile"; -import { IPlayer } from "../../PersonObjects/IPlayer"; +import { Player } from "../../Player"; import ButtonGroup from "@mui/material/ButtonGroup"; // Update as additional BitNodes get implemented const validSFN = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]; -interface IProps { - player: IPlayer; -} - -export function SourceFiles(props: IProps): React.ReactElement { +export function SourceFiles(): React.ReactElement { function setSF(sfN: number, sfLvl: number) { return function () { if (sfN === 9) { - props.player.hacknetNodes = []; + Player.hacknetNodes = []; } if (sfLvl === 0) { - props.player.sourceFiles = props.player.sourceFiles.filter((sf) => sf.n !== sfN); + Player.sourceFiles = Player.sourceFiles.filter((sf) => sf.n !== sfN); return; } - if (!props.player.sourceFiles.some((sf) => sf.n === sfN)) { - props.player.sourceFiles.push(new PlayerOwnedSourceFile(sfN, sfLvl)); + if (!Player.sourceFiles.some((sf) => sf.n === sfN)) { + Player.sourceFiles.push(new PlayerOwnedSourceFile(sfN, sfLvl)); return; } - for (let i = 0; i < props.player.sourceFiles.length; i++) { - if (props.player.sourceFiles[i].n === sfN) { - props.player.sourceFiles[i].lvl = sfLvl; + for (let i = 0; i < Player.sourceFiles.length; i++) { + if (Player.sourceFiles[i].n === sfN) { + Player.sourceFiles[i].lvl = sfLvl; } } }; @@ -51,7 +47,7 @@ export function SourceFiles(props: IProps): React.ReactElement { } function clearExploits(): void { - props.player.exploits = []; + Player.exploits = []; } return ( diff --git a/src/DevMenu/ui/Stats.tsx b/src/DevMenu/ui/Stats.tsx index a664214cf..c9a1c0966 100644 --- a/src/DevMenu/ui/Stats.tsx +++ b/src/DevMenu/ui/Stats.tsx @@ -8,132 +8,128 @@ import ExpandMoreIcon from "@mui/icons-material/ExpandMore"; import Typography from "@mui/material/Typography"; import Button from "@mui/material/Button"; import { Adjuster } from "./Adjuster"; -import { IPlayer } from "../../PersonObjects/IPlayer"; +import { Player } from "../../Player"; const bigNumber = 1e27; -interface IProps { - player: IPlayer; -} - -export function Stats(props: IProps): React.ReactElement { +export function Stats(): React.ReactElement { function modifyExp(stat: string, modifier: number) { return function (exp: number) { switch (stat) { case "hacking": if (exp) { - props.player.gainHackingExp(exp * modifier); + Player.gainHackingExp(exp * modifier); } break; case "strength": if (exp) { - props.player.gainStrengthExp(exp * modifier); + Player.gainStrengthExp(exp * modifier); } break; case "defense": if (exp) { - props.player.gainDefenseExp(exp * modifier); + Player.gainDefenseExp(exp * modifier); } break; case "dexterity": if (exp) { - props.player.gainDexterityExp(exp * modifier); + Player.gainDexterityExp(exp * modifier); } break; case "agility": if (exp) { - props.player.gainAgilityExp(exp * modifier); + Player.gainAgilityExp(exp * modifier); } break; case "charisma": if (exp) { - props.player.gainCharismaExp(exp * modifier); + Player.gainCharismaExp(exp * modifier); } break; case "intelligence": if (exp) { - props.player.gainIntelligenceExp(exp * modifier); + Player.gainIntelligenceExp(exp * modifier); } break; } - props.player.updateSkillLevels(); + Player.updateSkillLevels(); }; } function modifyKarma(modifier: number) { return function (amt: number) { - props.player.karma += amt * modifier; + Player.karma += amt * modifier; }; } function tonsOfExp(): void { - props.player.gainHackingExp(bigNumber); - props.player.gainStrengthExp(bigNumber); - props.player.gainDefenseExp(bigNumber); - props.player.gainDexterityExp(bigNumber); - props.player.gainAgilityExp(bigNumber); - props.player.gainCharismaExp(bigNumber); - props.player.gainIntelligenceExp(bigNumber); - props.player.updateSkillLevels(); + Player.gainHackingExp(bigNumber); + Player.gainStrengthExp(bigNumber); + Player.gainDefenseExp(bigNumber); + Player.gainDexterityExp(bigNumber); + Player.gainAgilityExp(bigNumber); + Player.gainCharismaExp(bigNumber); + Player.gainIntelligenceExp(bigNumber); + Player.updateSkillLevels(); } function resetAllExp(): void { - props.player.exp.hacking = 0; - props.player.exp.strength = 0; - props.player.exp.defense = 0; - props.player.exp.dexterity = 0; - props.player.exp.agility = 0; - props.player.exp.charisma = 0; - props.player.exp.intelligence = 0; - props.player.updateSkillLevels(); + Player.exp.hacking = 0; + Player.exp.strength = 0; + Player.exp.defense = 0; + Player.exp.dexterity = 0; + Player.exp.agility = 0; + Player.exp.charisma = 0; + Player.exp.intelligence = 0; + Player.updateSkillLevels(); } function resetExperience(stat: string): () => void { return function () { switch (stat) { case "hacking": - props.player.exp.hacking = 0; + Player.exp.hacking = 0; break; case "strength": - props.player.exp.strength = 0; + Player.exp.strength = 0; break; case "defense": - props.player.exp.defense = 0; + Player.exp.defense = 0; break; case "dexterity": - props.player.exp.dexterity = 0; + Player.exp.dexterity = 0; break; case "agility": - props.player.exp.agility = 0; + Player.exp.agility = 0; break; case "charisma": - props.player.exp.charisma = 0; + Player.exp.charisma = 0; break; case "intelligence": - props.player.exp.intelligence = 0; + Player.exp.intelligence = 0; break; } - props.player.updateSkillLevels(); + Player.updateSkillLevels(); }; } function resetKarma(): () => void { return function () { - props.player.karma = 0; + Player.karma = 0; }; } function enableIntelligence(): void { - if (props.player.skills.intelligence === 0) { - props.player.skills.intelligence = 1; - props.player.updateSkillLevels(); + if (Player.skills.intelligence === 0) { + Player.skills.intelligence = 1; + Player.updateSkillLevels(); } } function disableIntelligence(): void { - props.player.exp.intelligence = 0; - props.player.skills.intelligence = 0; - props.player.updateSkillLevels(); + Player.exp.intelligence = 0; + Player.skills.intelligence = 0; + Player.updateSkillLevels(); } return ( diff --git a/src/DevMenu/ui/TimeSkip.tsx b/src/DevMenu/ui/TimeSkip.tsx index f44f65a6d..b8da48b02 100644 --- a/src/DevMenu/ui/TimeSkip.tsx +++ b/src/DevMenu/ui/TimeSkip.tsx @@ -7,22 +7,17 @@ import ExpandMoreIcon from "@mui/icons-material/ExpandMore"; import Typography from "@mui/material/Typography"; import Button from "@mui/material/Button"; -import { IPlayer } from "../../PersonObjects/IPlayer"; +import { Player } from "../../Player"; import { saveObject } from "../../SaveObject"; -import { IEngine } from "../../IEngine"; +import { Engine } from "../../engine"; // Update as additional BitNodes get implemented -interface IProps { - player: IPlayer; - engine: IEngine; -} - -export function TimeSkip(props: IProps): React.ReactElement { +export function TimeSkip(): React.ReactElement { function timeskip(time: number) { return () => { - props.player.lastUpdate -= time; - props.engine._lastUpdate -= time; + Player.lastUpdate -= time; + Engine._lastUpdate -= time; saveObject.saveGame(); setTimeout(() => location.reload(), 1000); }; diff --git a/src/ExportBonus.tsx b/src/ExportBonus.tsx index c75bce683..f4a0a404d 100644 --- a/src/ExportBonus.tsx +++ b/src/ExportBonus.tsx @@ -1,5 +1,5 @@ import { Factions } from "./Faction/Factions"; -import { IPlayer } from "./PersonObjects/IPlayer"; +import { Player } from "./Player"; export let LastExportBonus = 0; @@ -9,9 +9,9 @@ export function canGetBonus(): boolean { return now - LastExportBonus > bonusTimer; } -export function onExport(p: IPlayer): void { +export function onExport(): void { if (!canGetBonus()) return; - for (const facName of p.factions) { + for (const facName of Player.factions) { Factions[facName].favor++; } LastExportBonus = new Date().getTime(); diff --git a/src/Faction/FactionHelpers.tsx b/src/Faction/FactionHelpers.tsx index 6e7d9509b..c5cea74ae 100644 --- a/src/Faction/FactionHelpers.tsx +++ b/src/Faction/FactionHelpers.tsx @@ -7,7 +7,6 @@ import { BitNodeMultipliers } from "../BitNode/BitNodeMultipliers"; import { Faction } from "./Faction"; import { Factions } from "./Factions"; import { Player } from "../Player"; -import { IPlayer } from "../PersonObjects/IPlayer"; import { Settings } from "../Settings/Settings"; import { getHackingWorkRepGain, @@ -59,7 +58,7 @@ export function hasAugmentationPrereqs(aug: Augmentation): boolean { export function purchaseAugmentation(aug: Augmentation, fac: Faction, sing = false): string { const hasPrereqs = hasAugmentationPrereqs(aug); - const augCosts = aug.getCost(Player); + const augCosts = aug.getCost(); if (!hasPrereqs) { const txt = `You must first purchase or install ${aug.prereqs .filter((req) => !Player.hasAugmentation(req)) @@ -84,7 +83,7 @@ export function purchaseAugmentation(aug: Augmentation, fac: Faction, sing = fal } else if (augCosts.moneyCost === 0 || Player.money >= augCosts.moneyCost) { const queuedAugmentation = new PlayerOwnedAugmentation(aug.name); if (aug.name == AugmentationNames.NeuroFluxGovernor) { - queuedAugmentation.level = aug.getLevel(Player); + queuedAugmentation.level = aug.getLevel(); } Player.queuedAugmentations.push(queuedAugmentation); @@ -134,20 +133,20 @@ export function processPassiveFactionRepGain(numCycles: number): void { } } -export const getFactionAugmentationsFiltered = (player: IPlayer, faction: Faction): string[] => { +export const getFactionAugmentationsFiltered = (faction: Faction): string[] => { // If player has a gang with this faction, return (almost) all augmentations - if (player.hasGangWith(faction.name)) { + if (Player.hasGangWith(faction.name)) { let augs = Object.values(StaticAugmentations); // Remove special augs augs = augs.filter((a) => !a.isSpecial && a.name !== AugmentationNames.CongruityImplant); - if (player.bitNodeN === 2) { + if (Player.bitNodeN === 2) { // TRP is not available outside of BN2 for Gangs augs.push(StaticAugmentations[AugmentationNames.TheRedPill]); } - const rng = SFC32RNG(`BN${player.bitNodeN}.${player.sourceFileLvl(player.bitNodeN)}`); + const rng = SFC32RNG(`BN${Player.bitNodeN}.${Player.sourceFileLvl(Player.bitNodeN)}`); // Remove faction-unique augs that don't belong to this faction const uniqueFilter = (a: Augmentation): boolean => { // Keep all the non-unique one diff --git a/src/Faction/formulas/donation.ts b/src/Faction/formulas/donation.ts index ea0e99b11..0bcd8c645 100644 --- a/src/Faction/formulas/donation.ts +++ b/src/Faction/formulas/donation.ts @@ -1,6 +1,6 @@ import { CONSTANTS } from "../../Constants"; -import { IPlayer } from "../../PersonObjects/IPlayer"; +import { IPerson } from "../../PersonObjects/IPerson"; -export function repFromDonation(amt: number, player: IPlayer): number { - return (amt / CONSTANTS.DonateMoneyToRepDivisor) * player.mults.faction_rep; +export function repFromDonation(amt: number, person: IPerson): number { + return (amt / CONSTANTS.DonateMoneyToRepDivisor) * person.mults.faction_rep; } diff --git a/src/Faction/ui/AugmentationsPage.tsx b/src/Faction/ui/AugmentationsPage.tsx index cb3b8cc45..939ad8e0e 100644 --- a/src/Faction/ui/AugmentationsPage.tsx +++ b/src/Faction/ui/AugmentationsPage.tsx @@ -10,7 +10,7 @@ import { AugmentationNames } from "../../Augmentation/data/AugmentationNames"; import { PurchasableAugmentations } from "../../Augmentation/ui/PurchasableAugmentations"; import { PurchaseAugmentationsOrderSetting } from "../../Settings/SettingEnums"; import { Settings } from "../../Settings/Settings"; -import { use } from "../../ui/Context"; +import { Player } from "../../Player"; import { numeralWrapper } from "../../ui/numeralFormat"; import { Favor } from "../../ui/React/Favor"; import { Reputation } from "../../ui/React/Reputation"; @@ -24,8 +24,6 @@ type IProps = { }; export function AugmentationsPage(props: IProps): React.ReactElement { - const player = use.Player(); - const setRerender = useState(false)[1]; function rerender(): void { @@ -33,7 +31,7 @@ export function AugmentationsPage(props: IProps): React.ReactElement { } function getAugs(): string[] { - return getFactionAugmentationsFiltered(player, props.faction); + return getFactionAugmentationsFiltered(props.faction); } function getAugsSorted(): string[] { @@ -61,7 +59,7 @@ export function AugmentationsPage(props: IProps): React.ReactElement { throw new Error("Invalid Augmentation Names"); } - return aug1.getCost(player).moneyCost - aug2.getCost(player).moneyCost; + return aug1.getCost().moneyCost - aug2.getCost().moneyCost; }); return augs; @@ -71,11 +69,11 @@ export function AugmentationsPage(props: IProps): React.ReactElement { const augs = getAugs(); function canBuy(augName: string): boolean { const aug = StaticAugmentations[augName]; - const augCosts = aug.getCost(player); + const augCosts = aug.getCost(); const repCost = augCosts.repCost; const hasReq = props.faction.playerReputation >= repCost; const hasRep = hasAugmentationPrereqs(aug); - const hasCost = augCosts.moneyCost !== 0 && player.money > augCosts.moneyCost; + const hasCost = augCosts.moneyCost !== 0 && Player.money > augCosts.moneyCost; return hasCost && hasReq && hasRep; } const buy = augs.filter(canBuy).sort((augName1, augName2) => { @@ -85,7 +83,7 @@ export function AugmentationsPage(props: IProps): React.ReactElement { throw new Error("Invalid Augmentation Names"); } - return aug1.getCost(player).moneyCost - aug2.getCost(player).moneyCost; + return aug1.getCost().moneyCost - aug2.getCost().moneyCost; }); const cantBuy = augs .filter((aug) => !canBuy(aug)) @@ -95,7 +93,7 @@ export function AugmentationsPage(props: IProps): React.ReactElement { if (aug1 == null || aug2 == null) { throw new Error("Invalid Augmentation Names"); } - return aug1.getCost(player).repCost - aug2.getCost(player).repCost; + return aug1.getCost().repCost - aug2.getCost().repCost; }); return buy.concat(cantBuy); @@ -109,7 +107,7 @@ export function AugmentationsPage(props: IProps): React.ReactElement { if (aug1 == null || aug2 == null) { throw new Error("Invalid Augmentation Names"); } - return aug1.getCost(player).repCost - aug2.getCost(player).repCost; + return aug1.getCost().repCost - aug2.getCost().repCost; }); return augs; @@ -128,7 +126,7 @@ export function AugmentationsPage(props: IProps): React.ReactElement { const purchasable = augs.filter( (aug: string) => aug === AugmentationNames.NeuroFluxGovernor || - (!player.augmentations.some((a) => a.name === aug) && !player.queuedAugmentations.some((a) => a.name === aug)), + (!Player.augmentations.some((a) => a.name === aug) && !Player.queuedAugmentations.some((a) => a.name === aug)), ); const owned = augs.filter((aug: string) => !purchasable.includes(aug)); @@ -195,16 +193,15 @@ export function AugmentationsPage(props: IProps): React.ReactElement { { - const costs = aug.getCost(player); + canPurchase={(aug) => { + const costs = aug.getCost(); return ( hasAugmentationPrereqs(aug) && props.faction.playerReputation >= costs.repCost && - (costs.moneyCost === 0 || player.money > costs.moneyCost) + (costs.moneyCost === 0 || Player.money > costs.moneyCost) ); }} - purchaseAugmentation={(player, aug, showModal) => { + purchaseAugmentation={(aug, showModal) => { if (!Settings.SuppressBuyAugmentationConfirmation) { showModal(true); } else { diff --git a/src/Faction/ui/DonateOption.tsx b/src/Faction/ui/DonateOption.tsx index afd840dbb..052b7d397 100644 --- a/src/Faction/ui/DonateOption.tsx +++ b/src/Faction/ui/DonateOption.tsx @@ -5,7 +5,7 @@ import React, { useState } from "react"; import { CONSTANTS } from "../../Constants"; import { Faction } from "../Faction"; -import { IPlayer } from "../../PersonObjects/IPlayer"; +import { Player } from "../../Player"; import { repFromDonation } from "../formulas/donation"; import { Favor } from "../../ui/React/Favor"; @@ -24,7 +24,6 @@ type IProps = { faction: Faction; disabled: boolean; favorToDonate: number; - p: IPlayer; rerender: () => void; }; @@ -35,7 +34,7 @@ export function DonateOption(props: IProps): React.ReactElement { function canDonate(): boolean { if (isNaN(donateAmt)) return false; if (isNaN(donateAmt) || donateAmt <= 0) return false; - if (props.p.money < donateAmt) return false; + if (Player.money < donateAmt) return false; return true; } @@ -44,8 +43,8 @@ export function DonateOption(props: IProps): React.ReactElement { const amt = donateAmt; if (isNaN(amt)) return; if (!canDonate()) return; - props.p.loseMoney(amt, "other"); - const repGain = repFromDonation(amt, props.p); + Player.loseMoney(amt, "other"); + const repGain = repFromDonation(amt, Player); props.faction.playerReputation += repGain; dialogBoxCreate( <> @@ -58,12 +57,12 @@ export function DonateOption(props: IProps): React.ReactElement { function Status(): React.ReactElement { if (isNaN(donateAmt)) return <>; if (!canDonate()) { - if (props.p.money < donateAmt) return Insufficient funds; + if (Player.money < donateAmt) return Insufficient funds; return Invalid donate amount entered!; } return ( - This donation will result in reputation gain + This donation will result in reputation gain ); } diff --git a/src/Faction/ui/FactionRoot.tsx b/src/Faction/ui/FactionRoot.tsx index ef5ad72fd..7e633b2d9 100644 --- a/src/Faction/ui/FactionRoot.tsx +++ b/src/Faction/ui/FactionRoot.tsx @@ -15,7 +15,8 @@ import { CONSTANTS } from "../../Constants"; import { BitNodeMultipliers } from "../../BitNode/BitNodeMultipliers"; import { Faction } from "../Faction"; -import { use } from "../../ui/Context"; +import { Router } from "../../ui/GameRoot"; +import { Player } from "../../Player"; import { Typography, Button } from "@mui/material"; import { CovenantPurchasesRoot } from "../../PersonObjects/Sleeve/ui/CovenantPurchasesRoot"; @@ -58,18 +59,16 @@ interface IMainProps { } function MainPage({ faction, rerender, onAugmentations }: IMainProps): React.ReactElement { - const player = use.Player(); - const router = use.Router(); const [sleevesOpen, setSleevesOpen] = useState(false); const factionInfo = faction.getInfo(); function startWork(): void { - player.startFocusing(); - router.toWork(); + Player.startFocusing(); + Router.toWork(); } function startFieldWork(faction: Faction): void { - player.startWork( + Player.startWork( new FactionWork({ singularity: false, faction: faction.name, @@ -80,7 +79,7 @@ function MainPage({ faction, rerender, onAugmentations }: IMainProps): React.Rea } function startHackingContracts(faction: Faction): void { - player.startWork( + Player.startWork( new FactionWork({ singularity: false, faction: faction.name, @@ -91,7 +90,7 @@ function MainPage({ faction, rerender, onAugmentations }: IMainProps): React.Rea } function startSecurityWork(faction: Faction): void { - player.startWork( + Player.startWork( new FactionWork({ singularity: false, faction: faction.name, @@ -103,18 +102,18 @@ function MainPage({ faction, rerender, onAugmentations }: IMainProps): React.Rea // We have a special flag for whether the player this faction is the player's // gang faction because if the player has a gang, they cannot do any other action - const isPlayersGang = player.inGang() && player.getGangName() === faction.name; + const isPlayersGang = Player.inGang() && Player.getGangName() === faction.name; // Flags for whether special options (gang, sleeve purchases, donate, etc.) // should be shown const favorToDonate = Math.floor(CONSTANTS.BaseFavorToDonate * BitNodeMultipliers.RepToDonateToFaction); const canDonate = faction.favor >= favorToDonate; - const canPurchaseSleeves = faction.name === FactionNames.TheCovenant && player.bitNodeN === 10; + const canPurchaseSleeves = faction.name === FactionNames.TheCovenant && Player.bitNodeN === 10; return ( <> - + {faction.name} @@ -134,13 +133,7 @@ function MainPage({ faction, rerender, onAugmentations }: IMainProps): React.Rea - {getGraftingAvailableAugs(player).length > 0 ? ( + {getGraftingAvailableAugs().length > 0 ? ( {getAugsSorted().map((k, i) => ( setSelectedAug(k)} selected={selectedAug === k}> { @@ -158,21 +153,20 @@ export const GraftingRoot = (): React.ReactElement => { open={graftOpen} onClose={() => setGraftOpen(false)} onConfirm={() => { - player.startWork( + Player.startWork( new GraftingWork({ augmentation: selectedAug, singularity: false, - player: player, }), ); - player.startFocusing(); - router.toWork(); + Player.startFocusing(); + Router.toWork(); }} confirmationText={ <> Cancelling grafting will not save grafting progress, and the money you spend will not{" "} be returned. - {!player.hasAugmentation(AugmentationNames.CongruityImplant) && ( + {!Player.hasAugmentation(AugmentationNames.CongruityImplant) && ( <>

    @@ -186,14 +180,12 @@ export const GraftingRoot = (): React.ReactElement => { Time to Graft:{" "} {convertTimeMsToTimeElapsedString( - calculateGraftingTimeWithBonus(player, graftableAugmentations[selectedAug]), + calculateGraftingTimeWithBonus(graftableAugmentations[selectedAug]), )} {/* Use formula so the displayed creation time is accurate to player bonus */} - {selectedAugmentation.prereqs.length > 0 && ( - - )} + {selectedAugmentation.prereqs.length > 0 && }
    @@ -229,10 +221,10 @@ export const GraftingRoot = (): React.ReactElement => { - Entropy strength: {player.entropy} + Entropy strength: {Player.entropy}
    All multipliers decreased by:{" "} - {formatNumber((1 - CONSTANTS.EntropyEffect ** player.entropy) * 100, 3)}% (multiplicative) + {formatNumber((1 - CONSTANTS.EntropyEffect ** Player.entropy) * 100, 3)}% (multiplicative)
    diff --git a/src/PersonObjects/Player/PlayerObjectAugmentationMethods.ts b/src/PersonObjects/Player/PlayerObjectAugmentationMethods.ts index 58accbe73..d7cd35177 100644 --- a/src/PersonObjects/Player/PlayerObjectAugmentationMethods.ts +++ b/src/PersonObjects/Player/PlayerObjectAugmentationMethods.ts @@ -32,5 +32,5 @@ export function applyEntropy(this: IPlayer, stacks = 1): void { this.reapplyAllAugmentations(); this.reapplyAllSourceFiles(); - this.mults = calculateEntropy(this, stacks); + this.mults = calculateEntropy(stacks); } diff --git a/src/PersonObjects/Player/PlayerObjectBladeburnerMethods.ts b/src/PersonObjects/Player/PlayerObjectBladeburnerMethods.ts index ee0d9e8e9..cf8d9e2ce 100644 --- a/src/PersonObjects/Player/PlayerObjectBladeburnerMethods.ts +++ b/src/PersonObjects/Player/PlayerObjectBladeburnerMethods.ts @@ -13,5 +13,5 @@ export function inBladeburner(this: IPlayer): boolean { } export function startBladeburner(this: IPlayer): void { - this.bladeburner = new Bladeburner(this); + this.bladeburner = new Bladeburner(); } diff --git a/src/PersonObjects/Player/PlayerObjectGeneralMethods.ts b/src/PersonObjects/Player/PlayerObjectGeneralMethods.ts index fed24e61d..dc13eb4d7 100644 --- a/src/PersonObjects/Player/PlayerObjectGeneralMethods.ts +++ b/src/PersonObjects/Player/PlayerObjectGeneralMethods.ts @@ -112,15 +112,15 @@ export function prestigeAugmentation(this: PlayerObject): void { const numSleeves = Math.min(3, this.sourceFileLvl(10) + (this.bitNodeN === 10 ? 1 : 0)) + this.sleevesFromCovenant; if (this.sleeves.length > numSleeves) this.sleeves.length = numSleeves; for (let i = this.sleeves.length; i < numSleeves; i++) { - this.sleeves.push(new Sleeve(this)); + this.sleeves.push(new Sleeve()); } for (let i = 0; i < this.sleeves.length; ++i) { if (this.sleeves[i] instanceof Sleeve) { if (this.sleeves[i].shock >= 100) { - this.sleeves[i].synchronize(this); + this.sleeves[i].synchronize(); } else { - this.sleeves[i].shockRecovery(this); + this.sleeves[i].shockRecovery(); } } } @@ -149,9 +149,9 @@ export function prestigeSourceFile(this: IPlayer): void { // Duplicate sleeves are reset to level 1 every Bit Node (but the number of sleeves you have persists) for (let i = 0; i < this.sleeves.length; ++i) { if (this.sleeves[i] instanceof Sleeve) { - this.sleeves[i].prestige(this); + this.sleeves[i].prestige(); } else { - this.sleeves[i] = new Sleeve(this); + this.sleeves[i] = new Sleeve(); } } @@ -490,7 +490,7 @@ export function regenerateHp(this: IPerson, amt: number): void { } export function hospitalize(this: IPlayer): number { - const cost = getHospitalizationCost(this); + const cost = getHospitalizationCost(); SnackbarEvents.emit(`You've been Hospitalized for ${numeralWrapper.formatMoney(cost)}`, ToastVariant.WARNING, 2000); this.loseMoney(cost, "hospitalization"); @@ -596,7 +596,7 @@ export function quitJob(this: IPlayer, company: string): void { } for (const sleeve of this.sleeves) { if (isSleeveCompanyWork(sleeve.currentWork) && sleeve.currentWork.companyName === company) { - sleeve.stopWork(this); + sleeve.stopWork(); dialogBoxCreate(`You quit ${company} while one of your sleeves was working there. The sleeve is now idle.`); } } diff --git a/src/PersonObjects/Player/PlayerObjectWorkMethods.ts b/src/PersonObjects/Player/PlayerObjectWorkMethods.ts index 949e1774f..c2c306db5 100644 --- a/src/PersonObjects/Player/PlayerObjectWorkMethods.ts +++ b/src/PersonObjects/Player/PlayerObjectWorkMethods.ts @@ -3,20 +3,20 @@ import { IPlayer } from "../IPlayer"; export function start(this: IPlayer, w: Work): void { if (this.currentWork !== null) { - this.currentWork.finish(this, true); + this.currentWork.finish(true); } this.currentWork = w; } export function process(this: IPlayer, cycles = 1): void { if (this.currentWork === null) return; - const finished = this.currentWork.process(this, cycles); + const finished = this.currentWork.process(cycles); if (finished) { this.finishWork(false); } } export function finish(this: IPlayer, cancelled: boolean): void { if (this.currentWork === null) return; - this.currentWork.finish(this, cancelled); + this.currentWork.finish(cancelled); this.currentWork = null; this.focus = false; } diff --git a/src/PersonObjects/Sleeve/Sleeve.ts b/src/PersonObjects/Sleeve/Sleeve.ts index 693aa0d20..189496e75 100644 --- a/src/PersonObjects/Sleeve/Sleeve.ts +++ b/src/PersonObjects/Sleeve/Sleeve.ts @@ -7,7 +7,7 @@ * Sleeves are unlocked in BitNode-10. */ -import { IPlayer } from "../IPlayer"; +import { Player } from "../../Player"; import { Person } from "../Person"; import { Augmentation } from "../../Augmentation/Augmentation"; @@ -74,11 +74,9 @@ export class Sleeve extends Person { */ sync = 1; - constructor(p: IPlayer | null = null) { + constructor() { super(); - if (p != null) { - this.shockRecovery(p); - } + this.shockRecovery(); } shockBonus(): number { @@ -89,26 +87,26 @@ export class Sleeve extends Person { return this.sync / 100; } - startWork(player: IPlayer, w: Work): void { - if (this.currentWork) this.currentWork.finish(player); + startWork(w: Work): void { + if (this.currentWork) this.currentWork.finish(); this.currentWork = w; } - stopWork(player: IPlayer): void { - if (this.currentWork) this.currentWork.finish(player); + stopWork(): void { + if (this.currentWork) this.currentWork.finish(); this.currentWork = null; } /** * Commit crimes */ - commitCrime(p: IPlayer, crimeKey: string): boolean { + commitCrime(crimeKey: string): boolean { const crime: Crime | null = Crimes[crimeKey] || Object.values(Crimes).find((crime) => crime.name === crimeKey); if (!crime) { return false; } - this.startWork(p, new SleeveCrimeWork(crime.type)); + this.startWork(new SleeveCrimeWork(crime.type)); return true; } @@ -152,7 +150,7 @@ export class Sleeve extends Person { /** * Called on every sleeve for a Source File Prestige */ - prestige(p: IPlayer): void { + prestige(): void { // Reset exp this.exp.hacking = 0; this.exp.strength = 0; @@ -164,8 +162,8 @@ export class Sleeve extends Person { this.hp.current = this.hp.max; // Reset task-related stuff - this.stopWork(p); - this.shockRecovery(p); + this.stopWork(); + this.shockRecovery(); // Reset augs and multipliers this.augmentations = []; @@ -186,7 +184,7 @@ export class Sleeve extends Person { * Returns an object containing the amount of experience that should be * transferred to all other sleeves */ - process(p: IPlayer, numCycles = 1): void { + process(numCycles = 1): void { // Only process once every second (5 cycles) const CyclesPerSecond = 1000 / CONSTANTS.MilliPerCycle; this.storedCycles += numCycles; @@ -196,24 +194,24 @@ export class Sleeve extends Person { cyclesUsed = Math.min(cyclesUsed, 15); this.shock = Math.min(100, this.shock + 0.0001 * cyclesUsed); if (!this.currentWork) return; - this.currentWork.process(p, this, cyclesUsed); + this.currentWork.process(this, cyclesUsed); this.storedCycles -= cyclesUsed; } - shockRecovery(p: IPlayer): boolean { - this.startWork(p, new SleeveRecoveryWork()); + shockRecovery(): boolean { + this.startWork(new SleeveRecoveryWork()); return true; } - synchronize(p: IPlayer): boolean { - this.startWork(p, new SleeveSynchroWork()); + synchronize(): boolean { + this.startWork(new SleeveSynchroWork()); return true; } /** * Take a course at a university */ - takeUniversityCourse(p: IPlayer, universityName: string, className: string): boolean { + takeUniversityCourse(universityName: string, className: string): boolean { // Set exp/money multipliers based on which university. // Also check that the sleeve is in the right city let loc: LocationName | undefined; @@ -261,7 +259,6 @@ export class Sleeve extends Person { if (!classType) return false; this.startWork( - p, new SleeveClassWork({ classType: classType, location: loc, @@ -273,8 +270,8 @@ export class Sleeve extends Person { /** * Travel to another City. Costs money from player */ - travel(p: IPlayer, newCity: CityName): boolean { - p.loseMoney(CONSTANTS.TravelCost, "sleeves"); + travel(newCity: CityName): boolean { + Player.loseMoney(CONSTANTS.TravelCost, "sleeves"); this.city = newCity; return true; @@ -284,13 +281,15 @@ export class Sleeve extends Person { return this.augmentations.some((a) => a.name === aug); } - tryBuyAugmentation(p: IPlayer, aug: Augmentation): boolean { - if (!p.canAfford(aug.baseCost)) return false; + tryBuyAugmentation(aug: Augmentation): boolean { + if (!Player.canAfford(aug.baseCost)) { + return false; + } // Verify that this sleeve does not already have that augmentation. if (this.hasAugmentation(aug.name)) return false; - p.loseMoney(aug.baseCost, "sleeves"); + Player.loseMoney(aug.baseCost, "sleeves"); this.installAugmentation(aug); return true; } @@ -303,17 +302,17 @@ export class Sleeve extends Person { * Start work for one of the player's companies * Returns boolean indicating success */ - workForCompany(p: IPlayer, companyName: string): boolean { - if (!(Companies[companyName] instanceof Company) || p.jobs[companyName] == null) { + workForCompany(companyName: string): boolean { + if (!(Companies[companyName] instanceof Company) || Player.jobs[companyName] == null) { return false; } const company: Company | null = Companies[companyName]; - const companyPosition: CompanyPosition | null = CompanyPositions[p.jobs[companyName]]; + const companyPosition: CompanyPosition | null = CompanyPositions[Player.jobs[companyName]]; if (company == null) return false; if (companyPosition == null) return false; - this.startWork(p, new SleeveCompanyWork({ companyName: companyName })); + this.startWork(new SleeveCompanyWork({ companyName: companyName })); return true; } @@ -322,9 +321,9 @@ export class Sleeve extends Person { * Start work for one of the player's factions * Returns boolean indicating success */ - workForFaction(p: IPlayer, factionName: string, workType: string): boolean { + workForFaction(factionName: string, workType: string): boolean { const faction = Factions[factionName]; - if (factionName === "" || !faction || !(faction instanceof Faction) || !p.factions.includes(factionName)) { + if (factionName === "" || !faction || !(faction instanceof Faction) || !Player.factions.includes(factionName)) { return false; } @@ -347,7 +346,6 @@ export class Sleeve extends Person { } this.startWork( - p, new SleeveFactionWork({ factionWorkType: factionWorkType, factionName: faction.name, @@ -360,7 +358,7 @@ export class Sleeve extends Person { /** * Begin a gym workout task */ - workoutAtGym(p: IPlayer, gymName: string, stat: string): boolean { + workoutAtGym(gymName: string, stat: string): boolean { // Set exp/money multipliers based on which university. // Also check that the sleeve is in the right city let loc: LocationName | undefined; @@ -414,7 +412,6 @@ export class Sleeve extends Person { if (!classType) return false; this.startWork( - p, new SleeveClassWork({ classType: classType, location: loc, @@ -427,41 +424,41 @@ export class Sleeve extends Person { /** * Begin a bladeburner task */ - bladeburner(p: IPlayer, action: string, contract: string): boolean { + bladeburner(action: string, contract: string): boolean { switch (action) { case "Field analysis": - this.startWork(p, new SleeveBladeburnerWork({ type: "General", name: "Field Analysis" })); + this.startWork(new SleeveBladeburnerWork({ type: "General", name: "Field Analysis" })); return true; case "Recruitment": - this.startWork(p, new SleeveBladeburnerWork({ type: "General", name: "Recruitment" })); + this.startWork(new SleeveBladeburnerWork({ type: "General", name: "Recruitment" })); return true; case "Diplomacy": - this.startWork(p, new SleeveBladeburnerWork({ type: "General", name: "Diplomacy" })); + this.startWork(new SleeveBladeburnerWork({ type: "General", name: "Diplomacy" })); return true; case "Hyperbolic Regeneration Chamber": - this.startWork(p, new SleeveBladeburnerWork({ type: "General", name: "Hyperbolic Regeneration Chamber" })); + this.startWork(new SleeveBladeburnerWork({ type: "General", name: "Hyperbolic Regeneration Chamber" })); return true; case "Infiltrate synthoids": - this.startWork(p, new SleeveInfiltrateWork()); + this.startWork(new SleeveInfiltrateWork()); return true; case "Support main sleeve": - this.startWork(p, new SleeveSupportWork(p)); + this.startWork(new SleeveSupportWork()); return true; case "Take on contracts": if (!Contracts[contract]) return false; - this.startWork(p, new SleeveBladeburnerWork({ type: "Contracts", name: contract })); + this.startWork(new SleeveBladeburnerWork({ type: "Contracts", name: contract })); return true; } return false; } - recruitmentSuccessChance(p: IPlayer): number { - return Math.max(0, Math.min(1, p.bladeburner?.getRecruitmentSuccessChance(this) ?? 0)); + recruitmentSuccessChance(): number { + return Math.max(0, Math.min(1, Player.bladeburner?.getRecruitmentSuccessChance(this) ?? 0)); } - contractSuccessChance(p: IPlayer, type: string, name: string): string { - const bb = p.bladeburner; + contractSuccessChance(type: string, name: string): string { + const bb = Player.bladeburner; if (bb === null) { const errorLogText = `bladeburner is null`; console.error(`Function: sleeves.contractSuccessChance; Message: '${errorLogText}'`); diff --git a/src/PersonObjects/Sleeve/SleeveHelpers.ts b/src/PersonObjects/Sleeve/SleeveHelpers.ts index 3aa4aefc8..87460fe4c 100644 --- a/src/PersonObjects/Sleeve/SleeveHelpers.ts +++ b/src/PersonObjects/Sleeve/SleeveHelpers.ts @@ -1,7 +1,6 @@ import { FactionNames } from "../../Faction/data/FactionNames"; import { Sleeve } from "./Sleeve"; -import { IPlayer } from "../IPlayer"; import { Player } from "../../Player"; import { Augmentation } from "../../Augmentation/Augmentation"; @@ -11,7 +10,7 @@ import { Multipliers } from "../Multipliers"; import { AugmentationNames } from "../../Augmentation/data/AugmentationNames"; import { getFactionAugmentationsFiltered } from "../../Faction/FactionHelpers"; -export function findSleevePurchasableAugs(sleeve: Sleeve, p: IPlayer): Augmentation[] { +export function findSleevePurchasableAugs(sleeve: Sleeve): Augmentation[] { // You can only purchase Augmentations that are actually available from // your factions. I.e. you must be in a faction that has the Augmentation // and you must also have enough rep in that faction in order to purchase it. @@ -55,21 +54,21 @@ export function findSleevePurchasableAugs(sleeve: Sleeve, p: IPlayer): Augmentat // If player is in a gang, then we return all augs that the player // has enough reputation for (since that gang offers all augs) - if (p.inGang()) { - const fac = p.getGangFaction(); - const gangAugs = getFactionAugmentationsFiltered(Player, fac); + if (Player.inGang()) { + const fac = Player.getGangFaction(); + const gangAugs = getFactionAugmentationsFiltered(fac); for (const augName of gangAugs) { const aug = StaticAugmentations[augName]; if (!isAvailableForSleeve(aug)) continue; - if (fac.playerReputation > aug.getCost(p).repCost) { + if (fac.playerReputation > aug.getCost().repCost) { availableAugs.push(aug); } } } - for (const facName of p.factions) { + for (const facName of Player.factions) { if (facName === FactionNames.Bladeburners) continue; if (facName === FactionNames.Netburners) continue; const fac = Factions[facName]; @@ -79,7 +78,7 @@ export function findSleevePurchasableAugs(sleeve: Sleeve, p: IPlayer): Augmentat const aug = StaticAugmentations[augName]; if (!isAvailableForSleeve(aug)) continue; - if (fac.playerReputation > aug.getCost(p).repCost) { + if (fac.playerReputation > aug.getCost().repCost) { availableAugs.push(aug); } } diff --git a/src/PersonObjects/Sleeve/Work/SleeveBladeburnerWork.ts b/src/PersonObjects/Sleeve/Work/SleeveBladeburnerWork.ts index 198357a98..cd4de69de 100644 --- a/src/PersonObjects/Sleeve/Work/SleeveBladeburnerWork.ts +++ b/src/PersonObjects/Sleeve/Work/SleeveBladeburnerWork.ts @@ -1,4 +1,4 @@ -import { IPlayer } from "../../IPlayer"; +import { Player } from "../../../Player"; import { Generic_fromJSON, Generic_toJSON, IReviverValue, Reviver } from "../../../utils/JSONReviver"; import { Sleeve } from "../Sleeve"; import { applySleeveGains, Work, WorkType } from "./Work"; @@ -25,45 +25,45 @@ export class SleeveBladeburnerWork extends Work { this.actionName = params?.name ?? "Field analysis"; } - cyclesNeeded(player: IPlayer, sleeve: Sleeve): number { - const ret = player.bladeburner?.getActionTimeNetscriptFn(sleeve, this.actionType, this.actionName); + cyclesNeeded(sleeve: Sleeve): number { + const ret = Player.bladeburner?.getActionTimeNetscriptFn(sleeve, this.actionType, this.actionName); if (!ret || typeof ret === "string") throw new Error(`Error querying ${this.actionName} time`); return ret / CONSTANTS._idleSpeed; } - process(player: IPlayer, sleeve: Sleeve, cycles: number): number { - if (!player.bladeburner) throw new Error("sleeve doing blade work without being a member"); + process(sleeve: Sleeve, cycles: number): number { + if (!Player.bladeburner) throw new Error("sleeve doing blade work without being a member"); this.cyclesWorked += cycles; - const actionIdent = player.bladeburner.getActionIdFromTypeAndName(this.actionType, this.actionName); + const actionIdent = Player.bladeburner.getActionIdFromTypeAndName(this.actionType, this.actionName); if (!actionIdent) throw new Error(`Error getting ${this.actionName} action`); if (this.actionType === "Contracts") { - const action = player.bladeburner.getActionObject(actionIdent); + const action = Player.bladeburner.getActionObject(actionIdent); if (!action) throw new Error(`Error getting ${this.actionName} action object`); if (action.count <= 0) { - sleeve.stopWork(player); + sleeve.stopWork(); return 0; } } - while (this.cyclesWorked > this.cyclesNeeded(player, sleeve)) { + while (this.cyclesWorked > this.cyclesNeeded(sleeve)) { if (this.actionType === "Contracts") { - const action = player.bladeburner.getActionObject(actionIdent); + const action = Player.bladeburner.getActionObject(actionIdent); if (!action) throw new Error(`Error getting ${this.actionName} action object`); if (action.count <= 0) { - sleeve.stopWork(player); + sleeve.stopWork(); return 0; } } - const retValue = player.bladeburner.completeAction(player, sleeve, actionIdent, false); + const retValue = Player.bladeburner.completeAction(sleeve, actionIdent, false); let exp: WorkStats | undefined; if (this.actionType === "General") { exp = GeneralActions[this.actionName]?.exp; if (!exp) throw new Error(`Somehow there was no exp for action ${this.actionType} ${this.actionName}`); - applySleeveGains(player, sleeve, exp, 1); + applySleeveGains(sleeve, exp, 1); } - player.gainMoney(retValue.money, "sleeves"); - player.gainStats(retValue); - this.cyclesWorked -= this.cyclesNeeded(player, sleeve); + Player.gainMoney(retValue.money, "sleeves"); + Player.gainStats(retValue); + this.cyclesWorked -= this.cyclesNeeded(sleeve); } return 0; } diff --git a/src/PersonObjects/Sleeve/Work/SleeveClassWork.ts b/src/PersonObjects/Sleeve/Work/SleeveClassWork.ts index ee498fd49..8d8213c6f 100644 --- a/src/PersonObjects/Sleeve/Work/SleeveClassWork.ts +++ b/src/PersonObjects/Sleeve/Work/SleeveClassWork.ts @@ -24,9 +24,9 @@ export class SleeveClassWork extends Work { this.location = params?.location ?? LocationName.Sector12RothmanUniversity; } - calculateRates(player: IPlayer, sleeve: Sleeve): WorkStats { + calculateRates(sleeve: Sleeve): WorkStats { return scaleWorkStats( - calculateClassEarnings(player, sleeve, this.classType, this.location), + calculateClassEarnings(sleeve, this.classType, this.location), sleeve.shockBonus(), false, ); @@ -38,9 +38,9 @@ export class SleeveClassWork extends Work { ); } - process(player: IPlayer, sleeve: Sleeve, cycles: number): number { - const rate = this.calculateRates(player, sleeve); - applySleeveGains(player, sleeve, rate, cycles); + process(sleeve: Sleeve, cycles: number): number { + const rate = this.calculateRates(sleeve); + applySleeveGains(sleeve, rate, cycles); return 0; } APICopy(): Record { diff --git a/src/PersonObjects/Sleeve/Work/SleeveCompanyWork.ts b/src/PersonObjects/Sleeve/Work/SleeveCompanyWork.ts index 70a80216f..795f3d451 100644 --- a/src/PersonObjects/Sleeve/Work/SleeveCompanyWork.ts +++ b/src/PersonObjects/Sleeve/Work/SleeveCompanyWork.ts @@ -30,14 +30,14 @@ export class SleeveCompanyWork extends Work { return c; } - getGainRates(player: IPlayer, sleeve: Sleeve): WorkStats { - return calculateCompanyWorkStats(player, sleeve, this.getCompany()); + getGainRates(sleeve: Sleeve): WorkStats { + return calculateCompanyWorkStats(sleeve, this.getCompany()); } - process(player: IPlayer, sleeve: Sleeve, cycles: number): number { + process(sleeve: Sleeve, cycles: number): number { const company = this.getCompany(); - const gains = this.getGainRates(player, sleeve); - applySleeveGains(player, sleeve, gains, cycles); + const gains = this.getGainRates(sleeve); + applySleeveGains(sleeve, gains, cycles); company.playerReputation += gains.reputation * cycles; influenceStockThroughCompanyWork(company, gains.reputation, cycles); return 0; diff --git a/src/PersonObjects/Sleeve/Work/SleeveCrimeWork.ts b/src/PersonObjects/Sleeve/Work/SleeveCrimeWork.ts index 30aa8c847..75d315452 100644 --- a/src/PersonObjects/Sleeve/Work/SleeveCrimeWork.ts +++ b/src/PersonObjects/Sleeve/Work/SleeveCrimeWork.ts @@ -1,4 +1,4 @@ -import { IPlayer } from "../../IPlayer"; +import { Player } from "../../../Player"; import { Generic_fromJSON, Generic_toJSON, IReviverValue, Reviver } from "../../../utils/JSONReviver"; import { Sleeve } from "../Sleeve"; import { applySleeveGains, Work, WorkType } from "./Work"; @@ -43,19 +43,19 @@ export class SleeveCrimeWork extends Work { return this.getCrime().time / CONSTANTS._idleSpeed; } - process(player: IPlayer, sleeve: Sleeve, cycles: number): number { + process(sleeve: Sleeve, cycles: number): number { this.cyclesWorked += cycles; const crime = this.getCrime(); let gains = this.getExp(); if (this.cyclesWorked >= this.cyclesNeeded()) { if (Math.random() < crime.successRate(sleeve)) { - player.karma -= crime.karma * sleeve.syncBonus(); + Player.karma -= crime.karma * sleeve.syncBonus(); } else { gains.money = 0; gains = scaleWorkStats(gains, 0.25); } - applySleeveGains(player, sleeve, gains, cycles); + applySleeveGains(sleeve, gains, cycles); this.cyclesWorked -= this.cyclesNeeded(); } return 0; diff --git a/src/PersonObjects/Sleeve/Work/SleeveFactionWork.ts b/src/PersonObjects/Sleeve/Work/SleeveFactionWork.ts index 398374f37..d4df44ba5 100644 --- a/src/PersonObjects/Sleeve/Work/SleeveFactionWork.ts +++ b/src/PersonObjects/Sleeve/Work/SleeveFactionWork.ts @@ -1,4 +1,4 @@ -import { IPlayer } from "../../IPlayer"; +import { Player } from "../../../Player"; import { Generic_fromJSON, Generic_toJSON, IReviverValue, Reviver } from "../../../utils/JSONReviver"; import { Sleeve } from "../Sleeve"; import { applySleeveGains, Work, WorkType } from "./Work"; @@ -57,16 +57,14 @@ export class SleeveFactionWork extends Work { return f; } - process(player: IPlayer, sleeve: Sleeve, cycles: number): number { - if (player.gang) { - if (this.factionName === player.gang.facName) { - sleeve.stopWork(player); - return 0; - } + process(sleeve: Sleeve, cycles: number): number { + if (this.factionName === Player.gang?.facName) { + sleeve.stopWork(); + return 0; } const exp = this.getExpRates(sleeve); - applySleeveGains(player, sleeve, exp, cycles); + applySleeveGains(sleeve, exp, cycles); const rep = this.getReputationRate(sleeve); this.getFaction().playerReputation += rep; return 0; diff --git a/src/PersonObjects/Sleeve/Work/SleeveInfiltrateWork.ts b/src/PersonObjects/Sleeve/Work/SleeveInfiltrateWork.ts index 1ad321e92..d0cf4f217 100644 --- a/src/PersonObjects/Sleeve/Work/SleeveInfiltrateWork.ts +++ b/src/PersonObjects/Sleeve/Work/SleeveInfiltrateWork.ts @@ -1,4 +1,4 @@ -import { IPlayer } from "../../IPlayer"; +import { Player } from "../../../Player"; import { Generic_fromJSON, Generic_toJSON, IReviverValue, Reviver } from "../../../utils/JSONReviver"; import { Sleeve } from "../Sleeve"; import { Work, WorkType } from "./Work"; @@ -20,12 +20,12 @@ export class SleeveInfiltrateWork extends Work { return infiltrateCycles; } - process(player: IPlayer, sleeve: Sleeve, cycles: number): number { - if (!player.bladeburner) throw new Error("sleeve doing blade work without being a member"); + process(_sleeve: Sleeve, cycles: number): number { + if (!Player.bladeburner) throw new Error("sleeve doing blade work without being a member"); this.cyclesWorked += cycles; if (this.cyclesWorked > this.cyclesNeeded()) { this.cyclesWorked -= this.cyclesNeeded(); - player.bladeburner.infiltrateSynthoidCommunities(player); + Player.bladeburner.infiltrateSynthoidCommunities(); } return 0; } diff --git a/src/PersonObjects/Sleeve/Work/SleeveRecoveryWork.ts b/src/PersonObjects/Sleeve/Work/SleeveRecoveryWork.ts index 5f0de0a5d..98707b6fc 100644 --- a/src/PersonObjects/Sleeve/Work/SleeveRecoveryWork.ts +++ b/src/PersonObjects/Sleeve/Work/SleeveRecoveryWork.ts @@ -1,4 +1,3 @@ -import { IPlayer } from "../../IPlayer"; import { Generic_fromJSON, Generic_toJSON, IReviverValue, Reviver } from "../../../utils/JSONReviver"; import { Sleeve } from "../Sleeve"; import { Work, WorkType } from "./Work"; @@ -11,9 +10,9 @@ export class SleeveRecoveryWork extends Work { super(WorkType.RECOVERY); } - process(player: IPlayer, sleeve: Sleeve, cycles: number): number { + process(sleeve: Sleeve, cycles: number): number { sleeve.shock = Math.min(100, sleeve.shock + 0.0002 * cycles); - if (sleeve.shock >= 100) sleeve.stopWork(player); + if (sleeve.shock >= 100) sleeve.stopWork(); return 0; } diff --git a/src/PersonObjects/Sleeve/Work/SleeveSupportWork.ts b/src/PersonObjects/Sleeve/Work/SleeveSupportWork.ts index 5dfa02b7c..86d34184a 100644 --- a/src/PersonObjects/Sleeve/Work/SleeveSupportWork.ts +++ b/src/PersonObjects/Sleeve/Work/SleeveSupportWork.ts @@ -1,4 +1,4 @@ -import { IPlayer } from "../../../PersonObjects/IPlayer"; +import { Player } from "../../../Player"; import { Generic_fromJSON, Generic_toJSON, IReviverValue, Reviver } from "../../../utils/JSONReviver"; import { Work, WorkType } from "./Work"; @@ -6,17 +6,17 @@ export const isSleeveSupportWork = (w: Work | null): w is SleeveSupportWork => w !== null && w.type === WorkType.SUPPORT; export class SleeveSupportWork extends Work { - constructor(player?: IPlayer) { + constructor() { super(WorkType.SUPPORT); - if (player) player.bladeburner?.sleeveSupport(true); + Player.bladeburner?.sleeveSupport(true); } process(): number { return 0; } - finish(player: IPlayer): void { - player.bladeburner?.sleeveSupport(false); + finish(): void { + Player.bladeburner?.sleeveSupport(false); } APICopy(): Record { diff --git a/src/PersonObjects/Sleeve/Work/SleeveSynchroWork.ts b/src/PersonObjects/Sleeve/Work/SleeveSynchroWork.ts index 09b5584d3..54d52fe56 100644 --- a/src/PersonObjects/Sleeve/Work/SleeveSynchroWork.ts +++ b/src/PersonObjects/Sleeve/Work/SleeveSynchroWork.ts @@ -1,4 +1,4 @@ -import { IPlayer } from "../../IPlayer"; +import { Player } from "../../../Player"; import { Generic_fromJSON, Generic_toJSON, IReviverValue, Reviver } from "../../../utils/JSONReviver"; import { Sleeve } from "../Sleeve"; import { Work, WorkType } from "./Work"; @@ -11,9 +11,9 @@ export class SleeveSynchroWork extends Work { super(WorkType.SYNCHRO); } - process(player: IPlayer, sleeve: Sleeve, cycles: number): number { - sleeve.sync = Math.min(100, sleeve.sync + player.getIntelligenceBonus(0.5) * 0.0002 * cycles); - if (sleeve.sync >= 100) sleeve.stopWork(player); + process(sleeve: Sleeve, cycles: number): number { + sleeve.sync = Math.min(100, sleeve.sync + Player.getIntelligenceBonus(0.5) * 0.0002 * cycles); + if (sleeve.sync >= 100) sleeve.stopWork(); return 0; } diff --git a/src/PersonObjects/Sleeve/Work/Work.ts b/src/PersonObjects/Sleeve/Work/Work.ts index 201b73015..b588a99bd 100644 --- a/src/PersonObjects/Sleeve/Work/Work.ts +++ b/src/PersonObjects/Sleeve/Work/Work.ts @@ -1,14 +1,14 @@ -import { IPlayer } from "../../IPlayer"; +import { Player } from "../../../Player"; import { IReviverValue } from "../../../utils/JSONReviver"; import { Sleeve } from "../Sleeve"; import { applyWorkStats, applyWorkStatsExp, scaleWorkStats, WorkStats } from "../../../Work/WorkStats"; -export const applySleeveGains = (player: IPlayer, sleeve: Sleeve, rawStats: WorkStats, cycles = 1): void => { +export const applySleeveGains = (sleeve: Sleeve, rawStats: WorkStats, cycles = 1): void => { const shockedStats = scaleWorkStats(rawStats, sleeve.shockBonus(), rawStats.money > 0); applyWorkStatsExp(sleeve, shockedStats, cycles); const syncStats = scaleWorkStats(shockedStats, sleeve.syncBonus(), rawStats.money > 0); - applyWorkStats(player, player, syncStats, cycles, "sleeves"); - player.sleeves.filter((s) => s != sleeve).forEach((s) => applyWorkStatsExp(s, syncStats, cycles)); + applyWorkStats(Player, syncStats, cycles, "sleeves"); + Player.sleeves.filter((s) => s !== sleeve).forEach((s) => applyWorkStatsExp(s, syncStats, cycles)); }; export abstract class Work { @@ -18,10 +18,10 @@ export abstract class Work { this.type = type; } - abstract process(player: IPlayer, sleeve: Sleeve, cycles: number): number; + abstract process(sleeve: Sleeve, cycles: number): number; abstract APICopy(): Record; abstract toJSON(): IReviverValue; - finish(__player: IPlayer): void { + finish(): void { /* left for children to implement */ } } diff --git a/src/PersonObjects/Sleeve/ui/CovenantPurchasesRoot.tsx b/src/PersonObjects/Sleeve/ui/CovenantPurchasesRoot.tsx index 10278017b..0fb597bc9 100644 --- a/src/PersonObjects/Sleeve/ui/CovenantPurchasesRoot.tsx +++ b/src/PersonObjects/Sleeve/ui/CovenantPurchasesRoot.tsx @@ -56,7 +56,7 @@ export function CovenantPurchasesRoot(props: IProps): React.ReactElement { if (player.canAfford(purchaseCost())) { player.loseMoney(purchaseCost(), "sleeves"); player.sleevesFromCovenant += 1; - player.sleeves.push(new Sleeve(player)); + player.sleeves.push(new Sleeve()); rerender(); } else { dialogBoxCreate(`You cannot afford to purchase a Duplicate Sleeve`); @@ -67,7 +67,7 @@ export function CovenantPurchasesRoot(props: IProps): React.ReactElement { const upgradePanels = []; for (let i = 0; i < player.sleeves.length; ++i) { const sleeve = player.sleeves[i]; - upgradePanels.push(); + upgradePanels.push(); } return ( @@ -81,7 +81,7 @@ export function CovenantPurchasesRoot(props: IProps): React.ReactElement {
    )} diff --git a/src/PersonObjects/Sleeve/ui/CovenantSleeveMemoryUpgrade.tsx b/src/PersonObjects/Sleeve/ui/CovenantSleeveMemoryUpgrade.tsx index ce1d81317..79219d993 100644 --- a/src/PersonObjects/Sleeve/ui/CovenantSleeveMemoryUpgrade.tsx +++ b/src/PersonObjects/Sleeve/ui/CovenantSleeveMemoryUpgrade.tsx @@ -5,7 +5,7 @@ import React, { useState } from "react"; import { Sleeve } from "../Sleeve"; -import { IPlayer } from "../../IPlayer"; +import { Player } from "../../../Player"; import { numeralWrapper } from "../../../ui/numeralFormat"; import { Money } from "../../../ui/React/Money"; @@ -18,7 +18,6 @@ import Paper from "@mui/material/Paper"; interface IProps { index: number; - p: IPlayer; rerender: () => void; sleeve: Sleeve; } @@ -52,16 +51,16 @@ export function CovenantSleeveMemoryUpgrade(props: IProps): React.ReactElement { function purchaseMemory(): void { const cost = getPurchaseCost(); - if (props.p.canAfford(cost)) { + if (Player.canAfford(cost)) { props.sleeve.upgradeMemory(amt); - props.p.loseMoney(cost, "sleeves"); + Player.loseMoney(cost, "sleeves"); props.rerender(); } } // Purchase button props const cost = getPurchaseCost(); - const purchaseBtnDisabled = !props.p.canAfford(cost); + const purchaseBtnDisabled = !Player.canAfford(cost); let purchaseBtnContent = <>; if (isNaN(amt)) { purchaseBtnContent = <>Invalid value; @@ -69,7 +68,7 @@ export function CovenantSleeveMemoryUpgrade(props: IProps): React.ReactElement { purchaseBtnContent = ( <> Purchase {amt} memory -  - + ); } diff --git a/src/PersonObjects/Sleeve/ui/SleeveAugmentationsModal.tsx b/src/PersonObjects/Sleeve/ui/SleeveAugmentationsModal.tsx index 582ba3df5..76e5c73a3 100644 --- a/src/PersonObjects/Sleeve/ui/SleeveAugmentationsModal.tsx +++ b/src/PersonObjects/Sleeve/ui/SleeveAugmentationsModal.tsx @@ -1,7 +1,7 @@ import { Container, Typography, Paper } from "@mui/material"; import React, { useEffect, useState } from "react"; import { PurchasableAugmentations } from "../../../Augmentation/ui/PurchasableAugmentations"; -import { use } from "../../../ui/Context"; +import { Player } from "../../../Player"; import { Modal } from "../../../ui/React/Modal"; import { Sleeve } from "../Sleeve"; import { findSleevePurchasableAugs } from "../SleeveHelpers"; @@ -13,7 +13,6 @@ interface IProps { } export function SleeveAugmentationsModal(props: IProps): React.ReactElement { - const player = use.Player(); const setRerender = useState(false)[1]; function rerender(): void { setRerender((old) => !old); @@ -30,7 +29,7 @@ export function SleeveAugmentationsModal(props: IProps): React.ReactElement { // You can only purchase Augmentations that are actually available from // your factions. I.e. you must be in a faction that has the Augmentation // and you must also have enough rep in that faction in order to purchase it. - const availableAugs = findSleevePurchasableAugs(props.sleeve, player); + const availableAugs = findSleevePurchasableAugs(props.sleeve); return ( @@ -50,12 +49,11 @@ export function SleeveAugmentationsModal(props: IProps): React.ReactElement { aug.name)} ownedAugNames={ownedAugNames} - player={player} - canPurchase={(player, aug) => { - return player.money > aug.baseCost; + canPurchase={(aug) => { + return Player.money > aug.baseCost; }} - purchaseAugmentation={(player, aug) => { - props.sleeve.tryBuyAugmentation(player, aug); + purchaseAugmentation={(aug) => { + props.sleeve.tryBuyAugmentation(aug); rerender(); }} sleeveAugs diff --git a/src/PersonObjects/Sleeve/ui/SleeveElem.tsx b/src/PersonObjects/Sleeve/ui/SleeveElem.tsx index 93aaf55d0..4d76044c9 100644 --- a/src/PersonObjects/Sleeve/ui/SleeveElem.tsx +++ b/src/PersonObjects/Sleeve/ui/SleeveElem.tsx @@ -2,7 +2,7 @@ import { Box, Button, Paper, Tooltip, Typography } from "@mui/material"; import React, { useState } from "react"; import { FactionWorkType } from "../../../Work/data/FactionWorkType"; import { CONSTANTS } from "../../../Constants"; -import { use } from "../../../ui/Context"; +import { Player } from "../../../Player"; import { numeralWrapper } from "../../../ui/numeralFormat"; import { ProgressBar } from "../../../ui/React/Progress"; import { Sleeve } from "../Sleeve"; @@ -27,7 +27,6 @@ interface IProps { } export function SleeveElem(props: IProps): React.ReactElement { - const player = use.Player(); const [statsOpen, setStatsOpen] = useState(false); const [travelOpen, setTravelOpen] = useState(false); const [augmentationsOpen, setAugmentationsOpen] = useState(false); @@ -39,28 +38,28 @@ export function SleeveElem(props: IProps): React.ReactElement { case "------": break; case "Work for Company": - props.sleeve.workForCompany(player, abc[1]); + props.sleeve.workForCompany(abc[1]); break; case "Work for Faction": - props.sleeve.workForFaction(player, abc[1], abc[2]); + props.sleeve.workForFaction(abc[1], abc[2]); break; case "Commit Crime": - props.sleeve.commitCrime(player, abc[1]); + props.sleeve.commitCrime(abc[1]); break; case "Take University Course": - props.sleeve.takeUniversityCourse(player, abc[2], abc[1]); + props.sleeve.takeUniversityCourse(abc[2], abc[1]); break; case "Workout at Gym": - props.sleeve.workoutAtGym(player, abc[2], abc[1]); + props.sleeve.workoutAtGym(abc[2], abc[1]); break; case "Perform Bladeburner Actions": - props.sleeve.bladeburner(player, abc[1], abc[2]); + props.sleeve.bladeburner(abc[1], abc[2]); break; case "Shock Recovery": - props.sleeve.shockRecovery(player); + props.sleeve.shockRecovery(); break; case "Synchronize": - props.sleeve.synchronize(player); + props.sleeve.synchronize(); break; default: console.error(`Invalid/Unrecognized taskValue in setSleeveTask(): ${abc[0]}`); @@ -130,7 +129,7 @@ export function SleeveElem(props: IProps): React.ReactElement { desc = ( <> This sleeve is currently attempting to perform {w.actionName}. ( - {((100 * w.cyclesWorked) / w.cyclesNeeded(player, props.sleeve)).toFixed(2)}%) + {((100 * w.cyclesWorked) / w.cyclesNeeded(props.sleeve)).toFixed(2)}%) ); } @@ -156,11 +155,11 @@ export function SleeveElem(props: IProps): React.ReactElement { - Insufficient funds : ""}> + Insufficient funds : ""}> @@ -202,7 +201,7 @@ export function SleeveElem(props: IProps): React.ReactElement { variant="determinate" value={ (props.sleeve.currentWork.cyclesWorked / - props.sleeve.currentWork.cyclesNeeded(player, props.sleeve)) * + props.sleeve.currentWork.cyclesNeeded(props.sleeve)) * 100 } color="primary" diff --git a/src/PersonObjects/Sleeve/ui/StatsElement.tsx b/src/PersonObjects/Sleeve/ui/StatsElement.tsx index 542988092..b257491fc 100644 --- a/src/PersonObjects/Sleeve/ui/StatsElement.tsx +++ b/src/PersonObjects/Sleeve/ui/StatsElement.tsx @@ -9,7 +9,6 @@ import { characterOverviewStyles as useStyles } from "../../../ui/React/Characte import { Money } from "../../../ui/React/Money"; import { MoneyRate } from "../../../ui/React/MoneyRate"; import { ReputationRate } from "../../../ui/React/ReputationRate"; -import { use } from "../../../ui/Context"; import { Sleeve } from "../Sleeve"; import { isSleeveClassWork } from "../Work/SleeveClassWork"; @@ -95,7 +94,6 @@ export function StatsElement(props: IProps): React.ReactElement { export function EarningsElement(props: IProps): React.ReactElement { const classes = useStyles(); - const player = use.Player(); let data: (string | JSX.Element)[][] = []; if (isSleeveCrimeWork(props.sleeve.currentWork)) { @@ -111,7 +109,7 @@ export function EarningsElement(props: IProps): React.ReactElement { ]; } if (isSleeveClassWork(props.sleeve.currentWork)) { - const rates = props.sleeve.currentWork.calculateRates(player, props.sleeve); + const rates = props.sleeve.currentWork.calculateRates(props.sleeve); data = [ [`Money:`, ], [`Hacking Exp:`, `${numeralWrapper.formatExp(5 * rates.hackExp)} / sec`], @@ -137,7 +135,7 @@ export function EarningsElement(props: IProps): React.ReactElement { } if (isSleeveCompanyWork(props.sleeve.currentWork)) { - const rates = props.sleeve.currentWork.getGainRates(player, props.sleeve); + const rates = props.sleeve.currentWork.getGainRates(props.sleeve); data = [ [`Money:`, ], [`Hacking Exp:`, `${numeralWrapper.formatExp(5 * rates.hackExp)} / sec`], diff --git a/src/PersonObjects/Sleeve/ui/TaskSelector.tsx b/src/PersonObjects/Sleeve/ui/TaskSelector.tsx index 8df94de47..e6dde19ad 100644 --- a/src/PersonObjects/Sleeve/ui/TaskSelector.tsx +++ b/src/PersonObjects/Sleeve/ui/TaskSelector.tsx @@ -1,6 +1,6 @@ import React, { useState } from "react"; import { Sleeve } from "../Sleeve"; -import { IPlayer } from "../../IPlayer"; +import { Player } from "../../../Player"; import { Crimes } from "../../../Crime/Crimes"; import { LocationName } from "../../../Locations/data/LocationNames"; import { CityName } from "../../../Locations/data/CityNames"; @@ -43,7 +43,6 @@ const bladeburnerSelectorOptions: string[] = [ interface IProps { sleeve: Sleeve; - player: IPlayer; setABC: (abc: string[]) => void; } @@ -52,10 +51,10 @@ interface ITaskDetails { second: (s1: string) => string[]; } -function possibleJobs(player: IPlayer, sleeve: Sleeve): string[] { +function possibleJobs(sleeve: Sleeve): string[] { // Array of all companies that other sleeves are working at const forbiddenCompanies: string[] = []; - for (const otherSleeve of player.sleeves) { + for (const otherSleeve of Player.sleeves) { if (sleeve === otherSleeve) { continue; } @@ -63,18 +62,18 @@ function possibleJobs(player: IPlayer, sleeve: Sleeve): string[] { forbiddenCompanies.push(otherSleeve.currentWork.companyName); } } - const allJobs: string[] = Object.keys(player.jobs); + const allJobs: string[] = Object.keys(Player.jobs); return allJobs.filter((company) => !forbiddenCompanies.includes(company)); } -function possibleFactions(player: IPlayer, sleeve: Sleeve): string[] { +function possibleFactions(sleeve: Sleeve): string[] { // Array of all factions that other sleeves are working for const forbiddenFactions = [FactionNames.Bladeburners as string, FactionNames.ShadowsOfAnarchy as string]; - if (player.gang) { - forbiddenFactions.push(player.gang.facName); + if (Player.gang) { + forbiddenFactions.push(Player.gang.facName); } - for (const otherSleeve of player.sleeves) { + for (const otherSleeve of Player.sleeves) { if (sleeve === otherSleeve) { continue; } @@ -84,7 +83,7 @@ function possibleFactions(player: IPlayer, sleeve: Sleeve): string[] { } const factions = []; - for (const fac of player.factions) { + for (const fac of Player.factions) { if (!forbiddenFactions.includes(fac)) { factions.push(fac); } @@ -98,13 +97,13 @@ function possibleFactions(player: IPlayer, sleeve: Sleeve): string[] { }); } -function possibleContracts(player: IPlayer, sleeve: Sleeve): string[] { - const bb = player.bladeburner; +function possibleContracts(sleeve: Sleeve): string[] { + const bb = Player.bladeburner; if (bb === null) { return ["------"]; } let contracts = bb.getContractNamesNetscriptFn(); - for (const otherSleeve of player.sleeves) { + for (const otherSleeve of Player.sleeves) { if (sleeve === otherSleeve) { continue; } @@ -120,28 +119,28 @@ function possibleContracts(player: IPlayer, sleeve: Sleeve): string[] { } const tasks: { - [key: string]: undefined | ((player: IPlayer, sleeve: Sleeve) => ITaskDetails); - ["------"]: (player: IPlayer, sleeve: Sleeve) => ITaskDetails; - ["Work for Company"]: (player: IPlayer, sleeve: Sleeve) => ITaskDetails; - ["Work for Faction"]: (player: IPlayer, sleeve: Sleeve) => ITaskDetails; - ["Commit Crime"]: (player: IPlayer, sleeve: Sleeve) => ITaskDetails; - ["Take University Course"]: (player: IPlayer, sleeve: Sleeve) => ITaskDetails; - ["Workout at Gym"]: (player: IPlayer, sleeve: Sleeve) => ITaskDetails; - ["Perform Bladeburner Actions"]: (player: IPlayer, sleeve: Sleeve) => ITaskDetails; - ["Shock Recovery"]: (player: IPlayer, sleeve: Sleeve) => ITaskDetails; - ["Synchronize"]: (player: IPlayer, sleeve: Sleeve) => ITaskDetails; + [key: string]: undefined | ((sleeve: Sleeve) => ITaskDetails); + ["------"]: (sleeve: Sleeve) => ITaskDetails; + ["Work for Company"]: (sleeve: Sleeve) => ITaskDetails; + ["Work for Faction"]: (sleeve: Sleeve) => ITaskDetails; + ["Commit Crime"]: (sleeve: Sleeve) => ITaskDetails; + ["Take University Course"]: (sleeve: Sleeve) => ITaskDetails; + ["Workout at Gym"]: (sleeve: Sleeve) => ITaskDetails; + ["Perform Bladeburner Actions"]: (sleeve: Sleeve) => ITaskDetails; + ["Shock Recovery"]: (sleeve: Sleeve) => ITaskDetails; + ["Synchronize"]: (sleeve: Sleeve) => ITaskDetails; } = { "------": (): ITaskDetails => { return { first: ["------"], second: () => ["------"] }; }, - "Work for Company": (player: IPlayer, sleeve: Sleeve): ITaskDetails => { - let jobs = possibleJobs(player, sleeve); + "Work for Company": (sleeve: Sleeve): ITaskDetails => { + let jobs = possibleJobs(sleeve); if (jobs.length === 0) jobs = ["------"]; return { first: jobs, second: () => ["------"] }; }, - "Work for Faction": (player: IPlayer, sleeve: Sleeve): ITaskDetails => { - let factions = possibleFactions(player, sleeve); + "Work for Faction": (sleeve: Sleeve): ITaskDetails => { + let factions = possibleFactions(sleeve); if (factions.length === 0) factions = ["------"]; return { @@ -168,7 +167,7 @@ const tasks: { "Commit Crime": (): ITaskDetails => { return { first: Object.values(Crimes).map((crime) => crime.name), second: () => ["------"] }; }, - "Take University Course": (player: IPlayer, sleeve: Sleeve): ITaskDetails => { + "Take University Course": (sleeve: Sleeve): ITaskDetails => { let universities: string[] = []; switch (sleeve.city) { case CityName.Aevum: @@ -187,7 +186,7 @@ const tasks: { return { first: universitySelectorOptions, second: () => universities }; }, - "Workout at Gym": (player: IPlayer, sleeve: Sleeve): ITaskDetails => { + "Workout at Gym": (sleeve: Sleeve): ITaskDetails => { let gyms: string[] = []; switch (sleeve.city) { case CityName.Aevum: @@ -206,12 +205,12 @@ const tasks: { return { first: gymSelectorOptions, second: () => gyms }; }, - "Perform Bladeburner Actions": (player: IPlayer, sleeve: Sleeve): ITaskDetails => { + "Perform Bladeburner Actions": (sleeve: Sleeve): ITaskDetails => { return { first: bladeburnerSelectorOptions, second: (s1: string) => { if (s1 === "Take on contracts") { - return possibleContracts(player, sleeve); + return possibleContracts(sleeve); } else { return ["------"]; } @@ -227,28 +226,28 @@ const tasks: { }; const canDo: { - [key: string]: undefined | ((player: IPlayer, sleeve: Sleeve) => boolean); - ["------"]: (player: IPlayer, sleeve: Sleeve) => boolean; - ["Work for Company"]: (player: IPlayer, sleeve: Sleeve) => boolean; - ["Work for Faction"]: (player: IPlayer, sleeve: Sleeve) => boolean; - ["Commit Crime"]: (player: IPlayer, sleeve: Sleeve) => boolean; - ["Take University Course"]: (player: IPlayer, sleeve: Sleeve) => boolean; - ["Workout at Gym"]: (player: IPlayer, sleeve: Sleeve) => boolean; - ["Perform Bladeburner Actions"]: (player: IPlayer, sleeve: Sleeve) => boolean; - ["Shock Recovery"]: (player: IPlayer, sleeve: Sleeve) => boolean; - ["Synchronize"]: (player: IPlayer, sleeve: Sleeve) => boolean; + [key: string]: undefined | ((sleeve: Sleeve) => boolean); + ["------"]: (sleeve: Sleeve) => boolean; + ["Work for Company"]: (sleeve: Sleeve) => boolean; + ["Work for Faction"]: (sleeve: Sleeve) => boolean; + ["Commit Crime"]: (sleeve: Sleeve) => boolean; + ["Take University Course"]: (sleeve: Sleeve) => boolean; + ["Workout at Gym"]: (sleeve: Sleeve) => boolean; + ["Perform Bladeburner Actions"]: (sleeve: Sleeve) => boolean; + ["Shock Recovery"]: (sleeve: Sleeve) => boolean; + ["Synchronize"]: (sleeve: Sleeve) => boolean; } = { "------": () => true, - "Work for Company": (player: IPlayer, sleeve: Sleeve) => possibleJobs(player, sleeve).length > 0, - "Work for Faction": (player: IPlayer, sleeve: Sleeve) => possibleFactions(player, sleeve).length > 0, + "Work for Company": (sleeve: Sleeve) => possibleJobs(sleeve).length > 0, + "Work for Faction": (sleeve: Sleeve) => possibleFactions(sleeve).length > 0, "Commit Crime": () => true, - "Take University Course": (player: IPlayer, sleeve: Sleeve) => + "Take University Course": (sleeve: Sleeve) => [CityName.Aevum, CityName.Sector12, CityName.Volhaven].includes(sleeve.city), - "Workout at Gym": (player: IPlayer, sleeve: Sleeve) => + "Workout at Gym": (sleeve: Sleeve) => [CityName.Aevum, CityName.Sector12, CityName.Volhaven].includes(sleeve.city), - "Perform Bladeburner Actions": (player: IPlayer) => player.inBladeburner(), - "Shock Recovery": (player: IPlayer, sleeve: Sleeve) => sleeve.shock < 100, - Synchronize: (player: IPlayer, sleeve: Sleeve) => sleeve.sync < 100, + "Perform Bladeburner Actions": () => Player.inBladeburner(), + "Shock Recovery": (sleeve: Sleeve) => sleeve.shock < 100, + Synchronize: (sleeve: Sleeve) => sleeve.sync < 100, }; function getABC(sleeve: Sleeve): [string, string, string] { @@ -345,12 +344,12 @@ export function TaskSelector(props: IProps): React.ReactElement { const [s2, setS2] = useState(abc[2]); const validActions = Object.keys(canDo).filter((k) => - (canDo[k] as (player: IPlayer, sleeve: Sleeve) => boolean)(props.player, props.sleeve), + (canDo[k] as (sleeve: Sleeve) => boolean)(props.sleeve), ); const detailsF = tasks[s0]; if (detailsF === undefined) throw new Error(`No function for task '${s0}'`); - const details = detailsF(props.player, props.sleeve); + const details = detailsF(props.sleeve); const details2 = details.second(s1); if (details.first.length > 0 && !details.first.includes(s1)) { @@ -366,7 +365,7 @@ export function TaskSelector(props: IProps): React.ReactElement { const n = event.target.value; const detailsF = tasks[n]; if (detailsF === undefined) throw new Error(`No function for task '${s0}'`); - const details = detailsF(props.player, props.sleeve); + const details = detailsF(props.sleeve); const details2 = details.second(details.first[0]) ?? ["------"]; setS2(details2[0]); setS1(details.first[0]); diff --git a/src/PersonObjects/Sleeve/ui/TravelModal.tsx b/src/PersonObjects/Sleeve/ui/TravelModal.tsx index 83ea6f663..27a715297 100644 --- a/src/PersonObjects/Sleeve/ui/TravelModal.tsx +++ b/src/PersonObjects/Sleeve/ui/TravelModal.tsx @@ -6,7 +6,7 @@ import { WorldMap } from "../../../ui/React/WorldMap"; import { CityName } from "../../../Locations/data/CityNames"; import { Settings } from "../../../Settings/Settings"; import { dialogBoxCreate } from "../../../ui/React/DialogBox"; -import { use } from "../../../ui/Context"; +import { Player } from "../../../Player"; import { Modal } from "../../../ui/React/Modal"; import Typography from "@mui/material/Typography"; import Button from "@mui/material/Button"; @@ -19,14 +19,13 @@ interface IProps { } export function TravelModal(props: IProps): React.ReactElement { - const player = use.Player(); function travel(city: string): void { - if (!player.canAfford(CONSTANTS.TravelCost)) { + if (!Player.canAfford(CONSTANTS.TravelCost)) { dialogBoxCreate("You cannot afford to have this sleeve travel to another city"); } props.sleeve.city = city as CityName; - player.loseMoney(CONSTANTS.TravelCost, "sleeve"); - props.sleeve.stopWork(player); + Player.loseMoney(CONSTANTS.TravelCost, "sleeve"); + props.sleeve.stopWork(); props.rerender(); props.onClose(); } @@ -36,7 +35,7 @@ export function TravelModal(props: IProps): React.ReactElement { <> Have this sleeve travel to a different city. This affects the gyms and universities at which this sleeve can - study. Traveling to a different city costs . It will + study. Traveling to a different city costs . It will also set your current sleeve task to idle. {Settings.DisableASCIIArt ? ( diff --git a/src/Prestige.ts b/src/Prestige.ts index b526946fe..1c919d549 100755 --- a/src/Prestige.ts +++ b/src/Prestige.ts @@ -37,7 +37,7 @@ const BitNode8StartingMoney = 250e6; // Prestige by purchasing augmentation export function prestigeAugmentation(): void { - initBitNodeMultipliers(Player); + initBitNodeMultipliers(); const maintainMembership = Player.factions.concat(Player.factionInvitations).filter(function (faction) { return Factions[faction].getInfo().keep; @@ -91,7 +91,7 @@ export function prestigeAugmentation(): void { // Stop a Terminal action if there is one. if (Terminal.action !== null) { - Terminal.finishAction(Router, Player, true); + Terminal.finishAction(true); } Terminal.clear(); LogBoxClearEvents.emit(); @@ -176,7 +176,7 @@ export function prestigeAugmentation(): void { // Prestige by destroying Bit Node and gaining a Source File export function prestigeSourceFile(flume: boolean): void { - initBitNodeMultipliers(Player); + initBitNodeMultipliers(); Player.prestigeSourceFile(); prestigeWorkerScripts(); // Delete all Worker Scripts objects @@ -185,7 +185,7 @@ export function prestigeSourceFile(flume: boolean): void { // Stop a Terminal action if there is one. if (Terminal.action !== null) { - Terminal.finishAction(Router, Player, true); + Terminal.finishAction(true); } Terminal.clear(); LogBoxClearEvents.emit(); @@ -225,7 +225,7 @@ export function prestigeSourceFile(flume: boolean): void { // Stop a Terminal action if there is one if (Terminal.action !== null) { - Terminal.finishAction(Router, Player, true); + Terminal.finishAction(true); } // Delete all Augmentations @@ -302,7 +302,7 @@ export function prestigeSourceFile(flume: boolean): void { hserver.cache = 5; hserver.updateHashRate(Player.mults.hacknet_node_money); hserver.updateHashCapacity(); - updateHashManagerCapacity(Player); + updateHashManagerCapacity(); } if (Player.bitNodeN === 13) { diff --git a/src/Programs/Program.ts b/src/Programs/Program.ts index 1b63e27ec..e05ecff3a 100644 --- a/src/Programs/Program.ts +++ b/src/Programs/Program.ts @@ -1,11 +1,8 @@ import { BaseServer } from "../Server/BaseServer"; -import { ITerminal } from "../Terminal/ITerminal"; -import { IPlayer } from "../PersonObjects/IPlayer"; -import { IRouter } from "../ui/Router"; export interface IProgramCreate { level: number; - req(p: IPlayer): boolean; // Function that indicates whether player meets requirements + req(): boolean; // Function that indicates whether player meets requirements time: number; tooltip: string; } @@ -13,12 +10,12 @@ export interface IProgramCreate { export class Program { name = ""; create: IProgramCreate | null; - run: (router: IRouter, terminal: ITerminal, player: IPlayer, server: BaseServer, args: string[]) => void; + run: (args: string[], server: BaseServer) => void; constructor( name: string, create: IProgramCreate | null, - run: (router: IRouter, terminal: ITerminal, player: IPlayer, server: BaseServer, args: string[]) => void, + run: (args: string[], server: BaseServer) => void, ) { this.name = name; this.create = create; diff --git a/src/Programs/ProgramHelpers.ts b/src/Programs/ProgramHelpers.ts index abb8b5049..ce0433c4b 100644 --- a/src/Programs/ProgramHelpers.ts +++ b/src/Programs/ProgramHelpers.ts @@ -1,10 +1,10 @@ import { Programs } from "./Programs"; import { Program } from "./Program"; -import { IPlayer } from "../PersonObjects/IPlayer"; +import { Player } from "../Player"; //Returns the programs this player can create. -export function getAvailableCreatePrograms(player: IPlayer): Program[] { +export function getAvailableCreatePrograms(): Program[] { const programs: Program[] = []; for (const key of Object.keys(Programs)) { // Non-creatable program @@ -12,10 +12,10 @@ export function getAvailableCreatePrograms(player: IPlayer): Program[] { if (create == null) continue; // Already has program - if (player.hasProgram(Programs[key].name)) continue; + if (Player.hasProgram(Programs[key].name)) continue; // Does not meet requirements - if (!create.req(player)) continue; + if (!create.req()) continue; programs.push(Programs[key]); } diff --git a/src/Programs/data/ProgramsMetadata.ts b/src/Programs/data/ProgramsMetadata.ts index 28c700c5f..a0369c569 100644 --- a/src/Programs/data/ProgramsMetadata.ts +++ b/src/Programs/data/ProgramsMetadata.ts @@ -2,9 +2,8 @@ import { IProgramCreate } from "../Program"; import { CONSTANTS } from "../../Constants"; import { BaseServer } from "../../Server/BaseServer"; import { Server } from "../../Server/Server"; -import { ITerminal } from "../../Terminal/ITerminal"; -import { IRouter } from "../../ui/Router"; -import { IPlayer } from "../../PersonObjects/IPlayer"; +import { Terminal } from "../../Terminal"; +import { Player } from "../../Player"; import { convertTimeMsToTimeElapsedString } from "../../utils/StringHelperFunctions"; import { GetServer } from "../../Server/AllServers"; import { numeralWrapper } from "../../ui/numeralFormat"; @@ -14,14 +13,14 @@ import { calculateHackingTime, calculateGrowTime, calculateWeakenTime } from ".. import { FactionNames } from "../../Faction/data/FactionNames"; function requireHackingLevel(lvl: number) { - return function (p: IPlayer) { - return p.skills.hacking + p.skills.intelligence / 2 >= lvl; + return function () { + return Player.skills.hacking + Player.skills.intelligence / 2 >= lvl; }; } function bitFlumeRequirements() { - return function (p: IPlayer) { - return p.sourceFiles.length > 0 && p.skills.hacking >= 1; + return function () { + return Player.sourceFiles.length > 0 && Player.skills.hacking >= 1; }; } @@ -29,7 +28,7 @@ interface IProgramCreationParams { key: string; name: string; create: IProgramCreate | null; - run: (router: IRouter, terminal: ITerminal, player: IPlayer, server: BaseServer, args: string[]) => void; + run: (args: string[], server: BaseServer) => void; } export const programsMetadata: IProgramCreationParams[] = [ @@ -42,24 +41,24 @@ export const programsMetadata: IProgramCreationParams[] = [ req: requireHackingLevel(1), time: CONSTANTS.MillisecondsPerFiveMinutes, }, - run: (router: IRouter, terminal: ITerminal, player: IPlayer, server: BaseServer): void => { + run: (_args:string[], server: BaseServer): void => { if (!(server instanceof Server)) { - terminal.error("Cannot nuke this kind of server."); + Terminal.error("Cannot nuke this kind of server."); return; } if (server.hasAdminRights) { - terminal.print("You already have root access to this computer. There is no reason to run NUKE.exe"); - terminal.print("You can now run scripts on this server."); + Terminal.print("You already have root access to this computer. There is no reason to run NUKE.exe"); + Terminal.print("You can now run scripts on this server."); return; } if (server.openPortCount >= server.numOpenPortsRequired) { server.hasAdminRights = true; - terminal.print("NUKE successful! Gained root access to " + server.hostname); - terminal.print("You can now run scripts on this server."); + Terminal.print("NUKE successful! Gained root access to " + server.hostname); + Terminal.print("You can now run scripts on this server."); return; } - terminal.print("NUKE unsuccessful. Not enough ports have been opened"); + Terminal.print("NUKE unsuccessful. Not enough ports have been opened"); }, }, { @@ -71,18 +70,18 @@ export const programsMetadata: IProgramCreationParams[] = [ req: requireHackingLevel(50), time: CONSTANTS.MillisecondsPerFiveMinutes * 2, }, - run: (router: IRouter, terminal: ITerminal, player: IPlayer, server: BaseServer): void => { + run: (_args:string[], server: BaseServer): void => { if (!(server instanceof Server)) { - terminal.error("Cannot run BruteSSH.exe on this kind of server."); + Terminal.error("Cannot run BruteSSH.exe on this kind of server."); return; } if (server.sshPortOpen) { - terminal.print("SSH Port (22) is already open!"); + Terminal.print("SSH Port (22) is already open!"); return; } server.sshPortOpen = true; - terminal.print("Opened SSH Port(22)!"); + Terminal.print("Opened SSH Port(22)!"); server.openPortCount++; }, }, @@ -95,18 +94,18 @@ export const programsMetadata: IProgramCreationParams[] = [ req: requireHackingLevel(100), time: CONSTANTS.MillisecondsPerHalfHour, }, - run: (router: IRouter, terminal: ITerminal, player: IPlayer, server: BaseServer): void => { + run: (_args:string[], server: BaseServer): void => { if (!(server instanceof Server)) { - terminal.error("Cannot run FTPCrack.exe on this kind of server."); + Terminal.error("Cannot run FTPCrack.exe on this kind of server."); return; } if (server.ftpPortOpen) { - terminal.print("FTP Port (21) is already open!"); + Terminal.print("FTP Port (21) is already open!"); return; } server.ftpPortOpen = true; - terminal.print("Opened FTP Port (21)!"); + Terminal.print("Opened FTP Port (21)!"); server.openPortCount++; }, }, @@ -119,18 +118,18 @@ export const programsMetadata: IProgramCreationParams[] = [ req: requireHackingLevel(250), time: CONSTANTS.MillisecondsPer2Hours, }, - run: (router: IRouter, terminal: ITerminal, player: IPlayer, server: BaseServer): void => { + run: (_args:string[], server: BaseServer): void => { if (!(server instanceof Server)) { - terminal.error("Cannot run relaySMTP.exe on this kind of server."); + Terminal.error("Cannot run relaySMTP.exe on this kind of server."); return; } if (server.smtpPortOpen) { - terminal.print("SMTP Port (25) is already open!"); + Terminal.print("SMTP Port (25) is already open!"); return; } server.smtpPortOpen = true; - terminal.print("Opened SMTP Port (25)!"); + Terminal.print("Opened SMTP Port (25)!"); server.openPortCount++; }, }, @@ -143,18 +142,18 @@ export const programsMetadata: IProgramCreationParams[] = [ req: requireHackingLevel(500), time: CONSTANTS.MillisecondsPer4Hours, }, - run: (router: IRouter, terminal: ITerminal, player: IPlayer, server: BaseServer): void => { + run: (_args:string[], server: BaseServer): void => { if (!(server instanceof Server)) { - terminal.error("Cannot run HTTPWorm.exe on this kind of server."); + Terminal.error("Cannot run HTTPWorm.exe on this kind of server."); return; } if (server.httpPortOpen) { - terminal.print("HTTP Port (80) is already open!"); + Terminal.print("HTTP Port (80) is already open!"); return; } server.httpPortOpen = true; - terminal.print("Opened HTTP Port (80)!"); + Terminal.print("Opened HTTP Port (80)!"); server.openPortCount++; }, }, @@ -167,18 +166,18 @@ export const programsMetadata: IProgramCreationParams[] = [ req: requireHackingLevel(750), time: CONSTANTS.MillisecondsPer8Hours, }, - run: (router: IRouter, terminal: ITerminal, player: IPlayer, server: BaseServer): void => { + run: (_args:string[], server: BaseServer): void => { if (!(server instanceof Server)) { - terminal.error("Cannot run SQLInject.exe on this kind of server."); + Terminal.error("Cannot run SQLInject.exe on this kind of server."); return; } if (server.sqlPortOpen) { - terminal.print("SQL Port (1433) is already open!"); + Terminal.print("SQL Port (1433) is already open!"); return; } server.sqlPortOpen = true; - terminal.print("Opened SQL Port (1433)!"); + Terminal.print("Opened SQL Port (1433)!"); server.openPortCount++; }, }, @@ -191,9 +190,9 @@ export const programsMetadata: IProgramCreationParams[] = [ req: requireHackingLevel(75), time: CONSTANTS.MillisecondsPerQuarterHour, }, - run: (router: IRouter, terminal: ITerminal): void => { - terminal.print("This executable cannot be run."); - terminal.print("DeepscanV1.exe lets you run 'scan-analyze' with a depth up to 5."); + run: (): void => { + Terminal.print("This executable cannot be run."); + Terminal.print("DeepscanV1.exe lets you run 'scan-analyze' with a depth up to 5."); }, }, { @@ -205,9 +204,9 @@ export const programsMetadata: IProgramCreationParams[] = [ req: requireHackingLevel(400), time: CONSTANTS.MillisecondsPer2Hours, }, - run: (router: IRouter, terminal: ITerminal): void => { - terminal.print("This executable cannot be run."); - terminal.print("DeepscanV2.exe lets you run 'scan-analyze' with a depth up to 10."); + run: (): void => { + Terminal.print("This executable cannot be run."); + Terminal.print("DeepscanV2.exe lets you run 'scan-analyze' with a depth up to 10."); }, }, { @@ -219,42 +218,42 @@ export const programsMetadata: IProgramCreationParams[] = [ req: requireHackingLevel(75), time: CONSTANTS.MillisecondsPerHalfHour, }, - run: (router: IRouter, terminal: ITerminal, player: IPlayer, server: BaseServer, args: string[]): void => { + run: (args: string[]): void => { if (args.length !== 1) { - terminal.error("Must pass a server hostname or IP as an argument for ServerProfiler.exe"); + Terminal.error("Must pass a server hostname or IP as an argument for ServerProfiler.exe"); return; } const targetServer = GetServer(args[0]); if (targetServer == null) { - terminal.error("Invalid server IP/hostname"); + Terminal.error("Invalid server IP/hostname"); return; } if (!(targetServer instanceof Server)) { - terminal.error(`ServerProfiler.exe can only be run on normal servers.`); + Terminal.error(`ServerProfiler.exe can only be run on normal servers.`); return; } - terminal.print(targetServer.hostname + ":"); - terminal.print("Server base security level: " + targetServer.baseDifficulty); - terminal.print("Server current security level: " + targetServer.hackDifficulty); - terminal.print("Server growth rate: " + targetServer.serverGrowth); - terminal.print( + Terminal.print(targetServer.hostname + ":"); + Terminal.print("Server base security level: " + targetServer.baseDifficulty); + Terminal.print("Server current security level: " + targetServer.hackDifficulty); + Terminal.print("Server growth rate: " + targetServer.serverGrowth); + Terminal.print( `Netscript hack() execution time: ${convertTimeMsToTimeElapsedString( - calculateHackingTime(targetServer, player) * 1000, + calculateHackingTime(targetServer, Player) * 1000, true, )}`, ); - terminal.print( + Terminal.print( `Netscript grow() execution time: ${convertTimeMsToTimeElapsedString( - calculateGrowTime(targetServer, player) * 1000, + calculateGrowTime(targetServer, Player) * 1000, true, )}`, ); - terminal.print( + Terminal.print( `Netscript weaken() execution time: ${convertTimeMsToTimeElapsedString( - calculateWeakenTime(targetServer, player) * 1000, + calculateWeakenTime(targetServer, Player) * 1000, true, )}`, ); @@ -269,10 +268,10 @@ export const programsMetadata: IProgramCreationParams[] = [ req: requireHackingLevel(25), time: CONSTANTS.MillisecondsPerQuarterHour, }, - run: (router: IRouter, terminal: ITerminal): void => { - terminal.print("This executable cannot be run."); - terminal.print("AutoLink.exe lets you automatically connect to other servers when using 'scan-analyze'."); - terminal.print("When using scan-analyze, click on a server's hostname to connect to it."); + run: (): void => { + Terminal.print("This executable cannot be run."); + Terminal.print("AutoLink.exe lets you automatically connect to other servers when using 'scan-analyze'."); + Terminal.print("When using scan-analyze, click on a server's hostname to connect to it."); }, }, { @@ -284,9 +283,9 @@ export const programsMetadata: IProgramCreationParams[] = [ req: requireHackingLevel(1000), time: CONSTANTS.MillisecondsPer4Hours, }, - run: (router: IRouter, terminal: ITerminal): void => { - terminal.print("This executable cannot be run."); - terminal.print("Formulas.exe lets you use the formulas API."); + run: (): void => { + Terminal.print("This executable cannot be run."); + Terminal.print("Formulas.exe lets you use the formulas API."); }, }, { @@ -306,19 +305,19 @@ export const programsMetadata: IProgramCreationParams[] = [ key: "Flight", name: "fl1ght.exe", create: null, - run: (router: IRouter, terminal: ITerminal, player: IPlayer): void => { + run: (): void => { const numAugReq = BitNodeMultipliers.DaedalusAugsRequirement; const fulfilled = - player.augmentations.length >= numAugReq && player.money > 1e11 && player.skills.hacking >= 2500; + Player.augmentations.length >= numAugReq && Player.money > 1e11 && Player.skills.hacking >= 2500; if (!fulfilled) { - terminal.print(`Augmentations: ${player.augmentations.length} / ${numAugReq}`); - terminal.print(`Money: ${numeralWrapper.formatMoney(player.money)} / $100b`); - terminal.print(`Hacking skill: ${player.skills.hacking} / 2500`); + Terminal.print(`Augmentations: ${Player.augmentations.length} / ${numAugReq}`); + Terminal.print(`Money: ${numeralWrapper.formatMoney(Player.money)} / $100b`); + Terminal.print(`Hacking skill: ${Player.skills.hacking} / 2500`); return; } - terminal.print("We will contact you."); - terminal.print(`-- ${FactionNames.Daedalus} --`); + Terminal.print("We will contact you."); + Terminal.print(`-- ${FactionNames.Daedalus} --`); }, }, ]; diff --git a/src/Programs/ui/ProgramsRoot.tsx b/src/Programs/ui/ProgramsRoot.tsx index a8638ab4a..767d6dda5 100644 --- a/src/Programs/ui/ProgramsRoot.tsx +++ b/src/Programs/ui/ProgramsRoot.tsx @@ -4,7 +4,8 @@ import { find } from "lodash"; import { Box, Typography, Button, Container, Paper } from "@mui/material"; import { Check, Lock, Create } from "@mui/icons-material"; -import { use } from "../../ui/Context"; +import { Router } from "../../ui/GameRoot"; +import { Player } from "../../Player"; import { Settings } from "../../Settings/Settings"; import { Programs } from "../Programs"; @@ -13,8 +14,6 @@ import { CreateProgramWork } from "../../Work/CreateProgramWork"; export const ProgramsSeen: string[] = []; export function ProgramsRoot(): React.ReactElement { - const player = use.Player(); - const router = use.Router(); const setRerender = useState(false)[1]; function rerender(): void { setRerender((old) => !old); @@ -25,13 +24,13 @@ export function ProgramsRoot(): React.ReactElement { const create = prog.create; if (create === null) return false; if (prog.name === "b1t_flum3.exe") { - return create.req(player); + return create.req(); } return true; }) .sort((a, b) => { - if (player.hasProgram(a.name)) return 1; - if (player.hasProgram(b.name)) return -1; + if (Player.hasProgram(a.name)) return 1; + if (Player.hasProgram(b.name)) return -1; return (a.create?.level ?? 0) - (b.create?.level ?? 0); }); @@ -48,11 +47,11 @@ export function ProgramsRoot(): React.ReactElement { }, []); const getHackingLevelRemaining = (lvl: number): number => { - return Math.ceil(Math.max(lvl - (player.skills.hacking + player.skills.intelligence / 2), 0)); + return Math.ceil(Math.max(lvl - (Player.skills.hacking + Player.skills.intelligence / 2), 0)); }; const getProgCompletion = (name: string): number => { - const programFile = find(player.getHomeComputer().programs, (p) => { + const programFile = find(Player.getHomeComputer().programs, (p) => { return p.startsWith(name) && p.endsWith("%-INC"); }); if (!programFile) return -1; @@ -84,31 +83,31 @@ export function ProgramsRoot(): React.ReactElement { return ( <> - {(player.hasProgram(program.name) && ) || - (create.req(player) && ) || } + {(Player.hasProgram(program.name) && ) || + (create.req() && ) || } {program.name} - {!player.hasProgram(program.name) && create.req(player) && ( + {!Player.hasProgram(program.name) && create.req() && ( )} - {player.hasProgram(program.name) || getHackingLevelRemaining(create.level) === 0 || ( + {Player.hasProgram(program.name) || getHackingLevelRemaining(create.level) === 0 || ( Unlocks in: {getHackingLevelRemaining(create.level)} hacking levels diff --git a/src/ScriptEditor/ui/ScriptEditorRoot.tsx b/src/ScriptEditor/ui/ScriptEditorRoot.tsx index f6f46f21e..fc9367b63 100644 --- a/src/ScriptEditor/ui/ScriptEditorRoot.tsx +++ b/src/ScriptEditor/ui/ScriptEditorRoot.tsx @@ -7,8 +7,8 @@ type ITextModel = monaco.editor.ITextModel; import { OptionsModal } from "./OptionsModal"; import { Options } from "./Options"; import { isValidFilePath } from "../../Terminal/DirectoryHelpers"; -import { IPlayer } from "../../PersonObjects/IPlayer"; -import { IRouter } from "../../ui/Router"; +import { Player } from "../../Player"; +import { Router } from "../../ui/GameRoot"; import { dialogBoxCreate } from "../../ui/React/DialogBox"; import { isScriptFilename } from "../../Script/isScriptFilename"; import { Script } from "../../Script/Script"; @@ -49,8 +49,6 @@ interface IProps { // Map of filename -> code files: Record; hostname: string; - player: IPlayer; - router: IRouter; vim: boolean; } @@ -156,7 +154,7 @@ export function Root(props: IProps): React.ReactElement { //Ctrl + b if (event.code == "KeyB" && (event.ctrlKey || event.metaKey)) { event.preventDefault(); - props.router.toTerminal(); + Router.toTerminal(); } // CTRL/CMD + S @@ -183,12 +181,12 @@ export function Root(props: IProps): React.ReactElement { save(); }); MonacoVim.VimMode.Vim.defineEx("quit", "q", function () { - props.router.toTerminal(); + Router.toTerminal(); }); const saveNQuit = (): void => { save(); - props.router.toTerminal(); + Router.toTerminal(); }; // "wqriteandquit" & "xriteandquit" are not typos, prefix must be found in full string MonacoVim.VimMode.Vim.defineEx("wqriteandquit", "wq", saveNQuit); @@ -252,7 +250,7 @@ export function Root(props: IProps): React.ReactElement { return; } const codeCopy = newCode + ""; - const ramUsage = calculateRamUsage(codeCopy, props.player.getCurrentServer().scripts); + const ramUsage = calculateRamUsage(codeCopy, Player.getCurrentServer().scripts); if (ramUsage.cost > 0) { const entries = ramUsage.entries?.sort((a, b) => b.cost - a.cost) ?? []; const entriesDisp = []; @@ -468,25 +466,25 @@ export function Root(props: IProps): React.ReactElement { server.scripts[i].saveScript( scriptToSave.fileName, scriptToSave.code, - props.player.currentServer, + Player.currentServer, server.scripts, ); if (Settings.SaveGameOnFileSave) saveObject.saveGame(); - props.router.toTerminal(); + Router.toTerminal(); return; } } //If the current script does NOT exist, create a new one const script = new Script(); - script.saveScript(scriptToSave.fileName, scriptToSave.code, props.player.currentServer, server.scripts); + script.saveScript(scriptToSave.fileName, scriptToSave.code, Player.currentServer, server.scripts); server.scripts.push(script); } else if (scriptToSave.isTxt) { for (let i = 0; i < server.textFiles.length; ++i) { if (server.textFiles[i].fn === scriptToSave.fileName) { server.textFiles[i].write(scriptToSave.code); if (Settings.SaveGameOnFileSave) saveObject.saveGame(); - props.router.toTerminal(); + Router.toTerminal(); return; } } @@ -498,7 +496,7 @@ export function Root(props: IProps): React.ReactElement { } if (Settings.SaveGameOnFileSave) saveObject.saveGame(); - props.router.toTerminal(); + Router.toTerminal(); } function save(): void { @@ -550,7 +548,7 @@ export function Root(props: IProps): React.ReactElement { server.scripts[i].saveScript( currentScript.fileName, currentScript.code, - props.player.currentServer, + Player.currentServer, server.scripts, ); if (Settings.SaveGameOnFileSave) saveObject.saveGame(); @@ -561,7 +559,7 @@ export function Root(props: IProps): React.ReactElement { //If the current script does NOT exist, create a new one const script = new Script(); - script.saveScript(currentScript.fileName, currentScript.code, props.player.currentServer, server.scripts); + script.saveScript(currentScript.fileName, currentScript.code, Player.currentServer, server.scripts); server.scripts.push(script); } else if (currentScript.isTxt) { for (let i = 0; i < server.textFiles.length; ++i) { @@ -653,7 +651,7 @@ export function Root(props: IProps): React.ReactElement { openScripts.splice(index, 1); if (openScripts.length === 0) { currentScript = null; - props.router.toTerminal(); + Router.toTerminal(); return; } @@ -905,7 +903,7 @@ export function Root(props: IProps): React.ReactElement { {ram} - diff --git a/src/Server/ServerPurchases.ts b/src/Server/ServerPurchases.ts index 3cf62635d..3811b4f58 100644 --- a/src/Server/ServerPurchases.ts +++ b/src/Server/ServerPurchases.ts @@ -7,7 +7,7 @@ import { safetlyCreateUniqueServer } from "./ServerHelpers"; import { BitNodeMultipliers } from "../BitNode/BitNodeMultipliers"; import { CONSTANTS } from "../Constants"; -import { IPlayer } from "../PersonObjects/IPlayer"; +import { Player } from "../Player"; import { dialogBoxCreate } from "../ui/React/DialogBox"; import { isPowerOfTwo } from "../utils/helpers/isPowerOfTwo"; @@ -50,15 +50,15 @@ export function getPurchaseServerMaxRam(): number { } // Manually purchase a server (NOT through Netscript) -export function purchaseServer(hostname: string, ram: number, cost: number, p: IPlayer): void { +export function purchaseServer(hostname: string, ram: number, cost: number): void { //Check if player has enough money - if (!p.canAfford(cost)) { + if (!Player.canAfford(cost)) { dialogBoxCreate("You don't have enough money to purchase this server!"); return; } //Maximum server limit - if (p.purchasedServers.length >= getPurchaseServerLimit()) { + if (Player.purchasedServers.length >= getPurchaseServerLimit()) { dialogBoxCreate( "You have reached the maximum limit of " + getPurchaseServerLimit() + @@ -87,32 +87,32 @@ export function purchaseServer(hostname: string, ram: number, cost: number, p: I AddToAllServers(newServ); // Add to Player's purchasedServers array - p.purchasedServers.push(newServ.hostname); + Player.purchasedServers.push(newServ.hostname); // Connect new server to home computer - const homeComputer = p.getHomeComputer(); + const homeComputer = Player.getHomeComputer(); homeComputer.serversOnNetwork.push(newServ.hostname); newServ.serversOnNetwork.push(homeComputer.hostname); - p.loseMoney(cost, "servers"); + Player.loseMoney(cost, "servers"); dialogBoxCreate("Server successfully purchased with hostname " + newServ.hostname); } // Manually upgrade RAM on home computer (NOT through Netscript) -export function purchaseRamForHomeComputer(p: IPlayer): void { - const cost = p.getUpgradeHomeRamCost(); - if (!p.canAfford(cost)) { +export function purchaseRamForHomeComputer(): void { + const cost = Player.getUpgradeHomeRamCost(); + if (!Player.canAfford(cost)) { dialogBoxCreate("You do not have enough money to purchase additional RAM for your home computer"); return; } - const homeComputer = p.getHomeComputer(); + const homeComputer = Player.getHomeComputer(); if (homeComputer.maxRam >= CONSTANTS.HomeComputerMaxRam) { dialogBoxCreate(`You cannot upgrade your home computer RAM because it is at its maximum possible value`); return; } homeComputer.maxRam *= 2; - p.loseMoney(cost, "servers"); + Player.loseMoney(cost, "servers"); } diff --git a/src/Sidebar/ui/SidebarRoot.tsx b/src/Sidebar/ui/SidebarRoot.tsx index 4453d2347..ebef6ceb5 100644 --- a/src/Sidebar/ui/SidebarRoot.tsx +++ b/src/Sidebar/ui/SidebarRoot.tsx @@ -45,8 +45,9 @@ import LiveHelpIcon from "@mui/icons-material/LiveHelp"; import ExpandLessIcon from "@mui/icons-material/ExpandLess"; import ExpandMoreIcon from "@mui/icons-material/ExpandMore"; -import { IRouter, Page } from "../../ui/Router"; -import { IPlayer } from "../../PersonObjects/IPlayer"; +import { Router } from "../../ui/GameRoot"; +import { Page } from "../../ui/Router"; +import { Player } from "../../Player"; import { CONSTANTS } from "../../Constants"; import { iTutorialSteps, iTutorialNextStep, ITutorial } from "../../InteractiveTutorial"; import { getAvailableCreatePrograms } from "../../Programs/ProgramHelpers"; @@ -103,8 +104,6 @@ const useStyles = makeStyles((theme: Theme) => ); interface IProps { - player: IPlayer; - router: IRouter; page: Page; opened: boolean; onToggled: (newValue: boolean) => void; @@ -140,122 +139,122 @@ export function SidebarRoot(props: IProps): React.ReactElement { const flashTutorial = ITutorial.currStep === iTutorialSteps.WorldDescription; - const augmentationCount = props.player.queuedAugmentations.length; - const invitationsCount = props.player.factionInvitations.filter((f) => !InvitationsSeen.includes(f)).length; - const programCount = getAvailableCreatePrograms(props.player).length - ProgramsSeen.length; + const augmentationCount = Player.queuedAugmentations.length; + const invitationsCount = Player.factionInvitations.filter((f) => !InvitationsSeen.includes(f)).length; + const programCount = getAvailableCreatePrograms().length - ProgramsSeen.length; const canOpenFactions = - props.player.factionInvitations.length > 0 || - props.player.factions.length > 0 || - props.player.augmentations.length > 0 || - props.player.queuedAugmentations.length > 0 || - props.player.sourceFiles.length > 0; + Player.factionInvitations.length > 0 || + Player.factions.length > 0 || + Player.augmentations.length > 0 || + Player.queuedAugmentations.length > 0 || + Player.sourceFiles.length > 0; const canOpenAugmentations = - props.player.augmentations.length > 0 || - props.player.queuedAugmentations.length > 0 || - props.player.sourceFiles.length > 0; + Player.augmentations.length > 0 || + Player.queuedAugmentations.length > 0 || + Player.sourceFiles.length > 0; - const canOpenSleeves = props.player.sleeves.length > 0; + const canOpenSleeves = Player.sleeves.length > 0; - const canCorporation = !!props.player.corporation; - const canGang = !!props.player.gang; - const canJob = Object.values(props.player.jobs).length > 0; - const canStockMarket = props.player.hasWseAccount; - const canBladeburner = !!props.player.bladeburner; - const canStaneksGift = props.player.augmentations.some((aug) => aug.name === AugmentationNames.StaneksGift1); + const canCorporation = !!Player.corporation; + const canGang = !!Player.gang; + const canJob = Object.values(Player.jobs).length > 0; + const canStockMarket = Player.hasWseAccount; + const canBladeburner = !!Player.bladeburner; + const canStaneksGift = Player.augmentations.some((aug) => aug.name === AugmentationNames.StaneksGift1); function clickTerminal(): void { - props.router.toTerminal(); + Router.toTerminal(); if (flashTerminal) iTutorialNextStep(); } function clickScriptEditor(): void { - props.router.toScriptEditor(); + Router.toScriptEditor(); } function clickStats(): void { - props.router.toStats(); + Router.toStats(); if (flashStats) iTutorialNextStep(); } function clickActiveScripts(): void { - props.router.toActiveScripts(); + Router.toActiveScripts(); if (flashActiveScripts) iTutorialNextStep(); } function clickCreateProgram(): void { - props.router.toCreateProgram(); + Router.toCreateProgram(); } function clickStaneksGift(): void { - props.router.toStaneksGift(); + Router.toStaneksGift(); } function clickFactions(): void { - props.router.toFactions(); + Router.toFactions(); } function clickAugmentations(): void { - props.router.toAugmentations(); + Router.toAugmentations(); } function clickSleeves(): void { - props.router.toSleeves(); + Router.toSleeves(); } function clickHacknet(): void { - props.router.toHacknetNodes(); + Router.toHacknetNodes(); if (flashHacknet) iTutorialNextStep(); } function clickCity(): void { - props.router.toCity(); + Router.toCity(); if (flashCity) iTutorialNextStep(); } function clickTravel(): void { - props.router.toTravel(); + Router.toTravel(); } function clickJob(): void { - props.router.toJob(Locations[Object.keys(props.player.jobs)[0]]); + Router.toJob(Locations[Object.keys(Player.jobs)[0]]); } function clickStockMarket(): void { - props.router.toStockMarket(); + Router.toStockMarket(); } function clickBladeburner(): void { - props.router.toBladeburner(); + Router.toBladeburner(); } function clickCorp(): void { - props.router.toCorporation(); + Router.toCorporation(); } function clickGang(): void { - props.router.toGang(); + Router.toGang(); } function clickTutorial(): void { - props.router.toTutorial(); + Router.toTutorial(); if (flashTutorial) iTutorialNextStep(); } function clickMilestones(): void { - props.router.toMilestones(); + Router.toMilestones(); } function clickOptions(): void { - props.router.toGameOptions(); + Router.toGameOptions(); } function clickDev(): void { - props.router.toDevMenu(); + Router.toDevMenu(); } function clickAchievements(): void { - props.router.toAchievements(); + Router.toAchievements(); } useEffect(() => { @@ -277,7 +276,7 @@ export function SidebarRoot(props: IProps): React.ReactElement { // Alt-g - Gang function handleShortcuts(this: Document, event: KeyboardEvent): void { if (Settings.DisableHotkeys) return; - if ((props.player.currentWork && props.player.focus) || props.router.page() === Page.BitVerse) return; + if ((Player.currentWork && Player.focus) || Router.page() === Page.BitVerse) return; if (event.code === KEYCODE.T && event.altKey) { event.preventDefault(); clickTerminal(); @@ -321,10 +320,10 @@ export function SidebarRoot(props: IProps): React.ReactElement { } else if (event.code === KEYCODE.O && event.altKey) { event.preventDefault(); clickOptions(); - } else if (event.code === KEYCODE.B && event.altKey && props.player.bladeburner) { + } else if (event.code === KEYCODE.B && event.altKey && Player.bladeburner) { event.preventDefault(); clickBladeburner(); - } else if (event.code === KEYCODE.G && event.altKey && props.player.gang) { + } else if (event.code === KEYCODE.G && event.altKey && Player.gang) { event.preventDefault(); clickGang(); } diff --git a/src/StockMarket/ui/InfoAndPurchases.tsx b/src/StockMarket/ui/InfoAndPurchases.tsx index afa3f7293..70749ead5 100644 --- a/src/StockMarket/ui/InfoAndPurchases.tsx +++ b/src/StockMarket/ui/InfoAndPurchases.tsx @@ -8,7 +8,7 @@ import React, { useState } from "react"; import { getStockMarket4SDataCost, getStockMarket4STixApiCost } from "../StockMarketCosts"; import { CONSTANTS } from "../../Constants"; -import { IPlayer } from "../../PersonObjects/IPlayer"; +import { Player } from "../../Player"; import { Money } from "../../ui/React/Money"; import { initStockMarket } from "../StockMarket"; @@ -23,24 +23,23 @@ import { StaticModal } from "../../ui/React/StaticModal"; import { FactionNames } from "../../Faction/data/FactionNames"; type IProps = { - p: IPlayer; rerender: () => void; }; function Purchase4SMarketDataTixApiAccessButton(props: IProps): React.ReactElement { function purchase4SMarketDataTixApiAccess(): void { - if (props.p.has4SDataTixApi) { + if (Player.has4SDataTixApi) { return; } - if (!props.p.canAfford(getStockMarket4STixApiCost())) { + if (!Player.canAfford(getStockMarket4STixApiCost())) { return; } - props.p.has4SDataTixApi = true; - props.p.loseMoney(getStockMarket4STixApiCost(), "stock"); + Player.has4SDataTixApi = true; + Player.loseMoney(getStockMarket4STixApiCost(), "stock"); props.rerender(); } - if (props.p.has4SDataTixApi) { + if (Player.has4SDataTixApi) { return ( Market Data TIX API Access @@ -51,7 +50,7 @@ function Purchase4SMarketDataTixApiAccessButton(props: IProps): React.ReactEleme return ( Requires TIX API Access ) : ( Let you access 4S Market Data through Netscript @@ -60,11 +59,11 @@ function Purchase4SMarketDataTixApiAccessButton(props: IProps): React.ReactEleme > @@ -73,7 +72,7 @@ function Purchase4SMarketDataTixApiAccessButton(props: IProps): React.ReactEleme } function PurchaseWseAccountButton(props: IProps): React.ReactElement { - if (props.p.hasWseAccount) { + if (Player.hasWseAccount) { return ( WSE Account @@ -81,15 +80,15 @@ function PurchaseWseAccountButton(props: IProps): React.ReactElement { ); } function purchaseWseAccount(): void { - if (props.p.hasWseAccount) { + if (Player.hasWseAccount) { return; } - if (!props.p.canAfford(CONSTANTS.WSEAccountCost)) { + if (!Player.canAfford(CONSTANTS.WSEAccountCost)) { return; } - props.p.hasWseAccount = true; + Player.hasWseAccount = true; initStockMarket(); - props.p.loseMoney(CONSTANTS.WSEAccountCost, "stock"); + Player.loseMoney(CONSTANTS.WSEAccountCost, "stock"); props.rerender(); } @@ -97,9 +96,9 @@ function PurchaseWseAccountButton(props: IProps): React.ReactElement { return ( <> To begin trading, you must first purchase an account: - ); @@ -107,18 +106,18 @@ function PurchaseWseAccountButton(props: IProps): React.ReactElement { function PurchaseTixApiAccessButton(props: IProps): React.ReactElement { function purchaseTixApiAccess(): void { - if (props.p.hasTixApiAccess) { + if (Player.hasTixApiAccess) { return; } - if (!props.p.canAfford(CONSTANTS.TIXAPICost)) { + if (!Player.canAfford(CONSTANTS.TIXAPICost)) { return; } - props.p.hasTixApiAccess = true; - props.p.loseMoney(CONSTANTS.TIXAPICost, "stock"); + Player.hasTixApiAccess = true; + Player.loseMoney(CONSTANTS.TIXAPICost, "stock"); props.rerender(); } - if (props.p.hasTixApiAccess) { + if (Player.hasTixApiAccess) { return ( TIX API Access @@ -127,9 +126,9 @@ function PurchaseTixApiAccessButton(props: IProps): React.ReactElement { } else { const cost = CONSTANTS.TIXAPICost; return ( - ); } @@ -137,17 +136,17 @@ function PurchaseTixApiAccessButton(props: IProps): React.ReactElement { function Purchase4SMarketDataButton(props: IProps): React.ReactElement { function purchase4SMarketData(): void { - if (props.p.has4SData) { + if (Player.has4SData) { return; } - if (!props.p.canAfford(getStockMarket4SDataCost())) { + if (!Player.canAfford(getStockMarket4SDataCost())) { return; } - props.p.has4SData = true; - props.p.loseMoney(getStockMarket4SDataCost(), "stock"); + Player.has4SData = true; + Player.loseMoney(getStockMarket4SDataCost(), "stock"); props.rerender(); } - if (props.p.has4SData) { + if (Player.has4SData) { return ( 4S Market Data Access @@ -160,9 +159,9 @@ function Purchase4SMarketDataButton(props: IProps): React.ReactElement { title={Lets you view additional pricing and volatility information about stocks} > - @@ -204,7 +203,7 @@ export function InfoAndPurchases(props: IProps): React.ReactElement { Commission Fees: Every transaction you make has a{" "} - commission fee. + commission fee.
    diff --git a/src/StockMarket/ui/StockMarketRoot.tsx b/src/StockMarket/ui/StockMarketRoot.tsx index 4f3bf7e89..a77e213ac 100644 --- a/src/StockMarket/ui/StockMarketRoot.tsx +++ b/src/StockMarket/ui/StockMarketRoot.tsx @@ -8,10 +8,9 @@ import { StockTickers } from "./StockTickers"; import { IStockMarket } from "../IStockMarket"; -import { IPlayer } from "../../PersonObjects/IPlayer"; +import { Player } from "../../Player"; type IProps = { - p: IPlayer; stockMarket: IStockMarket; }; @@ -27,8 +26,8 @@ export function StockMarketRoot(props: IProps): React.ReactElement { }, []); return ( <> - - {props.p.hasWseAccount && } + + {Player.hasWseAccount && } ); } diff --git a/src/StockMarket/ui/StockTicker.tsx b/src/StockMarket/ui/StockTicker.tsx index faf3c9abb..8f3abc596 100644 --- a/src/StockMarket/ui/StockTicker.tsx +++ b/src/StockMarket/ui/StockTicker.tsx @@ -17,7 +17,7 @@ import { PositionTypes } from "../data/PositionTypes"; import { placeOrder } from "../StockMarket"; import { buyStock, shortStock, sellStock, sellShort } from "../BuyingAndSelling"; -import { IPlayer } from "../../PersonObjects/IPlayer"; +import { Player } from "../../Player"; import { numeralWrapper } from "../../ui/numeralFormat"; import { Money } from "../../ui/React/Money"; @@ -42,7 +42,6 @@ enum SelectorOrderType { type IProps = { orders: Order[]; - p: IPlayer; rerenderAllTickers: () => void; stock: Stock; }; @@ -157,7 +156,7 @@ export function StockTicker(props: IProps): React.ReactElement { } function handleBuyMaxButtonClick(): void { - const playerMoney: number = props.p.money; + const playerMoney: number = Player.money; const stock = props.stock; let maxShares = calculateBuyMaxAmount(stock, position, playerMoney); @@ -274,18 +273,18 @@ export function StockTicker(props: IProps): React.ReactElement { // Whether the player has access to orders besides market orders (limit/stop) function hasOrderAccess(): boolean { - return props.p.bitNodeN === 8 || props.p.sourceFileLvl(8) >= 3; + return Player.bitNodeN === 8 || Player.sourceFileLvl(8) >= 3; } // Whether the player has access to shorting stocks function hasShortAccess(): boolean { - return props.p.bitNodeN === 8 || props.p.sourceFileLvl(8) >= 2; + return Player.bitNodeN === 8 || Player.sourceFileLvl(8) >= 2; } return ( setTicketOpen((old) => !old)}> - } /> + } /> {tickerOpen ? : } @@ -311,8 +310,8 @@ export function StockTicker(props: IProps): React.ReactElement { - - + + = 2) { + if (Player.bitNodeN === 8 || Player.sourceFileLvl(8) >= 2) { return ( <> diff --git a/src/StockMarket/ui/StockTickers.tsx b/src/StockMarket/ui/StockTickers.tsx index 12cf52165..a2a89eba7 100644 --- a/src/StockMarket/ui/StockTickers.tsx +++ b/src/StockMarket/ui/StockTickers.tsx @@ -11,10 +11,7 @@ import { StockTickersConfig, TickerDisplayMode } from "./StockTickersConfig"; import { IStockMarket } from "../IStockMarket"; import { Stock } from "../Stock"; -import { IPlayer } from "../../PersonObjects/IPlayer"; - type IProps = { - p: IPlayer; stockMarket: IStockMarket; }; @@ -67,9 +64,7 @@ export function StockTickers(props: IProps): React.ReactElement { } } - tickers.push( - , - ); + tickers.push(); } } diff --git a/src/Terminal/ITerminal.tsx b/src/Terminal/ITerminal.tsx index 6c7518096..c76e9e5b2 100644 --- a/src/Terminal/ITerminal.tsx +++ b/src/Terminal/ITerminal.tsx @@ -1,8 +1,6 @@ import React from "react"; import { TextFile } from "../TextFile"; import { Script } from "../Script/Script"; -import { IPlayer } from "../PersonObjects/IPlayer"; -import { IRouter } from "../ui/Router"; import { Settings } from "../Settings/Settings"; import { formatTime } from "../utils/helpers/formatTime"; import { BaseServer } from "../Server/BaseServer"; @@ -77,31 +75,31 @@ export interface ITerminal { warn(s: string): void; clear(): void; - startAnalyze(player: IPlayer): void; - startBackdoor(player: IPlayer): void; - startHack(player: IPlayer): void; - startGrow(player: IPlayer): void; - startWeaken(player: IPlayer): void; - finishHack(router: IRouter, player: IPlayer, server: BaseServer, cancelled?: boolean): void; - finishGrow(player: IPlayer, server: BaseServer, cancelled?: boolean): void; - finishWeaken(player: IPlayer, server: BaseServer, cancelled?: boolean): void; - finishBackdoor(router: IRouter, player: IPlayer, server: BaseServer, cancelled?: boolean): void; - finishAnalyze(player: IPlayer, server: BaseServer, cancelled?: boolean): void; - finishAction(router: IRouter, player: IPlayer, cancelled?: boolean): void; + startAnalyze(): void; + startBackdoor(): void; + startHack(): void; + startGrow(): void; + startWeaken(): void; + finishHack(server: BaseServer, cancelled?: boolean): void; + finishGrow(server: BaseServer, cancelled?: boolean): void; + finishWeaken(server: BaseServer, cancelled?: boolean): void; + finishBackdoor(server: BaseServer, cancelled?: boolean): void; + finishAnalyze(server: BaseServer, cancelled?: boolean): void; + finishAction(cancelled?: boolean): void; getFilepath(filename: string): string; - getFile(player: IPlayer, filename: string): Script | TextFile | string | null; - getScript(player: IPlayer, filename: string): Script | null; - getTextFile(player: IPlayer, filename: string): TextFile | null; - getLitFile(player: IPlayer, filename: string): string | null; + getFile(filename: string): Script | TextFile | string | null; + getScript(filename: string): Script | null; + getTextFile(filename: string): TextFile | null; + getLitFile(filename: string): string | null; cwd(): string; setcwd(dir: string): void; - runContract(player: IPlayer, name: string): void; - executeScanAnalyzeCommand(player: IPlayer, depth?: number, all?: boolean): void; - connectToServer(player: IPlayer, server: string): void; - executeCommand(router: IRouter, player: IPlayer, command: string): void; - executeCommands(router: IRouter, player: IPlayer, commands: string): void; + runContract(name: string): void; + executeScanAnalyzeCommand(depth?: number, all?: boolean): void; + connectToServer(server: string): void; + executeCommand(command: string): void; + executeCommands(commands: string): void; // If there was any changes, will return true, once. - process(router: IRouter, player: IPlayer, cycles: number): void; + process(cycles: number): void; prestige(): void; getProgressText(): string; } diff --git a/src/Terminal/Terminal.ts b/src/Terminal/Terminal.ts index cd2fb2d3f..e183eb19e 100644 --- a/src/Terminal/Terminal.ts +++ b/src/Terminal/Terminal.ts @@ -1,6 +1,6 @@ import { ITerminal, Output, Link, RawOutput, TTimer } from "./ITerminal"; -import { IRouter } from "../ui/Router"; -import { IPlayer } from "../PersonObjects/IPlayer"; +import { Router } from "../ui/GameRoot"; +import { Player } from "../Player"; import { HacknetServer } from "../Hacknet/HacknetServer"; import { BaseServer } from "../Server/BaseServer"; import { Server } from "../Server/Server"; @@ -93,10 +93,10 @@ export class Terminal implements ITerminal { // Excludes the trailing forward slash currDir = "/"; - process(router: IRouter, player: IPlayer, cycles: number): void { + process(cycles: number): void { if (this.action === null) return; this.action.timeLeft -= (CONSTANTS._idleSpeed * cycles) / 1000; - if (this.action.timeLeft < 0.01) this.finishAction(router, player, false); + if (this.action.timeLeft < 0.01) this.finishAction(false); TerminalEvents.emit(); } @@ -132,50 +132,50 @@ export class Terminal implements ITerminal { this.append(new Output(s, "warn")); } - startHack(player: IPlayer): void { + startHack(): void { // Hacking through Terminal should be faster than hacking through a script - const server = player.getCurrentServer(); + const server = Player.getCurrentServer(); if (server instanceof HacknetServer) { this.error("Cannot hack this kind of server"); return; } if (!(server instanceof Server)) throw new Error("server should be normal server"); - this.startAction(calculateHackingTime(server, player) / 4, "h", server); + this.startAction(calculateHackingTime(server, Player) / 4, "h", server); } - startGrow(player: IPlayer): void { - const server = player.getCurrentServer(); + startGrow(): void { + const server = Player.getCurrentServer(); if (server instanceof HacknetServer) { this.error("Cannot grow this kind of server"); return; } if (!(server instanceof Server)) throw new Error("server should be normal server"); - this.startAction(calculateGrowTime(server, player) / 16, "g", server); + this.startAction(calculateGrowTime(server, Player) / 16, "g", server); } - startWeaken(player: IPlayer): void { - const server = player.getCurrentServer(); + startWeaken(): void { + const server = Player.getCurrentServer(); if (server instanceof HacknetServer) { this.error("Cannot weaken this kind of server"); return; } if (!(server instanceof Server)) throw new Error("server should be normal server"); - this.startAction(calculateWeakenTime(server, player) / 16, "w", server); + this.startAction(calculateWeakenTime(server, Player) / 16, "w", server); } - startBackdoor(player: IPlayer): void { + startBackdoor(): void { // Backdoor should take the same amount of time as hack - const server = player.getCurrentServer(); + const server = Player.getCurrentServer(); if (server instanceof HacknetServer) { this.error("Cannot backdoor this kind of server"); return; } if (!(server instanceof Server)) throw new Error("server should be normal server"); - this.startAction(calculateHackingTime(server, player) / 4, "b", server); + this.startAction(calculateHackingTime(server, Player) / 4, "b", server); } - startAnalyze(player: IPlayer): void { + startAnalyze(): void { this.print("Analyzing system..."); - const server = player.getCurrentServer(); + const server = Player.getCurrentServer(); this.startAction(1, "a", server); } @@ -184,7 +184,7 @@ export class Terminal implements ITerminal { } // Complete the hack/analyze command - finishHack(router: IRouter, player: IPlayer, server: BaseServer, cancelled = false): void { + finishHack(server: BaseServer, cancelled = false): void { if (cancelled) return; if (server instanceof HacknetServer) { @@ -194,18 +194,18 @@ export class Terminal implements ITerminal { if (!(server instanceof Server)) throw new Error("server should be normal server"); // Calculate whether hack was successful - const hackChance = calculateHackingChance(server, player); + const hackChance = calculateHackingChance(server, Player); const rand = Math.random(); - const expGainedOnSuccess = calculateHackingExpGain(server, player); + const expGainedOnSuccess = calculateHackingExpGain(server, Player); const expGainedOnFailure = expGainedOnSuccess / 4; if (rand < hackChance) { // Success! server.backdoorInstalled = true; if (SpecialServers.WorldDaemon === server.hostname) { - router.toBitVerse(false, false); + Router.toBitVerse(false, false); return; } - let moneyGained = calculatePercentMoneyHacked(server, player) * BitNodeMultipliers.ManualHackMoney; + let moneyGained = calculatePercentMoneyHacked(server, Player) * BitNodeMultipliers.ManualHackMoney; moneyGained = Math.floor(server.moneyAvailable * moneyGained); if (moneyGained <= 0) { @@ -213,9 +213,9 @@ export class Terminal implements ITerminal { } // Safety check server.moneyAvailable -= moneyGained; - player.gainMoney(moneyGained, "hacking"); - player.gainHackingExp(expGainedOnSuccess); - player.gainIntelligenceExp(expGainedOnSuccess / CONSTANTS.IntelligenceTerminalHackBaseExpGain); + Player.gainMoney(moneyGained, "hacking"); + Player.gainHackingExp(expGainedOnSuccess); + Player.gainIntelligenceExp(expGainedOnSuccess / CONSTANTS.IntelligenceTerminalHackBaseExpGain); const oldSec = server.hackDifficulty; server.fortify(CONSTANTS.ServerFortifyAmount); @@ -233,14 +233,14 @@ export class Terminal implements ITerminal { ); } else { // Failure - player.gainHackingExp(expGainedOnFailure); + Player.gainHackingExp(expGainedOnFailure); this.print( `Failed to hack '${server.hostname}'. Gained ${numeralWrapper.formatExp(expGainedOnFailure)} hacking exp`, ); } } - finishGrow(player: IPlayer, server: BaseServer, cancelled = false): void { + finishGrow(server: BaseServer, cancelled = false): void { if (cancelled) return; if (server instanceof HacknetServer) { @@ -248,12 +248,12 @@ export class Terminal implements ITerminal { return; } if (!(server instanceof Server)) throw new Error("server should be normal server"); - const expGain = calculateHackingExpGain(server, player); + const expGain = calculateHackingExpGain(server, Player); const oldSec = server.hackDifficulty; - const growth = processSingleServerGrowth(server, 25, player, server.cpuCores) - 1; + const growth = processSingleServerGrowth(server, 25, Player, server.cpuCores) - 1; const newSec = server.hackDifficulty; - player.gainHackingExp(expGain); + Player.gainHackingExp(expGain); this.print( `Available money on '${server.hostname}' grown by ${numeralWrapper.formatPercentage( growth, @@ -267,7 +267,7 @@ export class Terminal implements ITerminal { ); } - finishWeaken(player: IPlayer, server: BaseServer, cancelled = false): void { + finishWeaken(server: BaseServer, cancelled = false): void { if (cancelled) return; if (server instanceof HacknetServer) { @@ -275,12 +275,12 @@ export class Terminal implements ITerminal { return; } if (!(server instanceof Server)) throw new Error("server should be normal server"); - const expGain = calculateHackingExpGain(server, player); + const expGain = calculateHackingExpGain(server, Player); const oldSec = server.hackDifficulty; server.weaken(CONSTANTS.ServerWeakenAmount); const newSec = server.hackDifficulty; - player.gainHackingExp(expGain); + Player.gainHackingExp(expGain); this.print( `Security decreased on '${server.hostname}' from ${numeralWrapper.formatSecurity( oldSec, @@ -289,7 +289,7 @@ export class Terminal implements ITerminal { ); } - finishBackdoor(router: IRouter, player: IPlayer, server: BaseServer, cancelled = false): void { + finishBackdoor(server: BaseServer, cancelled = false): void { if (!cancelled) { if (server instanceof HacknetServer) { this.error("Cannot hack this kind of server"); @@ -298,17 +298,17 @@ export class Terminal implements ITerminal { if (!(server instanceof Server)) throw new Error("server should be normal server"); server.backdoorInstalled = true; if (SpecialServers.WorldDaemon === server.hostname) { - if (player.bitNodeN == null) { - player.bitNodeN = 1; + if (Player.bitNodeN == null) { + Player.bitNodeN = 1; } - router.toBitVerse(false, false); + Router.toBitVerse(false, false); return; } this.print(`Backdoor on '${server.hostname}' successful!`); } } - finishAnalyze(player: IPlayer, currServ: BaseServer, cancelled = false): void { + finishAnalyze(currServ: BaseServer, cancelled = false): void { if (!cancelled) { const isHacknet = currServ instanceof HacknetServer; this.print(currServ.hostname + ": "); @@ -325,9 +325,9 @@ export class Terminal implements ITerminal { this.print("Required hacking skill for hack() and backdoor: " + (!isHacknet ? hackingSkill : "N/A")); const security = currServ.hackDifficulty; this.print("Server security level: " + (!isHacknet ? numeralWrapper.formatServerSecurity(security) : "N/A")); - const hackingChance = calculateHackingChance(currServ, player); + const hackingChance = calculateHackingChance(currServ, Player); this.print("Chance to hack: " + (!isHacknet ? numeralWrapper.formatPercentage(hackingChance) : "N/A")); - const hackingTime = calculateHackingTime(currServ, player) * 1000; + const hackingTime = calculateHackingTime(currServ, Player) * 1000; this.print("Time to hack: " + (!isHacknet ? convertTimeMsToTimeElapsedString(hackingTime, true) : "N/A")); } this.print( @@ -347,7 +347,7 @@ export class Terminal implements ITerminal { } } - finishAction(router: IRouter, player: IPlayer, cancelled = false): void { + finishAction(cancelled = false): void { if (this.action === null) { if (!cancelled) throw new Error("Finish action called when there was no action"); return; @@ -357,15 +357,15 @@ export class Terminal implements ITerminal { this.print(this.getProgressText()); if (this.action.action === "h") { - this.finishHack(router, player, this.action.server, cancelled); + this.finishHack(this.action.server, cancelled); } else if (this.action.action === "g") { - this.finishGrow(player, this.action.server, cancelled); + this.finishGrow(this.action.server, cancelled); } else if (this.action.action === "w") { - this.finishWeaken(player, this.action.server, cancelled); + this.finishWeaken(this.action.server, cancelled); } else if (this.action.action === "b") { - this.finishBackdoor(router, player, this.action.server, cancelled); + this.finishBackdoor(this.action.server, cancelled); } else if (this.action.action === "a") { - this.finishAnalyze(player, this.action.server, cancelled); + this.finishAnalyze(this.action.server, cancelled); } if (cancelled) { @@ -375,17 +375,17 @@ export class Terminal implements ITerminal { TerminalEvents.emit(); } - getFile(player: IPlayer, filename: string): Script | TextFile | string | null { + getFile(filename: string): Script | TextFile | string | null { if (isScriptFilename(filename)) { - return this.getScript(player, filename); + return this.getScript(filename); } if (filename.endsWith(".lit")) { - return this.getLitFile(player, filename); + return this.getLitFile(filename); } if (filename.endsWith(".txt")) { - return this.getTextFile(player, filename); + return this.getTextFile(filename); } return null; @@ -404,8 +404,8 @@ export class Terminal implements ITerminal { return path; } - getScript(player: IPlayer, filename: string): Script | null { - const s = player.getCurrentServer(); + getScript(filename: string): Script | null { + const s = Player.getCurrentServer(); const filepath = this.getFilepath(filename); for (const script of s.scripts) { if (filepath === script.filename) { @@ -416,8 +416,8 @@ export class Terminal implements ITerminal { return null; } - getTextFile(player: IPlayer, filename: string): TextFile | null { - const s = player.getCurrentServer(); + getTextFile(filename: string): TextFile | null { + const s = Player.getCurrentServer(); const filepath = this.getFilepath(filename); for (const txt of s.textFiles) { if (filepath === txt.fn) { @@ -428,8 +428,8 @@ export class Terminal implements ITerminal { return null; } - getLitFile(player: IPlayer, filename: string): string | null { - const s = player.getCurrentServer(); + getLitFile(filename: string): string | null { + const s = Player.getCurrentServer(); const filepath = this.getFilepath(filename); for (const lit of s.messages) { if (typeof lit === "string" && filepath === lit) { @@ -449,13 +449,13 @@ export class Terminal implements ITerminal { TerminalEvents.emit(); } - async runContract(player: IPlayer, contractName: string): Promise { + async runContract(contractName: string): Promise { // There's already an opened contract if (this.contractOpen) { return this.error("There's already a Coding Contract in Progress"); } - const serv = player.getCurrentServer(); + const serv = Player.getCurrentServer(); const contract = serv.getContract(contractName); if (contract == null) { return this.error("No such contract"); @@ -473,7 +473,7 @@ export class Terminal implements ITerminal { switch (res) { case CodingContractResult.Success: if (contract.reward !== null) { - const reward = player.gainCodingContractReward(contract.reward, contract.getDifficulty()); + const reward = Player.gainCodingContractReward(contract.reward, contract.getDifficulty()); this.print(`Contract SUCCESS - ${reward}`); } serv.removeContract(contract); @@ -495,7 +495,7 @@ export class Terminal implements ITerminal { this.contractOpen = false; } - executeScanAnalyzeCommand(player: IPlayer, depth = 1, all = false): void { + executeScanAnalyzeCommand(depth = 1, all = false): void { // TODO Using array as stack for now, can make more efficient this.print("~~~~~~~~~~ Beginning scan-analyze ~~~~~~~~~~"); this.print(" "); @@ -510,7 +510,7 @@ export class Terminal implements ITerminal { const stack: BaseServer[] = []; const depthQueue: number[] = [0]; - const currServ = player.getCurrentServer(); + const currServ = Player.getCurrentServer(); stack.push(currServ); while (stack.length != 0) { const s = stack.pop(); @@ -537,7 +537,7 @@ export class Terminal implements ITerminal { continue; } // Don't print current server const titleDashes = Array((d - 1) * 4 + 1).join("-"); - if (player.hasProgram(Programs.AutoLink.name)) { + if (Player.hasProgram(Programs.AutoLink.name)) { this.append(new Link(titleDashes, s.hostname)); } else { this.print(titleDashes + s.hostname); @@ -562,23 +562,23 @@ export class Terminal implements ITerminal { } } - connectToServer(player: IPlayer, server: string): void { + connectToServer(server: string): void { const serv = GetServer(server); if (serv == null) { this.error("Invalid server. Connection failed."); return; } - player.getCurrentServer().isConnectedTo = false; - player.currentServer = serv.hostname; - player.getCurrentServer().isConnectedTo = true; + Player.getCurrentServer().isConnectedTo = false; + Player.currentServer = serv.hostname; + Player.getCurrentServer().isConnectedTo = true; this.print("Connected to " + serv.hostname); this.setcwd("/"); - if (player.getCurrentServer().hostname == "darkweb") { + if (Player.getCurrentServer().hostname == "darkweb") { checkIfConnectedToDarkweb(); // Posts a 'help' message if connecting to dark web } } - executeCommands(router: IRouter, player: IPlayer, commands: string): void { + executeCommands(commands: string): void { // Sanitize input commands = commands.trim(); commands = commands.replace(/\s\s+/g, " "); // Replace all extra whitespace in command with a single space @@ -589,13 +589,13 @@ export class Terminal implements ITerminal { if (this.commandHistory.length > 50) { this.commandHistory.splice(0, 1); } - player.terminalCommandHistory = this.commandHistory; + Player.terminalCommandHistory = this.commandHistory; } this.commandHistoryIndex = this.commandHistory.length; const allCommands = ParseCommands(commands); for (let i = 0; i < allCommands.length; i++) { - this.executeCommand(router, player, allCommands[i]); + this.executeCommand(allCommands[i]); } } @@ -610,7 +610,7 @@ export class Terminal implements ITerminal { this.clear(); } - executeCommand(router: IRouter, player: IPlayer, command: string): void { + executeCommand(command: string): void { if (this.action !== null) { this.error(`Cannot execute command (${command}) while an action is in progress`); return; @@ -624,7 +624,7 @@ export class Terminal implements ITerminal { if (commandArray.length == 0) { return; } - const s = player.getCurrentServer(); + const s = Player.getCurrentServer(); /****************** Interactive Tutorial Terminal Commands ******************/ if (ITutorial.isRunning) { const n00dlesServ = GetServer("n00dles"); @@ -785,11 +785,8 @@ export class Terminal implements ITerminal { const commands: { [key: string]: ( - terminal: ITerminal, - router: IRouter, - player: IPlayer, - server: BaseServer, args: (string | number | boolean)[], + server: BaseServer, ) => void; } = { "scan-analyze": scananalyze, @@ -841,7 +838,7 @@ export class Terminal implements ITerminal { return; } - f(this, router, player, s, commandArray.slice(1)); + f(commandArray.slice(1), s); } getProgressText(): string { diff --git a/src/Terminal/commands/alias.ts b/src/Terminal/commands/alias.ts index 1e908baf8..d5c7f8d37 100644 --- a/src/Terminal/commands/alias.ts +++ b/src/Terminal/commands/alias.ts @@ -1,33 +1,24 @@ -import { ITerminal } from "../ITerminal"; -import { IRouter } from "../../ui/Router"; -import { IPlayer } from "../../PersonObjects/IPlayer"; -import { BaseServer } from "../../Server/BaseServer"; +import { Terminal } from "../../Terminal"; import { parseAliasDeclaration, printAliases } from "../../Alias"; -export function alias( - terminal: ITerminal, - router: IRouter, - player: IPlayer, - server: BaseServer, - args: (string | number | boolean)[], -): void { +export function alias(args: (string | number | boolean)[]): void { if (args.length === 0) { printAliases(); return; } if (args.length === 1) { if (parseAliasDeclaration(args[0] + "")) { - terminal.print(`Set alias ${args[0]}`); + Terminal.print(`Set alias ${args[0]}`); return; } } if (args.length === 2) { if (args[0] === "-g") { if (parseAliasDeclaration(args[1] + "", true)) { - terminal.print(`Set global alias ${args[1]}`); + Terminal.print(`Set global alias ${args[1]}`); return; } } } - terminal.error('Incorrect usage of alias command. Usage: alias [-g] [aliasname="value"]'); + Terminal.error('Incorrect usage of alias command. Usage: alias [-g] [aliasname="value"]'); } diff --git a/src/Terminal/commands/analyze.ts b/src/Terminal/commands/analyze.ts index 2544d837f..674b1db76 100644 --- a/src/Terminal/commands/analyze.ts +++ b/src/Terminal/commands/analyze.ts @@ -1,18 +1,9 @@ -import { ITerminal } from "../ITerminal"; -import { IRouter } from "../../ui/Router"; -import { IPlayer } from "../../PersonObjects/IPlayer"; -import { BaseServer } from "../../Server/BaseServer"; +import { Terminal } from "../../Terminal"; -export function analyze( - terminal: ITerminal, - router: IRouter, - player: IPlayer, - server: BaseServer, - args: (string | number | boolean)[], -): void { +export function analyze(args: (string | number | boolean)[]): void { if (args.length !== 0) { - terminal.error("Incorrect usage of analyze command. Usage: analyze"); + Terminal.error("Incorrect usage of analyze command. Usage: analyze"); return; } - terminal.startAnalyze(player); + Terminal.startAnalyze(); } diff --git a/src/Terminal/commands/backdoor.ts b/src/Terminal/commands/backdoor.ts index 2f49745e9..9766ce073 100644 --- a/src/Terminal/commands/backdoor.ts +++ b/src/Terminal/commands/backdoor.ts @@ -1,41 +1,34 @@ -import { ITerminal } from "../ITerminal"; -import { IRouter } from "../../ui/Router"; -import { IPlayer } from "../../PersonObjects/IPlayer"; +import { Terminal } from "../../Terminal"; +import { Player } from "../../Player"; import { BaseServer } from "../../Server/BaseServer"; import { Server } from "../../Server/Server"; import { HacknetServer } from "../../Hacknet/HacknetServer"; -export function backdoor( - terminal: ITerminal, - router: IRouter, - player: IPlayer, - server: BaseServer, - args: (string | number | boolean)[], -): void { +export function backdoor(args: (string | number | boolean)[], server: BaseServer): void { if (args.length !== 0) { - terminal.error("Incorrect usage of backdoor command. Usage: backdoor"); + Terminal.error("Incorrect usage of backdoor command. Usage: backdoor"); return; } if (!(server instanceof Server)) { - terminal.error("Can only backdoor normal servers"); + Terminal.error("Can only backdoor normal servers"); } const normalServer = server as Server; if (normalServer.purchasedByPlayer) { - terminal.error( + Terminal.error( "Cannot use backdoor on your own machines! You are currently connected to your home PC or one of your purchased servers", ); } else if (!normalServer.hasAdminRights) { - terminal.error("You do not have admin rights for this machine! Cannot backdoor"); - } else if (normalServer.requiredHackingSkill > player.skills.hacking) { - terminal.error( + Terminal.error("You do not have admin rights for this machine! Cannot backdoor"); + } else if (normalServer.requiredHackingSkill > Player.skills.hacking) { + Terminal.error( "Your hacking skill is not high enough to use backdoor on this machine. Try analyzing the machine to determine the required hacking skill", ); } else if (normalServer instanceof HacknetServer) { - terminal.error("Cannot use backdoor on this type of Server"); + Terminal.error("Cannot use backdoor on this type of Server"); } else { - terminal.startBackdoor(player); + Terminal.startBackdoor(); } } diff --git a/src/Terminal/commands/buy.ts b/src/Terminal/commands/buy.ts index 88a6b685c..50a90d169 100644 --- a/src/Terminal/commands/buy.ts +++ b/src/Terminal/commands/buy.ts @@ -1,35 +1,23 @@ -import { ITerminal } from "../ITerminal"; -import { IRouter } from "../../ui/Router"; -import { IPlayer } from "../../PersonObjects/IPlayer"; -import { BaseServer } from "../../Server/BaseServer"; +import { Terminal } from "../../Terminal"; +import { Player } from "../../Player"; import { listAllDarkwebItems, buyAllDarkwebItems, buyDarkwebItem } from "../../DarkWeb/DarkWeb"; -export function buy( - terminal: ITerminal, - router: IRouter, - player: IPlayer, - server: BaseServer, - args: (string | number | boolean)[], -): void { - if (!player.hasTorRouter()) { - terminal.error( +export function buy(args: (string | number | boolean)[]): void { + if (!Player.hasTorRouter()) { + Terminal.error( "You need to be able to connect to the Dark Web to use the buy command. (Maybe there's a TOR router you can buy somewhere)", ); return; } if (args.length != 1) { - terminal.print("Incorrect number of arguments. Usage: "); - terminal.print("buy -l"); - terminal.print("buy -a"); - terminal.print("buy [item name]"); + Terminal.print("Incorrect number of arguments. Usage: "); + Terminal.print("buy -l"); + Terminal.print("buy -a"); + Terminal.print("buy [item name]"); return; } const arg = args[0] + ""; - if (arg == "-l" || arg == "-1" || arg == "--list") { - listAllDarkwebItems(); - } else if (arg == "-a" || arg == "--all") { - buyAllDarkwebItems(); - } else { - buyDarkwebItem(arg); - } + if (arg == "-l" || arg == "-1" || arg == "--list") listAllDarkwebItems(); + else if (arg == "-a" || arg == "--all") buyAllDarkwebItems(); + else buyDarkwebItem(arg); } diff --git a/src/Terminal/commands/cat.ts b/src/Terminal/commands/cat.ts index 5d9723738..0807e8a84 100644 --- a/src/Terminal/commands/cat.ts +++ b/src/Terminal/commands/cat.ts @@ -1,25 +1,17 @@ -import { ITerminal } from "../ITerminal"; -import { IRouter } from "../../ui/Router"; -import { IPlayer } from "../../PersonObjects/IPlayer"; +import { Terminal } from "../../Terminal"; import { BaseServer } from "../../Server/BaseServer"; import { MessageFilenames, showMessage } from "../../Message/MessageHelpers"; import { showLiterature } from "../../Literature/LiteratureHelpers"; import { dialogBoxCreate } from "../../ui/React/DialogBox"; import { checkEnum } from "../../utils/helpers/checkEnum"; -export function cat( - terminal: ITerminal, - router: IRouter, - player: IPlayer, - server: BaseServer, - args: (string | number | boolean)[], -): void { +export function cat(args: (string | number | boolean)[], server: BaseServer): void { if (args.length !== 1) { - terminal.error("Incorrect usage of cat command. Usage: cat [file]"); + Terminal.error("Incorrect usage of cat command. Usage: cat [file]"); return; } const relative_filename = args[0] + ""; - const filename = terminal.getFilepath(relative_filename); + const filename = Terminal.getFilepath(relative_filename); if ( !filename.endsWith(".msg") && !filename.endsWith(".lit") && @@ -27,7 +19,7 @@ export function cat( !filename.endsWith(".script") && !filename.endsWith(".js") ) { - terminal.error( + Terminal.error( "Only .msg, .txt, .lit, .script and .js files are viewable with cat (filename must end with .msg, .txt, .lit, .script or .js)", ); return; @@ -49,18 +41,18 @@ export function cat( } } } else if (filename.endsWith(".txt")) { - const txt = terminal.getTextFile(player, relative_filename); + const txt = Terminal.getTextFile(relative_filename); if (txt != null) { txt.show(); return; } } else if (filename.endsWith(".script") || filename.endsWith(".js")) { - const script = terminal.getScript(player, relative_filename); + const script = Terminal.getScript(relative_filename); if (script != null) { dialogBoxCreate(`${script.filename}

    ${script.code}`); return; } } - terminal.error(`No such file ${filename}`); + Terminal.error(`No such file ${filename}`); } diff --git a/src/Terminal/commands/cd.ts b/src/Terminal/commands/cd.ts index 174f557bd..e67ef32ed 100644 --- a/src/Terminal/commands/cd.ts +++ b/src/Terminal/commands/cd.ts @@ -1,20 +1,12 @@ -import { ITerminal } from "../ITerminal"; -import { IRouter } from "../../ui/Router"; -import { IPlayer } from "../../PersonObjects/IPlayer"; +import { Terminal } from "../../Terminal"; import { BaseServer } from "../../Server/BaseServer"; import { evaluateDirectoryPath, removeTrailingSlash } from "../DirectoryHelpers"; import { containsFiles } from "../DirectoryServerHelpers"; -export function cd( - terminal: ITerminal, - router: IRouter, - player: IPlayer, - server: BaseServer, - args: (string | number | boolean)[], -): void { +export function cd(args: (string | number | boolean)[], server: BaseServer): void { if (args.length > 1) { - terminal.error("Incorrect number of arguments. Usage: cd [dir]"); + Terminal.error("Incorrect number of arguments. Usage: cd [dir]"); } else { let dir = args.length === 1 ? args[0] + "" : "/"; @@ -25,23 +17,22 @@ export function cd( // Ignore trailing slashes dir = removeTrailingSlash(dir); - evaledDir = evaluateDirectoryPath(dir, terminal.cwd()); + evaledDir = evaluateDirectoryPath(dir, Terminal.cwd()); if (evaledDir === null || evaledDir === "") { - terminal.error("Invalid path. Failed to change directories"); + Terminal.error("Invalid path. Failed to change directories"); return; } - if (terminal.cwd().length > 1 && dir === "..") { - terminal.setcwd(evaledDir); + if (Terminal.cwd().length > 1 && dir === "..") { + Terminal.setcwd(evaledDir); return; } - const server = player.getCurrentServer(); if (!containsFiles(server, evaledDir)) { - terminal.error("Invalid path. Failed to change directories"); + Terminal.error("Invalid path. Failed to change directories"); return; } } - terminal.setcwd(evaledDir); + Terminal.setcwd(evaledDir); } } diff --git a/src/Terminal/commands/check.ts b/src/Terminal/commands/check.ts index 0bc198a2f..852874570 100644 --- a/src/Terminal/commands/check.ts +++ b/src/Terminal/commands/check.ts @@ -1,24 +1,16 @@ -import { ITerminal } from "../ITerminal"; -import { IRouter } from "../../ui/Router"; -import { IPlayer } from "../../PersonObjects/IPlayer"; +import { Terminal } from "../../Terminal"; import { BaseServer } from "../../Server/BaseServer"; import { findRunningScript } from "../../Script/ScriptHelpers"; import { isScriptFilename, validScriptExtensions } from "../../Script/isScriptFilename"; -export function check( - terminal: ITerminal, - router: IRouter, - player: IPlayer, - server: BaseServer, - args: (string | number | boolean)[], -): void { +export function check(args: (string | number | boolean)[], server: BaseServer): void { if (args.length < 1) { - terminal.error(`Incorrect number of arguments. Usage: check [script] [arg1] [arg2]...`); + Terminal.error(`Incorrect number of arguments. Usage: check [script] [arg1] [arg2]...`); } else { - const scriptName = terminal.getFilepath(args[0] + ""); + const scriptName = Terminal.getFilepath(args[0] + ""); // Can only tail script files if (!isScriptFilename(scriptName)) { - terminal.error( + Terminal.error( `'check' can only be called on scripts files (filename must end with ${validScriptExtensions.join(", ")})`, ); return; @@ -27,7 +19,7 @@ export function check( // Check that the script is running on this machine const runningScript = findRunningScript(scriptName, args.slice(1), server); if (runningScript == null) { - terminal.error(`No script named ${scriptName} is running on the server`); + Terminal.error(`No script named ${scriptName} is running on the server`); return; } runningScript.displayLog(); diff --git a/src/Terminal/commands/common/editor.ts b/src/Terminal/commands/common/editor.ts index f24e0b029..8fab8804c 100644 --- a/src/Terminal/commands/common/editor.ts +++ b/src/Terminal/commands/common/editor.ts @@ -1,7 +1,7 @@ -import { ITerminal } from "../../ITerminal"; +import { Terminal } from "../../../Terminal"; import { removeLeadingSlash, removeTrailingSlash } from "../../DirectoryHelpers"; -import { IRouter, ScriptEditorRouteOptions } from "../../../ui/Router"; -import { IPlayer } from "../../../PersonObjects/IPlayer"; +import { ScriptEditorRouteOptions } from "../../../ui/Router"; +import { Router } from "../../../ui/GameRoot"; import { BaseServer } from "../../../Server/BaseServer"; import { isScriptFilename } from "../../../Script/isScriptFilename"; import { CursorPositions } from "../../../ScriptEditor/CursorPositions"; @@ -9,11 +9,8 @@ import { Script } from "../../../Script/Script"; import { isEmpty } from "lodash"; interface EditorParameters { - terminal: ITerminal; - router: IRouter; - player: IPlayer; - server: BaseServer; args: (string | number | boolean)[]; + server: BaseServer; } function isNs2(filename: string): boolean { @@ -38,21 +35,17 @@ function containsSimpleGlob(filename: string): boolean { return filename.includes("*"); } -function detectSimpleScriptGlob( - args: EditorParameters["args"], - player: IPlayer, - terminal: ITerminal, -): ISimpleScriptGlob | null { +function detectSimpleScriptGlob({ args, server }: EditorParameters): ISimpleScriptGlob | null { if (args.length == 1 && containsSimpleGlob(`${args[0]}`)) { const filename = `${args[0]}`; - const scripts = player.getCurrentServer().scripts; - const parsedGlob = parseSimpleScriptGlob(filename, scripts, terminal); + const scripts = server.scripts; + const parsedGlob = parseSimpleScriptGlob(filename, scripts); return parsedGlob; } return null; } -function parseSimpleScriptGlob(globString: string, globDatabase: Script[], terminal: ITerminal): ISimpleScriptGlob { +function parseSimpleScriptGlob(globString: string, globDatabase: Script[]): ISimpleScriptGlob { const parsedGlob: ISimpleScriptGlob = { glob: globString, preGlob: "", @@ -76,7 +69,7 @@ function parseSimpleScriptGlob(globString: string, globDatabase: Script[], termi parsedGlob.preGlob = removeLeadingSlash(parsedGlob.preGlob); // Add CWD to preGlob path - const cwd = removeTrailingSlash(terminal.cwd()); + const cwd = removeTrailingSlash(Terminal.cwd()); parsedGlob.preGlob = `${cwd}/${parsedGlob.preGlob}`; // For every script on the current server, filter matched scripts per glob values & persist @@ -95,17 +88,17 @@ function parseSimpleScriptGlob(globString: string, globDatabase: Script[], termi export function commonEditor( command: string, - { terminal, router, player, args }: EditorParameters, + { args, server }: EditorParameters, scriptEditorRouteOptions?: ScriptEditorRouteOptions, ): void { if (args.length < 1) { - terminal.error(`Incorrect usage of ${command} command. Usage: ${command} [scriptname]`); + Terminal.error(`Incorrect usage of ${command} command. Usage: ${command} [scriptname]`); return; } let filesToLoadOrCreate = args; try { - const globSearch = detectSimpleScriptGlob(args, player, terminal); + const globSearch = detectSimpleScriptGlob({ args, server }); if (globSearch) { if (isEmpty(globSearch.globError) === false) throw new Error(globSearch.globError); filesToLoadOrCreate = globSearch.globMatches; @@ -115,8 +108,8 @@ export function commonEditor( const filename = `${arg}`; if (isScriptFilename(filename)) { - const filepath = terminal.getFilepath(filename); - const script = terminal.getScript(player, filename); + const filepath = Terminal.getFilepath(filename); + const script = Terminal.getScript(filename); const fileIsNs2 = isNs2(filename); const code = script !== null ? script.code : fileIsNs2 ? newNs2Template : ""; @@ -131,8 +124,8 @@ export function commonEditor( } if (filename.endsWith(".txt")) { - const filepath = terminal.getFilepath(filename); - const txt = terminal.getTextFile(player, filename); + const filepath = Terminal.getFilepath(filename); + const txt = Terminal.getTextFile(filename); return [filepath, txt === null ? "" : txt.text]; } @@ -145,8 +138,8 @@ export function commonEditor( throw new Error(`Could not find any valid files to open with ${command} using glob: \`${globSearch.glob}\``); } - router.toScriptEditor(Object.fromEntries(files), scriptEditorRouteOptions); + Router.toScriptEditor(Object.fromEntries(files), scriptEditorRouteOptions); } catch (e) { - terminal.error(`${e}`); + Terminal.error(`${e}`); } } diff --git a/src/Terminal/commands/connect.ts b/src/Terminal/commands/connect.ts index c36e5541f..a5583010f 100644 --- a/src/Terminal/commands/connect.ts +++ b/src/Terminal/commands/connect.ts @@ -1,21 +1,13 @@ -import { ITerminal } from "../ITerminal"; -import { IRouter } from "../../ui/Router"; -import { IPlayer } from "../../PersonObjects/IPlayer"; +import { Terminal } from "../../Terminal"; import { BaseServer } from "../../Server/BaseServer"; import { getServerOnNetwork } from "../../Server/ServerHelpers"; import { GetServer } from "../../Server/AllServers"; import { Server } from "../../Server/Server"; -export function connect( - terminal: ITerminal, - router: IRouter, - player: IPlayer, - server: BaseServer, - args: (string | number | boolean)[], -): void { - // Disconnect from current server in terminal and connect to new one +export function connect(args: (string | number | boolean)[], server: BaseServer): void { + // Disconnect from current server in Terminal and connect to new one if (args.length !== 1) { - terminal.error("Incorrect usage of connect command. Usage: connect [hostname]"); + Terminal.error("Incorrect usage of connect command. Usage: connect [hostname]"); return; } @@ -25,7 +17,7 @@ export function connect( const other = getServerOnNetwork(server, i); if (other === null) throw new Error(`Server on network should not be null`); if (other.hostname == hostname) { - terminal.connectToServer(player, hostname); + Terminal.connectToServer(hostname); return; } } @@ -33,13 +25,13 @@ export function connect( const other = GetServer(hostname); if (other !== null) { if (other instanceof Server && other.backdoorInstalled) { - terminal.connectToServer(player, hostname); + Terminal.connectToServer(hostname); return; } - terminal.error( + Terminal.error( `Cannot directly connect to ${hostname}. Make sure the server is backdoored or adjacent to your current Server`, ); } else { - terminal.error("Host not found"); + Terminal.error("Host not found"); } } diff --git a/src/Terminal/commands/cp.ts b/src/Terminal/commands/cp.ts index 021e9c60d..1038cd6f7 100644 --- a/src/Terminal/commands/cp.ts +++ b/src/Terminal/commands/cp.ts @@ -1,50 +1,45 @@ -import { ITerminal } from "../ITerminal"; -import { IRouter } from "../../ui/Router"; -import { IPlayer } from "../../PersonObjects/IPlayer"; +import { Terminal } from "../../Terminal"; import { BaseServer } from "../../Server/BaseServer"; import { isScriptFilename } from "../../Script/isScriptFilename"; import { getDestinationFilepath, areFilesEqual } from "../DirectoryHelpers"; export function cp( - terminal: ITerminal, - router: IRouter, - player: IPlayer, - server: BaseServer, args: (string | number | boolean)[], + server: BaseServer, ): void { try { if (args.length !== 2) { - terminal.error("Incorrect usage of cp command. Usage: cp [src] [dst]"); + Terminal.error("Incorrect usage of cp command. Usage: cp [src] [dst]"); return; } // Convert a relative path source file to the absolute path. - const src = terminal.getFilepath(args[0] + ""); + const src = Terminal.getFilepath(args[0] + ""); if (src === null) { - terminal.error("src cannot be a directory"); + Terminal.error("src cannot be a directory"); return; } // Get the destination based on the source file and the current directory - const t_dst = getDestinationFilepath(args[1] + "", src, terminal.cwd()); + const t_dst = getDestinationFilepath(args[1] + "", src, Terminal.cwd()); if (t_dst === null) { - terminal.error("error parsing dst file"); + Terminal.error("error parsing dst file"); return; } // Convert a relative path destination file to the absolute path. - const dst = terminal.getFilepath(t_dst); + const dst = Terminal.getFilepath(t_dst); if (areFilesEqual(src, dst)) { - terminal.error("src and dst cannot be the same"); + Terminal.error("src and dst cannot be the same"); return; } const srcExt = src.slice(src.lastIndexOf(".")); const dstExt = dst.slice(dst.lastIndexOf(".")); if (srcExt !== dstExt) { - terminal.error("src and dst must have the same extension."); + Terminal.error("src and dst must have the same extension."); return; } if (!isScriptFilename(src) && !src.endsWith(".txt")) { - terminal.error("cp only works for scripts and .txt files"); + Terminal.error("cp only works for scripts and .txt files"); return; } @@ -59,20 +54,20 @@ export function cp( } if (txtFile === null) { - return terminal.error("No such file exists!"); + return Terminal.error("No such file exists!"); } const tRes = server.writeToTextFile(dst, txtFile.text); if (!tRes.success) { - terminal.error("cp failed"); + Terminal.error("cp failed"); return; } if (tRes.overwritten) { - terminal.print(`WARNING: ${dst} already exists and will be overwriten`); - terminal.print(`${dst} overwritten`); + Terminal.print(`WARNING: ${dst} already exists and will be overwriten`); + Terminal.print(`${dst} overwritten`); return; } - terminal.print(`${dst} copied`); + Terminal.print(`${dst} copied`); return; } @@ -85,22 +80,22 @@ export function cp( } } if (sourceScript == null) { - terminal.error("cp failed. No such script exists"); + Terminal.error("cp failed. No such script exists"); return; } const sRes = server.writeToScriptFile(dst, sourceScript.code); if (!sRes.success) { - terminal.error(`cp failed`); + Terminal.error(`cp failed`); return; } if (sRes.overwritten) { - terminal.print(`WARNING: ${dst} already exists and will be overwritten`); - terminal.print(`${dst} overwritten`); + Terminal.print(`WARNING: ${dst} already exists and will be overwritten`); + Terminal.print(`${dst} overwritten`); return; } - terminal.print(`${dst} copied`); + Terminal.print(`${dst} copied`); } catch (e) { - terminal.error(e + ""); + Terminal.error(e + ""); } } diff --git a/src/Terminal/commands/download.ts b/src/Terminal/commands/download.ts index 7060ee4b7..6a0902639 100644 --- a/src/Terminal/commands/download.ts +++ b/src/Terminal/commands/download.ts @@ -1,6 +1,4 @@ -import { ITerminal } from "../ITerminal"; -import { IRouter } from "../../ui/Router"; -import { IPlayer } from "../../PersonObjects/IPlayer"; +import { Terminal } from "../../Terminal"; import { BaseServer } from "../../Server/BaseServer"; import { isScriptFilename } from "../../Script/isScriptFilename"; import FileSaver from "file-saver"; @@ -37,16 +35,10 @@ export function exportScripts(pattern: string, server: BaseServer): void { zip.generateAsync({ type: "blob" }).then((content: Blob) => FileSaver.saveAs(content, zipFn)); } -export function download( - terminal: ITerminal, - router: IRouter, - player: IPlayer, - server: BaseServer, - args: (string | number | boolean)[], -): void { +export function download(args: (string | number | boolean)[], server: BaseServer): void { try { if (args.length !== 1) { - terminal.error("Incorrect usage of download command. Usage: download [script/text file]"); + Terminal.error("Incorrect usage of download command. Usage: download [script/text file]"); return; } const fn = args[0] + ""; @@ -60,28 +52,28 @@ export function download( if (e !== null && typeof e == "object" && e.hasOwnProperty("message")) { msg = String((e as { message: unknown }).message); } - return terminal.error(msg); + return Terminal.error(msg); } } else if (isScriptFilename(fn)) { // Download a single script - const script = terminal.getScript(player, fn); + const script = Terminal.getScript(fn); if (script != null) { return script.download(); } } else if (fn.endsWith(".txt")) { // Download a single text file - const txt = terminal.getTextFile(player, fn); + const txt = Terminal.getTextFile(fn); if (txt != null) { return txt.download(); } } else { - terminal.error(`Cannot download this filetype`); + Terminal.error(`Cannot download this filetype`); return; } - terminal.error(`${fn} does not exist`); + Terminal.error(`${fn} does not exist`); return; } catch (e) { - terminal.error(e + ""); + Terminal.error(e + ""); return; } } diff --git a/src/Terminal/commands/expr.ts b/src/Terminal/commands/expr.ts index 5645431e3..fffd00d9a 100644 --- a/src/Terminal/commands/expr.ts +++ b/src/Terminal/commands/expr.ts @@ -1,17 +1,8 @@ -import { ITerminal } from "../ITerminal"; -import { IRouter } from "../../ui/Router"; -import { IPlayer } from "../../PersonObjects/IPlayer"; -import { BaseServer } from "../../Server/BaseServer"; +import { Terminal } from "../../Terminal"; -export function expr( - terminal: ITerminal, - router: IRouter, - player: IPlayer, - server: BaseServer, - args: (string | number | boolean)[], -): void { +export function expr(args: (string | number | boolean)[]): void { if (args.length === 0) { - terminal.error("Incorrect usage of expr command. Usage: expr [math expression]"); + Terminal.error("Incorrect usage of expr command. Usage: expr [math expression]"); return; } const expr = args.join(""); @@ -22,8 +13,8 @@ export function expr( try { result = eval(sanitizedExpr); } catch (e) { - terminal.error(`Could not evaluate expression: ${sanitizedExpr}`); + Terminal.error(`Could not evaluate expression: ${sanitizedExpr}`); return; } - terminal.print(result); + Terminal.print(result); } diff --git a/src/Terminal/commands/free.ts b/src/Terminal/commands/free.ts index d86917003..88cc43ac4 100644 --- a/src/Terminal/commands/free.ts +++ b/src/Terminal/commands/free.ts @@ -1,29 +1,19 @@ -import { ITerminal } from "../ITerminal"; -import { IRouter } from "../../ui/Router"; -import { IPlayer } from "../../PersonObjects/IPlayer"; +import { Terminal } from "../../Terminal"; import { BaseServer } from "../../Server/BaseServer"; import { numeralWrapper } from "../../ui/numeralFormat"; -export function free( - terminal: ITerminal, - router: IRouter, - player: IPlayer, - server: BaseServer, - args: (string | number | boolean)[], -): void { +export function free(args: (string | number | boolean)[], server: BaseServer): void { if (args.length !== 0) { - terminal.error("Incorrect usage of free command. Usage: free"); + Terminal.error("Incorrect usage of free command. Usage: free"); return; } - const ram = numeralWrapper.formatRAM(player.getCurrentServer().maxRam); - const used = numeralWrapper.formatRAM(player.getCurrentServer().ramUsed); - const avail = numeralWrapper.formatRAM(player.getCurrentServer().maxRam - player.getCurrentServer().ramUsed); + const ram = numeralWrapper.formatRAM(server.maxRam); + const used = numeralWrapper.formatRAM(server.ramUsed); + const avail = numeralWrapper.formatRAM(server.maxRam - server.ramUsed); const maxLength = Math.max(ram.length, Math.max(used.length, avail.length)); - const usedPercent = numeralWrapper.formatPercentage( - player.getCurrentServer().ramUsed / player.getCurrentServer().maxRam, - ); + const usedPercent = numeralWrapper.formatPercentage(server.ramUsed / server.maxRam); - terminal.print(`Total: ${" ".repeat(maxLength - ram.length)}${ram}`); - terminal.print(`Used: ${" ".repeat(maxLength - used.length)}${used} (${usedPercent})`); - terminal.print(`Available: ${" ".repeat(maxLength - avail.length)}${avail}`); + Terminal.print(`Total: ${" ".repeat(maxLength - ram.length)}${ram}`); + Terminal.print(`Used: ${" ".repeat(maxLength - used.length)}${used} (${usedPercent})`); + Terminal.print(`Available: ${" ".repeat(maxLength - avail.length)}${avail}`); } diff --git a/src/Terminal/commands/grow.ts b/src/Terminal/commands/grow.ts index 6169a3a99..a87cd1847 100644 --- a/src/Terminal/commands/grow.ts +++ b/src/Terminal/commands/grow.ts @@ -1,23 +1,19 @@ -import { ITerminal } from "../ITerminal"; -import { IRouter } from "../../ui/Router"; -import { IPlayer } from "../../PersonObjects/IPlayer"; +import { Terminal } from "../../Terminal"; +import { Player } from "../../Player"; import { BaseServer } from "../../Server/BaseServer"; import { Server } from "../../Server/Server"; export function grow( - terminal: ITerminal, - router: IRouter, - player: IPlayer, - server: BaseServer, args: (string | number | boolean)[], + server: BaseServer, ): void { if (args.length !== 0) { - terminal.error("Incorrect usage of grow command. Usage: grow"); + Terminal.error("Incorrect usage of grow command. Usage: grow"); return; } if (!(server instanceof Server)) { - terminal.error( + Terminal.error( "Cannot grow your own machines! You are currently connected to your home PC or one of your purchased servers", ); } @@ -25,20 +21,20 @@ export function grow( // Hack the current PC (usually for money) // You can't grow your home pc or servers you purchased if (normalServer.purchasedByPlayer) { - terminal.error( + Terminal.error( "Cannot grow your own machines! You are currently connected to your home PC or one of your purchased servers", ); return; } if (!normalServer.hasAdminRights) { - terminal.error("You do not have admin rights for this machine! Cannot grow"); + Terminal.error("You do not have admin rights for this machine! Cannot grow"); return; } - if (normalServer.requiredHackingSkill > player.skills.hacking) { - terminal.error( + if (normalServer.requiredHackingSkill > Player.skills.hacking) { + Terminal.error( "Your hacking skill is not high enough to attempt hacking this machine. Try analyzing the machine to determine the required hacking skill", ); return; } - terminal.startGrow(player); + Terminal.startGrow(); } diff --git a/src/Terminal/commands/hack.ts b/src/Terminal/commands/hack.ts index cc66bd26a..039ad6461 100644 --- a/src/Terminal/commands/hack.ts +++ b/src/Terminal/commands/hack.ts @@ -1,23 +1,19 @@ -import { ITerminal } from "../ITerminal"; -import { IRouter } from "../../ui/Router"; -import { IPlayer } from "../../PersonObjects/IPlayer"; +import { Terminal } from "../../Terminal"; +import { Player } from "../../Player"; import { BaseServer } from "../../Server/BaseServer"; import { Server } from "../../Server/Server"; export function hack( - terminal: ITerminal, - router: IRouter, - player: IPlayer, - server: BaseServer, args: (string | number | boolean)[], + server: BaseServer, ): void { if (args.length !== 0) { - terminal.error("Incorrect usage of hack command. Usage: hack"); + Terminal.error("Incorrect usage of hack command. Usage: hack"); return; } if (!(server instanceof Server)) { - terminal.error( + Terminal.error( "Cannot hack your own machines! You are currently connected to your home PC or one of your purchased servers", ); } @@ -25,20 +21,20 @@ export function hack( // Hack the current PC (usually for money) // You can't hack your home pc or servers you purchased if (normalServer.purchasedByPlayer) { - terminal.error( + Terminal.error( "Cannot hack your own machines! You are currently connected to your home PC or one of your purchased servers", ); return; } if (!normalServer.hasAdminRights) { - terminal.error("You do not have admin rights for this machine! Cannot hack"); + Terminal.error("You do not have admin rights for this machine! Cannot hack"); return; } - if (normalServer.requiredHackingSkill > player.skills.hacking) { - terminal.error( + if (normalServer.requiredHackingSkill > Player.skills.hacking) { + Terminal.error( "Your hacking skill is not high enough to attempt hacking this machine. Try analyzing the machine to determine the required hacking skill", ); return; } - terminal.startHack(player); + Terminal.startHack(); } diff --git a/src/Terminal/commands/help.ts b/src/Terminal/commands/help.ts index 23de8028f..6bdf2a0d5 100644 --- a/src/Terminal/commands/help.ts +++ b/src/Terminal/commands/help.ts @@ -1,29 +1,20 @@ -import { ITerminal } from "../ITerminal"; -import { IRouter } from "../../ui/Router"; -import { IPlayer } from "../../PersonObjects/IPlayer"; -import { BaseServer } from "../../Server/BaseServer"; +import { Terminal } from "../../Terminal"; import { TerminalHelpText, HelpTexts } from "../HelpText"; -export function help( - terminal: ITerminal, - router: IRouter, - player: IPlayer, - server: BaseServer, - args: (string | number | boolean)[], -): void { +export function help(args: (string | number | boolean)[]): void { if (args.length !== 0 && args.length !== 1) { - terminal.error("Incorrect usage of help command. Usage: help"); + Terminal.error("Incorrect usage of help command. Usage: help"); return; } if (args.length === 0) { - TerminalHelpText.forEach((line) => terminal.print(line)); + TerminalHelpText.forEach((line) => Terminal.print(line)); } else { const cmd = args[0] + ""; const txt = HelpTexts[cmd]; if (txt == null) { - terminal.error("No help topics match '" + cmd + "'"); + Terminal.error("No help topics match '" + cmd + "'"); return; } - txt.forEach((t) => terminal.print(t)); + txt.forEach((t) => Terminal.print(t)); } } diff --git a/src/Terminal/commands/history.ts b/src/Terminal/commands/history.ts index 32a51f162..57076e406 100644 --- a/src/Terminal/commands/history.ts +++ b/src/Terminal/commands/history.ts @@ -1,27 +1,19 @@ -import { ITerminal } from "../ITerminal"; -import { IRouter } from "../../ui/Router"; -import { IPlayer } from "../../PersonObjects/IPlayer"; -import { BaseServer } from "../../Server/BaseServer"; +import { Terminal } from "../../Terminal"; +import { Player } from "../../Player"; -export function history( - terminal: ITerminal, - router: IRouter, - player: IPlayer, - server: BaseServer, - args: (string | number | boolean)[], -): void { +export function history(args: (string | number | boolean)[]): void { if (args.length === 0) { - terminal.commandHistory.forEach((command, index) => { - terminal.print(`${index.toString().padStart(2)} ${command}`); + Terminal.commandHistory.forEach((command, index) => { + Terminal.print(`${index.toString().padStart(2)} ${command}`); }); return; } const arg = args[0] + ""; if (arg === "-c" || arg === "--clear") { - player.terminalCommandHistory = []; - terminal.commandHistory = []; - terminal.commandHistoryIndex = 1; + Player.terminalCommandHistory = []; + Terminal.commandHistory = []; + Terminal.commandHistoryIndex = 1; } else { - terminal.error("Incorrect usage of history command. usage: history [-c]"); + Terminal.error("Incorrect usage of history command. usage: history [-c]"); } } diff --git a/src/Terminal/commands/home.ts b/src/Terminal/commands/home.ts index b20fdebd0..d26f44ef0 100644 --- a/src/Terminal/commands/home.ts +++ b/src/Terminal/commands/home.ts @@ -1,22 +1,16 @@ -import { ITerminal } from "../ITerminal"; -import { IRouter } from "../../ui/Router"; -import { IPlayer } from "../../PersonObjects/IPlayer"; -import { BaseServer } from "../../Server/BaseServer"; +import { Terminal } from "../../Terminal"; +import { Player } from "../../Player"; export function home( - terminal: ITerminal, - router: IRouter, - player: IPlayer, - server: BaseServer, args: (string | number | boolean)[], ): void { if (args.length !== 0) { - terminal.error("Incorrect usage of home command. Usage: home"); + Terminal.error("Incorrect usage of home command. Usage: home"); return; } - player.getCurrentServer().isConnectedTo = false; - player.currentServer = player.getHomeComputer().hostname; - player.getCurrentServer().isConnectedTo = true; - terminal.print("Connected to home"); - terminal.setcwd("/"); + Player.getCurrentServer().isConnectedTo = false; + Player.currentServer = Player.getHomeComputer().hostname; + Player.getCurrentServer().isConnectedTo = true; + Terminal.print("Connected to home"); + Terminal.setcwd("/"); } diff --git a/src/Terminal/commands/hostname.ts b/src/Terminal/commands/hostname.ts index 7c061d93f..767763808 100644 --- a/src/Terminal/commands/hostname.ts +++ b/src/Terminal/commands/hostname.ts @@ -1,18 +1,10 @@ -import { ITerminal } from "../ITerminal"; -import { IRouter } from "../../ui/Router"; -import { IPlayer } from "../../PersonObjects/IPlayer"; +import { Terminal } from "../../Terminal"; import { BaseServer } from "../../Server/BaseServer"; -export function hostname( - terminal: ITerminal, - router: IRouter, - player: IPlayer, - server: BaseServer, - args: (string | number | boolean)[], -): void { +export function hostname(args: (string | number | boolean)[], server: BaseServer): void { if (args.length !== 0) { - terminal.error("Incorrect usage of hostname command. Usage: hostname"); + Terminal.error("Incorrect usage of hostname command. Usage: hostname"); return; } - terminal.print(player.getCurrentServer().hostname); + Terminal.print(server.hostname); } diff --git a/src/Terminal/commands/kill.ts b/src/Terminal/commands/kill.ts index 652043496..92f0f89f4 100644 --- a/src/Terminal/commands/kill.ts +++ b/src/Terminal/commands/kill.ts @@ -1,19 +1,11 @@ -import { ITerminal } from "../ITerminal"; -import { IRouter } from "../../ui/Router"; -import { IPlayer } from "../../PersonObjects/IPlayer"; +import { Terminal } from "../../Terminal"; import { BaseServer } from "../../Server/BaseServer"; import { killWorkerScript } from "../../Netscript/killWorkerScript"; -export function kill( - terminal: ITerminal, - router: IRouter, - player: IPlayer, - server: BaseServer, - args: (string | number | boolean)[], -): void { +export function kill(args: (string | number | boolean)[], server: BaseServer): void { try { if (args.length < 1) { - terminal.error("Incorrect usage of kill command. Usage: kill [scriptname] [arg1] [arg2]..."); + Terminal.error("Incorrect usage of kill command. Usage: kill [scriptname] [arg1] [arg2]..."); return; } if (typeof args[0] === "boolean") { @@ -25,23 +17,23 @@ export function kill( const pid = args[0]; const res = killWorkerScript(pid); if (res) { - terminal.print(`Killing script with PID ${pid}`); + Terminal.print(`Killing script with PID ${pid}`); } else { - terminal.error(`Failed to kill script with PID ${pid}. No such script is running`); + Terminal.error(`Failed to kill script with PID ${pid}. No such script is running`); } return; } - const scriptName = terminal.getFilepath(args[0]); + const scriptName = Terminal.getFilepath(args[0]); const runningScript = server.getRunningScript(scriptName, args.slice(1)); if (runningScript == null) { - terminal.error("No such script is running. Nothing to kill"); + Terminal.error("No such script is running. Nothing to kill"); return; } killWorkerScript({ runningScript: runningScript, hostname: server.hostname }); - terminal.print(`Killing ${scriptName}`); + Terminal.print(`Killing ${scriptName}`); } catch (e) { - terminal.error(e + ""); + Terminal.error(e + ""); } } diff --git a/src/Terminal/commands/killall.ts b/src/Terminal/commands/killall.ts index 6c670fe07..28ec0950d 100644 --- a/src/Terminal/commands/killall.ts +++ b/src/Terminal/commands/killall.ts @@ -1,14 +1,12 @@ -import { ITerminal } from "../ITerminal"; -import { IRouter } from "../../ui/Router"; -import { IPlayer } from "../../PersonObjects/IPlayer"; +import { Terminal } from "../../Terminal"; import { BaseServer } from "../../Server/BaseServer"; import { killWorkerScript } from "../../Netscript/killWorkerScript"; import { WorkerScriptStartStopEventEmitter } from "../../Netscript/WorkerScriptStartStopEventEmitter"; -export function killall(terminal: ITerminal, router: IRouter, player: IPlayer, server: BaseServer): void { +export function killall(_args: (string | number | boolean)[], server: BaseServer): void { for (let i = server.runningScripts.length - 1; i >= 0; --i) { killWorkerScript({ runningScript: server.runningScripts[i], hostname: server.hostname }); } WorkerScriptStartStopEventEmitter.emit(); - terminal.print("Killing all running scripts"); + Terminal.print("Killing all running scripts"); } diff --git a/src/Terminal/commands/ls.tsx b/src/Terminal/commands/ls.tsx index f66560e77..a05e43235 100644 --- a/src/Terminal/commands/ls.tsx +++ b/src/Terminal/commands/ls.tsx @@ -3,17 +3,15 @@ import createStyles from "@mui/styles/createStyles"; import makeStyles from "@mui/styles/makeStyles"; import { toString } from "lodash"; import React from "react"; -import { IPlayer } from "../../PersonObjects/IPlayer"; import { BaseServer } from "../../Server/BaseServer"; import { evaluateDirectoryPath, getFirstParentDirectory, isValidDirectoryPath } from "../DirectoryHelpers"; -import { IRouter } from "../../ui/Router"; -import { ITerminal } from "../ITerminal"; +import { Router } from "../../ui/GameRoot"; +import { Terminal } from "../../Terminal"; import libarg from "arg"; import { showLiterature } from "../../Literature/LiteratureHelpers"; import { MessageFilenames, showMessage } from "../../Message/MessageHelpers"; -import { ScriptArg } from "../../Netscript/ScriptArg"; -export function ls(terminal: ITerminal, router: IRouter, player: IPlayer, server: BaseServer, args: ScriptArg[]): void { +export function ls(args: (string | number | boolean)[], server: BaseServer): void { interface LSFlags { ["-l"]: boolean; ["--grep"]: string; @@ -37,7 +35,7 @@ export function ls(terminal: ITerminal, router: IRouter, player: IPlayer, server const numArgs = args.length; function incorrectUsage(): void { - terminal.error("Incorrect usage of ls command. Usage: ls [dir] [-l] [-g, --grep pattern]"); + Terminal.error("Incorrect usage of ls command. Usage: ls [dir] [-l] [-g, --grep pattern]"); } if (numArgs > 4) { @@ -45,14 +43,14 @@ export function ls(terminal: ITerminal, router: IRouter, player: IPlayer, server } // Directory path - let prefix = terminal.cwd(); + let prefix = Terminal.cwd(); if (!prefix.endsWith("/")) { prefix += "/"; } // If first arg doesn't contain a - it must be the file/folder const dir = args[0] && typeof args[0] == "string" && !args[0].startsWith("-") ? args[0] : ""; - const newPath = evaluateDirectoryPath(dir + "", terminal.cwd()); + const newPath = evaluateDirectoryPath(dir + "", Terminal.cwd()); prefix = newPath || ""; if (!prefix.endsWith("/")) { prefix += "/"; @@ -107,12 +105,11 @@ export function ls(terminal: ITerminal, router: IRouter, player: IPlayer, server } // Get all of the programs and scripts on the machine into one temporary array - const s = player.getCurrentServer(); - for (const program of s.programs) handleFn(program, allPrograms); - for (const script of s.scripts) handleFn(script.filename, allScripts); - for (const txt of s.textFiles) handleFn(txt.fn, allTextFiles); - for (const contract of s.contracts) handleFn(contract.fn, allContracts); - for (const msgOrLit of s.messages) handleFn(msgOrLit, allMessages); + for (const program of server.programs) handleFn(program, allPrograms); + for (const script of server.scripts) handleFn(script.filename, allScripts); + for (const txt of server.textFiles) handleFn(txt.fn, allTextFiles); + for (const contract of server.contracts) handleFn(contract.fn, allContracts); + for (const msgOrLit of server.messages) handleFn(msgOrLit, allMessages); // Sort the files/folders alphabetically then print each allPrograms.sort(); @@ -149,13 +146,13 @@ export function ls(terminal: ITerminal, router: IRouter, player: IPlayer, server rowSplitArray = rowSplitArray.filter((x) => !!x[0]); function onScriptLinkClick(filename: string): void { - if (player.getCurrentServer().hostname !== hostname) { - return terminal.error(`File is not on this server, connect to ${hostname} and try again`); + if (!server.isConnectedTo) { + return Terminal.error(`File is not on this server, connect to ${hostname} and try again`); } if (filename.startsWith("/")) filename = filename.slice(1); - const filepath = terminal.getFilepath(`${prefix}${filename}`); - const code = toString(terminal.getScript(player, filepath)?.code); - router.toScriptEditor({ [filepath]: code }); + const filepath = Terminal.getFilepath(`${prefix}${filename}`); + const code = toString(Terminal.getScript(filepath)?.code); + Router.toScriptEditor({ [filepath]: code }); } return ( @@ -193,11 +190,11 @@ export function ls(terminal: ITerminal, router: IRouter, player: IPlayer, server rowSplitArray = rowSplitArray.filter((x) => !!x[0]); function onMessageLinkClick(filename: string): void { - if (player.getCurrentServer().hostname !== hostname) { - return terminal.error(`File is not on this server, connect to ${hostname} and try again`); + if (!server.isConnectedTo) { + return Terminal.error(`File is not on this server, connect to ${hostname} and try again`); } if (filename.startsWith("/")) filename = filename.slice(1); - const filepath = terminal.getFilepath(`${prefix}${filename}`); + const filepath = Terminal.getFilepath(`${prefix}${filename}`); if (filepath.endsWith(".lit")) { showLiterature(filepath); @@ -254,16 +251,16 @@ export function ls(terminal: ITerminal, router: IRouter, player: IPlayer, server switch (group.type) { case FileType.Folder: - terminal.printRaw({row}); + Terminal.printRaw({row}); break; case FileType.Script: - terminal.printRaw(); + Terminal.printRaw(); break; case FileType.Message: - terminal.printRaw(); + Terminal.printRaw(); break; default: - terminal.print(row); + Terminal.print(row); } } } diff --git a/src/Terminal/commands/lscpu.ts b/src/Terminal/commands/lscpu.ts index 8eba1239e..096793249 100644 --- a/src/Terminal/commands/lscpu.ts +++ b/src/Terminal/commands/lscpu.ts @@ -1,7 +1,6 @@ -import { ITerminal } from "../ITerminal"; -import { IRouter } from "../../ui/Router"; -import { IPlayer } from "../../PersonObjects/IPlayer"; +import { Terminal } from "../../Terminal"; +import { BaseServer } from "../../Server/BaseServer"; -export function lscpu(terminal: ITerminal, router: IRouter, player: IPlayer): void { - terminal.print(player.getCurrentServer().cpuCores + " Core(s)"); +export function lscpu(_args: (string | number | boolean)[], server: BaseServer): void { + Terminal.print(server.cpuCores + " Core(s)"); } diff --git a/src/Terminal/commands/mem.ts b/src/Terminal/commands/mem.ts index b8acb448a..17593096d 100644 --- a/src/Terminal/commands/mem.ts +++ b/src/Terminal/commands/mem.ts @@ -1,20 +1,11 @@ -import { ITerminal } from "../ITerminal"; -import { IRouter } from "../../ui/Router"; -import { IPlayer } from "../../PersonObjects/IPlayer"; -import { BaseServer } from "../../Server/BaseServer"; +import { Terminal } from "../../Terminal"; import { numeralWrapper } from "../../ui/numeralFormat"; import { Settings } from "../../Settings/Settings"; -export function mem( - terminal: ITerminal, - router: IRouter, - player: IPlayer, - server: BaseServer, - args: (string | number | boolean)[], -): void { +export function mem(args: (string | number | boolean)[]): void { try { if (args.length !== 1 && args.length !== 3) { - terminal.error("Incorrect usage of mem command. usage: mem [scriptname] [-t] [number threads]"); + Terminal.error("Incorrect usage of mem command. usage: mem [scriptname] [-t] [number threads]"); return; } @@ -23,36 +14,36 @@ export function mem( if (args.length === 3 && args[1] === "-t") { numThreads = Math.round(parseInt(args[2] + "")); if (isNaN(numThreads) || numThreads < 1) { - terminal.error("Invalid number of threads specified. Number of threads must be greater than 1"); + Terminal.error("Invalid number of threads specified. Number of threads must be greater than 1"); return; } } - const script = terminal.getScript(player, scriptName); + const script = Terminal.getScript(scriptName); if (script == null) { - terminal.error("mem failed. No such script exists!"); + Terminal.error("mem failed. No such script exists!"); return; } const ramUsage = script.ramUsage * numThreads; - terminal.print( + Terminal.print( `This script requires ${numeralWrapper.formatRAM(ramUsage)} of RAM to run for ${numThreads} thread(s)`, ); const verboseEntries = script.ramUsageEntries?.sort((a, b) => b.cost - a.cost) ?? []; const padding = Settings.UseIEC60027_2 ? 9 : 8; for (const entry of verboseEntries) { - terminal.print( + Terminal.print( `${numeralWrapper.formatRAM(entry.cost * numThreads).padStart(padding)} | ${entry.name} (${entry.type})`, ); } if (ramUsage > 0 && verboseEntries.length === 0) { // Let's warn the user that he might need to save his script again to generate the detailed entries - terminal.warn("You might have to open & save this script to see the detailed RAM usage information."); + Terminal.warn("You might have to open & save this script to see the detailed RAM usage information."); } } catch (e) { - terminal.error(e + ""); + Terminal.error(e + ""); } } diff --git a/src/Terminal/commands/mv.ts b/src/Terminal/commands/mv.ts index f7f04ad94..44e07fcd9 100644 --- a/src/Terminal/commands/mv.ts +++ b/src/Terminal/commands/mv.ts @@ -1,21 +1,13 @@ -import { ITerminal } from "../ITerminal"; -import { IRouter } from "../../ui/Router"; -import { IPlayer } from "../../PersonObjects/IPlayer"; +import { Terminal } from "../../Terminal"; import { BaseServer } from "../../Server/BaseServer"; import { isScriptFilename } from "../../Script/isScriptFilename"; import { TextFile } from "../../TextFile"; import { Script } from "../../Script/Script"; import { getDestinationFilepath, areFilesEqual } from "../DirectoryHelpers"; -export function mv( - terminal: ITerminal, - router: IRouter, - player: IPlayer, - server: BaseServer, - args: (string | number | boolean)[], -): void { +export function mv(args: (string | number | boolean)[], server: BaseServer): void { if (args.length !== 2) { - terminal.error(`Incorrect number of arguments. Usage: mv [src] [dest]`); + Terminal.error(`Incorrect number of arguments. Usage: mv [src] [dest]`); return; } @@ -24,28 +16,28 @@ export function mv( const t_dest = args[1] + ""; if (!isScriptFilename(source) && !source.endsWith(".txt")) { - terminal.error(`'mv' can only be used on scripts and text files (.txt)`); + Terminal.error(`'mv' can only be used on scripts and text files (.txt)`); return; } - const srcFile = terminal.getFile(player, source); + const srcFile = Terminal.getFile(source); if (srcFile == null) { - terminal.error(`Source file ${source} does not exist`); + Terminal.error(`Source file ${source} does not exist`); return; } - const sourcePath = terminal.getFilepath(source); + const sourcePath = Terminal.getFilepath(source); // Get the destination based on the source file and the current directory - const dest = getDestinationFilepath(t_dest, source, terminal.cwd()); + const dest = getDestinationFilepath(t_dest, source, Terminal.cwd()); if (dest === null) { - terminal.error("error parsing dst file"); + Terminal.error("error parsing dst file"); return; } - const destFile = terminal.getFile(player, dest); - const destPath = terminal.getFilepath(dest); + const destFile = Terminal.getFile(dest); + const destPath = Terminal.getFilepath(dest); if (areFilesEqual(sourcePath, destPath)) { - terminal.error(`Source and destination files are the same file`); + Terminal.error(`Source and destination files are the same file`); return; } @@ -54,13 +46,13 @@ export function mv( if (isScriptFilename(source)) { const script = srcFile as Script; if (!isScriptFilename(destPath)) { - terminal.error(`Source and destination files must have the same type`); + Terminal.error(`Source and destination files must have the same type`); return; } // Command doesnt work if script is running if (server.isRunning(sourcePath)) { - terminal.error(`Cannot use 'mv' on a script that is running`); + Terminal.error(`Cannot use 'mv' on a script that is running`); return; } @@ -69,16 +61,16 @@ export function mv( // Command doesnt work if script is running if (server.isRunning(destPath)) { - terminal.error(`Cannot use 'mv' on a script that is running`); + Terminal.error(`Cannot use 'mv' on a script that is running`); return; } const status = server.removeFile(destPath); if (!status.res) { - terminal.error(`Something went wrong...please contact game dev (probably a bug)`); + Terminal.error(`Something went wrong...please contact game dev (probably a bug)`); return; } else { - terminal.print("Warning: The destination file was overwritten"); + Terminal.print("Warning: The destination file was overwritten"); } } @@ -86,7 +78,7 @@ export function mv( } else if (srcFile instanceof TextFile) { const textFile = srcFile; if (!dest.endsWith(".txt")) { - terminal.error(`Source and destination files must have the same type`); + Terminal.error(`Source and destination files must have the same type`); return; } @@ -94,16 +86,16 @@ export function mv( // Already exists, will be overwritten, so we'll delete it const status = server.removeFile(destPath); if (!status.res) { - terminal.error(`Something went wrong...please contact game dev (probably a bug)`); + Terminal.error(`Something went wrong...please contact game dev (probably a bug)`); return; } else { - terminal.print("Warning: The destination file was overwritten"); + Terminal.print("Warning: The destination file was overwritten"); } } textFile.fn = destPath; } } catch (e) { - terminal.error(e + ""); + Terminal.error(e + ""); } } diff --git a/src/Terminal/commands/nano.ts b/src/Terminal/commands/nano.ts index ed455923e..9e5718482 100644 --- a/src/Terminal/commands/nano.ts +++ b/src/Terminal/commands/nano.ts @@ -1,16 +1,7 @@ -import { ITerminal } from "../ITerminal"; -import { IRouter } from "../../ui/Router"; -import { IPlayer } from "../../PersonObjects/IPlayer"; import { BaseServer } from "../../Server/BaseServer"; import { commonEditor } from "./common/editor"; -export function nano( - terminal: ITerminal, - router: IRouter, - player: IPlayer, - server: BaseServer, - args: (string | number | boolean)[], -): void { - return commonEditor("nano", { terminal, router, player, server, args }); +export function nano(args: (string | number | boolean)[], server: BaseServer): void { + return commonEditor("nano", { args, server }); } diff --git a/src/Terminal/commands/ps.ts b/src/Terminal/commands/ps.ts index c213f7777..a4e226bb7 100644 --- a/src/Terminal/commands/ps.ts +++ b/src/Terminal/commands/ps.ts @@ -1,16 +1,8 @@ -import { ITerminal } from "../ITerminal"; -import { IRouter } from "../../ui/Router"; -import { IPlayer } from "../../PersonObjects/IPlayer"; +import { Terminal } from "../../Terminal"; import { BaseServer } from "../../Server/BaseServer"; import * as libarg from "arg"; -export function ps( - terminal: ITerminal, - router: IRouter, - player: IPlayer, - server: BaseServer, - args: (string | number | boolean)[], -): void { +export function ps(args: (string | number | boolean)[], server: BaseServer): void { let flags; try { flags = libarg( @@ -22,7 +14,7 @@ export function ps( ); } catch (e) { // catch passing only -g / --grep with no string to use as the search - terminal.error("Incorrect usage of ps command. Usage: ps [-g, --grep pattern]"); + Terminal.error("Incorrect usage of ps command. Usage: ps [-g, --grep pattern]"); return; } const pattern = flags["--grep"]; @@ -35,7 +27,7 @@ export function ps( for (let j = 0; j < rsObj.args.length; ++j) { res += " " + rsObj.args[j].toString(); } - terminal.print(res); + Terminal.print(res); } } if (args.length === 0) { @@ -45,7 +37,7 @@ export function ps( for (let j = 0; j < rsObj.args.length; ++j) { res += " " + rsObj.args[j].toString(); } - terminal.print(res); + Terminal.print(res); } } } diff --git a/src/Terminal/commands/rm.ts b/src/Terminal/commands/rm.ts index dc4b5e126..bc8b956ee 100644 --- a/src/Terminal/commands/rm.ts +++ b/src/Terminal/commands/rm.ts @@ -1,18 +1,10 @@ -import { ITerminal } from "../ITerminal"; -import { IRouter } from "../../ui/Router"; -import { IPlayer } from "../../PersonObjects/IPlayer"; +import { Terminal } from "../../Terminal"; import { BaseServer } from "../../Server/BaseServer"; import { IReturnStatus } from "../../types"; -export function rm( - terminal: ITerminal, - router: IRouter, - player: IPlayer, - server: BaseServer, - args: (string | number | boolean)[], -): void { +export function rm(args: (string | number | boolean)[], server: BaseServer): void { if (args.length !== 1) { - terminal.error("Incorrect number of arguments. Usage: rm [program/script]"); + Terminal.error("Incorrect number of arguments. Usage: rm [program/script]"); return; } @@ -23,7 +15,7 @@ export function rm( msg: "", }; try { - delTarget = terminal.getFilepath(args[0] + ""); + delTarget = Terminal.getFilepath(args[0] + ""); status = server.removeFile(delTarget); } catch (err) { status = { @@ -33,6 +25,6 @@ export function rm( } if (!status.res && status.msg) { - terminal.error(status.msg); + Terminal.error(status.msg); } } diff --git a/src/Terminal/commands/run.ts b/src/Terminal/commands/run.ts index 594170cf6..b551d1453 100644 --- a/src/Terminal/commands/run.ts +++ b/src/Terminal/commands/run.ts @@ -1,31 +1,26 @@ -import { ITerminal } from "../ITerminal"; -import { IRouter } from "../../ui/Router"; -import { IPlayer } from "../../PersonObjects/IPlayer"; +import { Terminal } from "../../Terminal"; import { BaseServer } from "../../Server/BaseServer"; import { isScriptFilename } from "../../Script/isScriptFilename"; import { runScript } from "./runScript"; import { runProgram } from "./runProgram"; export function run( - terminal: ITerminal, - router: IRouter, - player: IPlayer, - server: BaseServer, args: (string | number | boolean)[], + server: BaseServer, ): void { // Run a program or a script if (args.length < 1) { - terminal.error("Incorrect number of arguments. Usage: run [program/script] [-t] [num threads] [arg1] [arg2]..."); + Terminal.error("Incorrect number of arguments. Usage: run [program/script] [-t] [num threads] [arg1] [arg2]..."); } else { const executableName = args[0] + ""; // Check if its a script or just a program/executable if (isScriptFilename(executableName)) { - runScript(terminal, router, player, server, args); + runScript(args, server); } else if (executableName.endsWith(".cct")) { - terminal.runContract(player, executableName); + Terminal.runContract(executableName); } else { - runProgram(terminal, router, player, server, args); + runProgram(args, server); } } } diff --git a/src/Terminal/commands/runProgram.ts b/src/Terminal/commands/runProgram.ts index 5f48029e6..cd4ae1dd5 100644 --- a/src/Terminal/commands/runProgram.ts +++ b/src/Terminal/commands/runProgram.ts @@ -1,16 +1,9 @@ -import { ITerminal } from "../ITerminal"; -import { IRouter } from "../../ui/Router"; -import { IPlayer } from "../../PersonObjects/IPlayer"; +import { Terminal } from "../../Terminal"; +import { Player } from "../../Player"; import { BaseServer } from "../../Server/BaseServer"; import { Programs } from "../../Programs/Programs"; -export function runProgram( - terminal: ITerminal, - router: IRouter, - player: IPlayer, - server: BaseServer, - args: (string | number | boolean)[], -): void { +export function runProgram(args: (string | number | boolean)[], server: BaseServer): void { if (args.length < 1) { return; } @@ -19,11 +12,9 @@ export function runProgram( // display an error message const programName = args[0] + ""; - if (!player.hasProgram(programName)) { - terminal.error( - `No such (exe, script, js, ns, or cct) file! (Only programs that exist on your home computer or scripts on ${ - player.getCurrentServer().hostname - } can be run)`, + if (!Player.hasProgram(programName)) { + Terminal.error( + `No such (exe, script, js, ns, or cct) file! (Only programs that exist on your home computer or scripts on ${server.hostname} can be run)`, ); return; } @@ -35,15 +26,12 @@ export function runProgram( for (const program of Object.values(Programs)) { if (program.name.toLocaleLowerCase() === programName.toLocaleLowerCase()) { program.run( - router, - terminal, - player, - server, args.slice(1).map((arg) => arg + ""), + server, ); return; } } - terminal.error("Invalid executable. Cannot be run"); + Terminal.error("Invalid executable. Cannot be run"); } diff --git a/src/Terminal/commands/runScript.ts b/src/Terminal/commands/runScript.ts index baa18e589..90e8b206c 100644 --- a/src/Terminal/commands/runScript.ts +++ b/src/Terminal/commands/runScript.ts @@ -1,6 +1,4 @@ -import { ITerminal } from "../ITerminal"; -import { IRouter } from "../../ui/Router"; -import { IPlayer } from "../../PersonObjects/IPlayer"; +import { Terminal } from "../../Terminal"; import { BaseServer } from "../../Server/BaseServer"; import { LogBoxEvents } from "../../ui/React/LogBoxManager"; import { startWorkerScript } from "../../NetscriptWorker"; @@ -10,20 +8,17 @@ import * as libarg from "arg"; import { numeralWrapper } from "../../ui/numeralFormat"; export function runScript( - terminal: ITerminal, - router: IRouter, - player: IPlayer, - server: BaseServer, commandArgs: (string | number | boolean)[], + server: BaseServer, ): void { if (commandArgs.length < 1) { - terminal.error( + Terminal.error( `Bug encountered with Terminal.runScript(). Command array has a length of less than 1: ${commandArgs}`, ); return; } - const scriptName = terminal.getFilepath(commandArgs[0] + ""); + const scriptName = Terminal.getFilepath(commandArgs[0] + ""); const runArgs = { "--tail": Boolean, "-t": Number }; const flags = libarg(runArgs, { @@ -33,7 +28,7 @@ export function runScript( const threadFlag = Math.round(parseFloat(flags["-t"])); const tailFlag = flags["--tail"] === true; if (flags["-t"] !== undefined && (threadFlag < 0 || isNaN(threadFlag))) { - terminal.error("Invalid number of threads specified. Number of threads must be greater than 0"); + Terminal.error("Invalid number of threads specified. Number of threads must be greater than 0"); return; } const numThreads = !isNaN(threadFlag) && threadFlag > 0 ? threadFlag : 1; @@ -41,7 +36,7 @@ export function runScript( // Check if this script is already running if (findRunningScript(scriptName, args, server) != null) { - terminal.error( + Terminal.error( "This script is already running with the same args. Cannot run multiple instances with the same args", ); return; @@ -54,17 +49,17 @@ export function runScript( } // Check for admin rights and that there is enough RAM availble to run const script = server.scripts[i]; - script.server = player.getCurrentServer().hostname; + script.server = server.hostname; const ramUsage = script.ramUsage * numThreads; const ramAvailable = server.maxRam - server.ramUsed; if (!server.hasAdminRights) { - terminal.error("Need root access to run script"); + Terminal.error("Need root access to run script"); return; } if (ramUsage > ramAvailable + 0.001) { - terminal.error( + Terminal.error( "This machine does not have enough RAM to run this script" + (numThreads === 1 ? "" : ` with ${numThreads} threads`) + `. Script requires ${numeralWrapper.formatRAM(ramUsage)} of RAM`, @@ -78,11 +73,11 @@ export function runScript( const success = startWorkerScript(runningScript, server); if (!success) { - terminal.error(`Failed to start script`); + Terminal.error(`Failed to start script`); return; } - terminal.print( + Terminal.print( `Running script with ${numThreads} thread(s), pid ${runningScript.pid} and args: ${JSON.stringify(args)}.`, ); if (tailFlag) { @@ -91,5 +86,5 @@ export function runScript( return; } - terminal.error("No such script"); + Terminal.error("No such script"); } diff --git a/src/Terminal/commands/scan.ts b/src/Terminal/commands/scan.ts index da5c262a4..f6c61093a 100644 --- a/src/Terminal/commands/scan.ts +++ b/src/Terminal/commands/scan.ts @@ -1,23 +1,14 @@ -import { ITerminal } from "../ITerminal"; -import { IRouter } from "../../ui/Router"; -import { IPlayer } from "../../PersonObjects/IPlayer"; +import { Terminal } from "../../Terminal"; import { BaseServer } from "../../Server/BaseServer"; import { getServerOnNetwork } from "../../Server/ServerHelpers"; -export function scan( - terminal: ITerminal, - router: IRouter, - player: IPlayer, - server: BaseServer, - args: (string | number | boolean)[], -): void { +export function scan(args: (string | number | boolean)[], currServ: BaseServer): void { if (args.length !== 0) { - terminal.error("Incorrect usage of scan command. Usage: scan"); + Terminal.error("Incorrect usage of scan command. Usage: scan"); return; } // Displays available network connections using TCP - const currServ = player.getCurrentServer(); const servers = currServ.serversOnNetwork.map((_, i) => { const server = getServerOnNetwork(currServ, i); if (server === null) throw new Error("Server should not be null"); @@ -41,6 +32,6 @@ export function scan( entry += server.ip; entry += " ".repeat(maxIP - server.ip.length + 1); entry += server.hasRoot; - terminal.print(entry); + Terminal.print(entry); } } diff --git a/src/Terminal/commands/scananalyze.ts b/src/Terminal/commands/scananalyze.ts index f30c6dc9f..d9811909b 100644 --- a/src/Terminal/commands/scananalyze.ts +++ b/src/Terminal/commands/scananalyze.ts @@ -1,22 +1,14 @@ -import { ITerminal } from "../ITerminal"; -import { IRouter } from "../../ui/Router"; -import { IPlayer } from "../../PersonObjects/IPlayer"; -import { BaseServer } from "../../Server/BaseServer"; +import { Terminal } from "../../Terminal"; +import { Player } from "../../Player"; import { Programs } from "../../Programs/Programs"; -export function scananalyze( - terminal: ITerminal, - router: IRouter, - player: IPlayer, - server: BaseServer, - args: (string | number | boolean)[], -): void { +export function scananalyze(args: (string | number | boolean)[]): void { if (args.length === 0) { - terminal.executeScanAnalyzeCommand(player, 1); + Terminal.executeScanAnalyzeCommand(); } else { // # of args must be 2 or 3 if (args.length > 2) { - terminal.error("Incorrect usage of scan-analyze command. usage: scan-analyze [depth]"); + Terminal.error("Incorrect usage of scan-analyze command. usage: scan-analyze [depth]"); return; } let all = false; @@ -27,19 +19,19 @@ export function scananalyze( const depth = parseInt(args[0] + ""); if (isNaN(depth) || depth < 0) { - terminal.error("Incorrect usage of scan-analyze command. depth argument must be positive numeric"); + Terminal.error("Incorrect usage of scan-analyze command. depth argument must be positive numeric"); return; } - if (depth > 3 && !player.hasProgram(Programs.DeepscanV1.name) && !player.hasProgram(Programs.DeepscanV2.name)) { - terminal.error("You cannot scan-analyze with that high of a depth. Maximum depth is 3"); + if (depth > 3 && !Player.hasProgram(Programs.DeepscanV1.name) && !Player.hasProgram(Programs.DeepscanV2.name)) { + Terminal.error("You cannot scan-analyze with that high of a depth. Maximum depth is 3"); return; - } else if (depth > 5 && !player.hasProgram(Programs.DeepscanV2.name)) { - terminal.error("You cannot scan-analyze with that high of a depth. Maximum depth is 5"); + } else if (depth > 5 && !Player.hasProgram(Programs.DeepscanV2.name)) { + Terminal.error("You cannot scan-analyze with that high of a depth. Maximum depth is 5"); return; } else if (depth > 10) { - terminal.error("You cannot scan-analyze with that high of a depth. Maximum depth is 10"); + Terminal.error("You cannot scan-analyze with that high of a depth. Maximum depth is 10"); return; } - terminal.executeScanAnalyzeCommand(player, depth, all); + Terminal.executeScanAnalyzeCommand(depth, all); } } diff --git a/src/Terminal/commands/scp.ts b/src/Terminal/commands/scp.ts index d5def4d68..bef747545 100644 --- a/src/Terminal/commands/scp.ts +++ b/src/Terminal/commands/scp.ts @@ -1,111 +1,73 @@ -import { ITerminal } from "../ITerminal"; -import { IRouter } from "../../ui/Router"; -import { IPlayer } from "../../PersonObjects/IPlayer"; +import { Terminal } from "../../Terminal"; import { BaseServer } from "../../Server/BaseServer"; import { GetServer } from "../../Server/AllServers"; import { isScriptFilename } from "../../Script/isScriptFilename"; -export function scp( - terminal: ITerminal, - router: IRouter, - player: IPlayer, - server: BaseServer, - args: (string | number | boolean)[], -): void { +export function scp(args: (string | number | boolean)[], server: BaseServer): void { try { if (args.length !== 2) { - terminal.error("Incorrect usage of scp command. Usage: scp [file] [destination hostname]"); + Terminal.error("Incorrect usage of scp command. Usage: scp [file] [destination hostname]"); return; } - const scriptname = terminal.getFilepath(args[0] + ""); + const scriptname = Terminal.getFilepath(args[0] + ""); if (!scriptname.endsWith(".lit") && !isScriptFilename(scriptname) && !scriptname.endsWith(".txt")) { - terminal.error("scp only works for scripts, text files (.txt), and literature files (.lit)"); + Terminal.error("scp only works for scripts, text files (.txt), and literature files (.lit)"); return; } const destServer = GetServer(args[1] + ""); if (destServer == null) { - terminal.error(`Invalid destination. ${args[1]} not found`); + Terminal.error(`Invalid destination. ${args[1]} not found`); return; } // Scp for lit files if (scriptname.endsWith(".lit")) { - let found = false; - for (let i = 0; i < server.messages.length; ++i) { - if (server.messages[i] == scriptname) { - found = true; - break; - } - } + if (!server.messages.includes(scriptname)) return Terminal.error("No such file exists!"); - if (!found) { - return terminal.error("No such file exists!"); - } - - for (let i = 0; i < destServer.messages.length; ++i) { - if (destServer.messages[i] === scriptname) { - terminal.print(scriptname + " copied over to " + destServer.hostname); - return; // Already exists - } - } - destServer.messages.push(scriptname); - return terminal.print(scriptname + " copied over to " + destServer.hostname); + const onDestServer = destServer.messages.includes(scriptname); + if (!onDestServer) destServer.messages.push(scriptname); + return Terminal.print(`${scriptname} ${onDestServer ? "was already on" : "copied to"} ${destServer.hostname}`); } // Scp for txt files if (scriptname.endsWith(".txt")) { - let txtFile = null; - for (let i = 0; i < server.textFiles.length; ++i) { - if (server.textFiles[i].fn === scriptname) { - txtFile = server.textFiles[i]; - break; - } - } - - if (txtFile === null) { - return terminal.error("No such file exists!"); - } + const txtFile = server.textFiles.find((txtFile) => txtFile.fn === scriptname); + if (!txtFile) return Terminal.error("No such file exists!"); const tRes = destServer.writeToTextFile(txtFile.fn, txtFile.text); if (!tRes.success) { - terminal.error("scp failed"); + Terminal.error("scp failed"); return; } if (tRes.overwritten) { - terminal.print(`WARNING: ${scriptname} already exists on ${destServer.hostname} and will be overwriten`); - terminal.print(`${scriptname} overwritten on ${destServer.hostname}`); + Terminal.print(`WARNING: ${scriptname} already exists on ${destServer.hostname} and will be overwriten`); + Terminal.print(`${scriptname} overwritten on ${destServer.hostname}`); return; } - terminal.print(`${scriptname} copied over to ${destServer.hostname}`); + Terminal.print(`${scriptname} copied over to ${destServer.hostname}`); return; } // Get the current script - let sourceScript = null; - for (let i = 0; i < server.scripts.length; ++i) { - if (scriptname == server.scripts[i].filename) { - sourceScript = server.scripts[i]; - break; - } - } - if (sourceScript == null) { - terminal.error("scp failed. No such script exists"); + const sourceScript = server.scripts.find((script) => script.filename === scriptname); + if (!sourceScript) { + Terminal.error("scp failed. No such script exists"); return; } const sRes = destServer.writeToScriptFile(scriptname, sourceScript.code); if (!sRes.success) { - terminal.error(`scp failed`); + Terminal.error(`scp failed`); return; } if (sRes.overwritten) { - terminal.print(`WARNING: ${scriptname} already exists on ${destServer.hostname} and will be overwritten`); - terminal.print(`${scriptname} overwritten on ${destServer.hostname}`); + Terminal.print(`WARNING: ${scriptname} already exists on ${destServer.hostname} and will be overwritten`); + Terminal.print(`${scriptname} overwritten on ${destServer.hostname}`); return; } - terminal.print(`${scriptname} copied over to ${destServer.hostname}`); + Terminal.print(`${scriptname} copied over to ${destServer.hostname}`); } catch (e) { - terminal.error(e + ""); + Terminal.error(e + ""); } } diff --git a/src/Terminal/commands/sudov.ts b/src/Terminal/commands/sudov.ts index d5cfc3394..f80bec452 100644 --- a/src/Terminal/commands/sudov.ts +++ b/src/Terminal/commands/sudov.ts @@ -1,23 +1,18 @@ -import { ITerminal } from "../ITerminal"; -import { IRouter } from "../../ui/Router"; -import { IPlayer } from "../../PersonObjects/IPlayer"; +import { Terminal } from "../../Terminal"; import { BaseServer } from "../../Server/BaseServer"; export function sudov( - terminal: ITerminal, - router: IRouter, - player: IPlayer, - server: BaseServer, args: (string | number | boolean)[], + server: BaseServer, ): void { if (args.length !== 0) { - terminal.error("Incorrect number of arguments. Usage: sudov"); + Terminal.error("Incorrect number of arguments. Usage: sudov"); return; } if (server.hasAdminRights) { - terminal.print("You have ROOT access to this machine"); + Terminal.print("You have ROOT access to this machine"); } else { - terminal.print("You do NOT have root access to this machine"); + Terminal.print("You do NOT have root access to this machine"); } } diff --git a/src/Terminal/commands/tail.ts b/src/Terminal/commands/tail.ts index d1101e76a..834b433ce 100644 --- a/src/Terminal/commands/tail.ts +++ b/src/Terminal/commands/tail.ts @@ -1,26 +1,18 @@ -import { ITerminal } from "../ITerminal"; -import { IRouter } from "../../ui/Router"; -import { IPlayer } from "../../PersonObjects/IPlayer"; +import { Terminal } from "../../Terminal"; import { BaseServer } from "../../Server/BaseServer"; import { findRunningScriptByPid } from "../../Script/ScriptHelpers"; import { isScriptFilename, validScriptExtensions } from "../../Script/isScriptFilename"; import { compareArrays } from "../../utils/helpers/compareArrays"; import { LogBoxEvents } from "../../ui/React/LogBoxManager"; -export function tail( - terminal: ITerminal, - router: IRouter, - player: IPlayer, - server: BaseServer, - commandArray: (string | number | boolean)[], -): void { +export function tail(commandArray: (string | number | boolean)[], server: BaseServer): void { try { if (commandArray.length < 1) { - terminal.error("Incorrect number of arguments. Usage: tail [script] [arg1] [arg2]..."); + Terminal.error("Incorrect number of arguments. Usage: tail [script] [arg1] [arg2]..."); } else if (typeof commandArray[0] === "string") { - const scriptName = terminal.getFilepath(commandArray[0]); + const scriptName = Terminal.getFilepath(commandArray[0]); if (!isScriptFilename(scriptName)) { - terminal.error(`tail can only be called on ${validScriptExtensions.join(", ")} files, or by PID`); + Terminal.error(`tail can only be called on ${validScriptExtensions.join(", ")} files, or by PID`); return; } @@ -59,23 +51,23 @@ export function tail( // otherwise lists all possible conflicting choices. if (candidates.length > 1) { - terminal.error("Found several potential candidates:"); - for (const candidate of candidates) terminal.error(`${candidate.filename} ${candidate.args.join(" ")}`); - terminal.error("Script arguments need to be specified."); + Terminal.error("Found several potential candidates:"); + for (const candidate of candidates) Terminal.error(`${candidate.filename} ${candidate.args.join(" ")}`); + Terminal.error("Script arguments need to be specified."); return; } // if there's no candidate then we just don't know. - terminal.error(`No script named ${scriptName} is running on the server`); + Terminal.error(`No script named ${scriptName} is running on the server`); } else if (typeof commandArray[0] === "number") { const runningScript = findRunningScriptByPid(commandArray[0], server); if (runningScript == null) { - terminal.error(`No script with PID ${commandArray[0]} is running on the server`); + Terminal.error(`No script with PID ${commandArray[0]} is running on the server`); return; } LogBoxEvents.emit(runningScript); } } catch (e) { - terminal.error(e + ""); + Terminal.error(e + ""); } } diff --git a/src/Terminal/commands/top.ts b/src/Terminal/commands/top.ts index 283951f44..a57de4779 100644 --- a/src/Terminal/commands/top.ts +++ b/src/Terminal/commands/top.ts @@ -1,19 +1,14 @@ -import { ITerminal } from "../ITerminal"; -import { IRouter } from "../../ui/Router"; -import { IPlayer } from "../../PersonObjects/IPlayer"; +import { Terminal } from "../../Terminal"; import { BaseServer } from "../../Server/BaseServer"; import { getRamUsageFromRunningScript } from "../../Script/RunningScriptHelpers"; import { numeralWrapper } from "../../ui/numeralFormat"; export function top( - terminal: ITerminal, - router: IRouter, - player: IPlayer, - server: BaseServer, args: (string | number | boolean)[], + server: BaseServer, ): void { if (args.length !== 0) { - terminal.error("Incorrect usage of top command. Usage: top"); + Terminal.error("Incorrect usage of top command. Usage: top"); return; } @@ -33,7 +28,7 @@ export function top( const headers = `${scriptTxt}${spacesAfterScriptTxt}${pidTxt}${spacesAfterPidTxt}${threadsTxt}${spacesAfterThreadsTxt}${ramTxt}`; - terminal.print(headers); + Terminal.print(headers); const currRunningScripts = server.runningScripts; // Iterate through scripts on current server @@ -58,6 +53,6 @@ export function top( const entry = [script.filename, spacesScript, script.pid, spacesPid, script.threads, spacesThread, ramUsage].join( "", ); - terminal.print(entry); + Terminal.print(entry); } } diff --git a/src/Terminal/commands/unalias.ts b/src/Terminal/commands/unalias.ts index 48dc3e8d6..d2ebd5ada 100644 --- a/src/Terminal/commands/unalias.ts +++ b/src/Terminal/commands/unalias.ts @@ -1,22 +1,15 @@ -import { ITerminal } from "../ITerminal"; -import { IRouter } from "../../ui/Router"; -import { IPlayer } from "../../PersonObjects/IPlayer"; -import { BaseServer } from "../../Server/BaseServer"; +import { Terminal } from "../../Terminal"; import { removeAlias } from "../../Alias"; export function unalias( - terminal: ITerminal, - router: IRouter, - player: IPlayer, - server: BaseServer, args: (string | number | boolean)[], ): void { if (args.length !== 1) { - terminal.error("Incorrect usage of unalias name. Usage: unalias [alias]"); + Terminal.error("Incorrect usage of unalias name. Usage: unalias [alias]"); return; } else if (removeAlias(args[0] + "")) { - terminal.print(`Removed alias ${args[0]}`); + Terminal.print(`Removed alias ${args[0]}`); } else { - terminal.error(`No such alias exists: ${args[0]}`); + Terminal.error(`No such alias exists: ${args[0]}`); } } diff --git a/src/Terminal/commands/vim.ts b/src/Terminal/commands/vim.ts index 58cffba31..9ae834fb0 100644 --- a/src/Terminal/commands/vim.ts +++ b/src/Terminal/commands/vim.ts @@ -1,16 +1,7 @@ -import { ITerminal } from "../ITerminal"; -import { IRouter } from "../../ui/Router"; -import { IPlayer } from "../../PersonObjects/IPlayer"; import { BaseServer } from "../../Server/BaseServer"; import { commonEditor } from "./common/editor"; -export function vim( - terminal: ITerminal, - router: IRouter, - player: IPlayer, - server: BaseServer, - args: (string | number | boolean)[], -): void { - return commonEditor("vim", { terminal, router, player, server, args }, { vim: true }); +export function vim(args: (string | number | boolean)[], server: BaseServer): void { + return commonEditor("vim", { args, server }, { vim: true }); } diff --git a/src/Terminal/commands/weaken.ts b/src/Terminal/commands/weaken.ts index 9586db7c0..0d2d56715 100644 --- a/src/Terminal/commands/weaken.ts +++ b/src/Terminal/commands/weaken.ts @@ -1,23 +1,16 @@ -import { ITerminal } from "../ITerminal"; -import { IRouter } from "../../ui/Router"; -import { IPlayer } from "../../PersonObjects/IPlayer"; +import { Terminal } from "../../Terminal"; +import { Player } from "../../Player"; import { BaseServer } from "../../Server/BaseServer"; import { Server } from "../../Server/Server"; -export function weaken( - terminal: ITerminal, - router: IRouter, - player: IPlayer, - server: BaseServer, - args: (string | number | boolean)[], -): void { +export function weaken(args: (string | number | boolean)[], server: BaseServer): void { if (args.length !== 0) { - terminal.error("Incorrect usage of weaken command. Usage: weaken"); + Terminal.error("Incorrect usage of weaken command. Usage: weaken"); return; } if (!(server instanceof Server)) { - terminal.error( + Terminal.error( "Cannot weaken your own machines! You are currently connected to your home PC or one of your purchased servers", ); } @@ -25,20 +18,20 @@ export function weaken( // Hack the current PC (usually for money) // You can't weaken your home pc or servers you purchased if (normalServer.purchasedByPlayer) { - terminal.error( + Terminal.error( "Cannot weaken your own machines! You are currently connected to your home PC or one of your purchased servers", ); return; } if (!normalServer.hasAdminRights) { - terminal.error("You do not have admin rights for this machine! Cannot weaken"); + Terminal.error("You do not have admin rights for this machine! Cannot weaken"); return; } - if (normalServer.requiredHackingSkill > player.skills.hacking) { - terminal.error( + if (normalServer.requiredHackingSkill > Player.skills.hacking) { + Terminal.error( "Your hacking skill is not high enough to attempt hacking this machine. Try analyzing the machine to determine the required hacking skill", ); return; } - terminal.startWeaken(player); + Terminal.startWeaken(); } diff --git a/src/Terminal/commands/wget.ts b/src/Terminal/commands/wget.ts index 77e3444bc..afdcb0fdd 100644 --- a/src/Terminal/commands/wget.ts +++ b/src/Terminal/commands/wget.ts @@ -1,27 +1,22 @@ import $ from "jquery"; -import { ITerminal } from "../ITerminal"; -import { IRouter } from "../../ui/Router"; -import { IPlayer } from "../../PersonObjects/IPlayer"; +import { Terminal } from "../../Terminal"; import { BaseServer } from "../../Server/BaseServer"; import { isScriptFilename } from "../../Script/isScriptFilename"; export function wget( - terminal: ITerminal, - router: IRouter, - player: IPlayer, - server: BaseServer, args: (string | number | boolean)[], + server: BaseServer, ): void { if (args.length !== 2) { - terminal.error("Incorrect usage of wget command. Usage: wget [url] [target file]"); + Terminal.error("Incorrect usage of wget command. Usage: wget [url] [target file]"); return; } const url = args[0] + ""; - const target = terminal.getFilepath(args[1] + ""); + const target = Terminal.getFilepath(args[1] + ""); if (!isScriptFilename(target) && !target.endsWith(".txt")) { - return terminal.error(`wget failed: Invalid target file. Target file must be script or text file`); + return Terminal.error(`wget failed: Invalid target file. Target file must be script or text file`); } $.get( url, @@ -33,15 +28,15 @@ export function wget( res = server.writeToTextFile(target, String(data)); } if (!res.success) { - return terminal.error("wget failed"); + return Terminal.error("wget failed"); } if (res.overwritten) { - return terminal.print(`wget successfully retrieved content and overwrote ${target}`); + return Terminal.print(`wget successfully retrieved content and overwrote ${target}`); } - return terminal.print(`wget successfully retrieved content to new file ${target}`); + return Terminal.print(`wget successfully retrieved content to new file ${target}`); }, "text", ).fail(function (e) { - return terminal.error("wget failed: " + JSON.stringify(e)); + return Terminal.error("wget failed: " + JSON.stringify(e)); }); } diff --git a/src/Terminal/ui/TerminalInput.tsx b/src/Terminal/ui/TerminalInput.tsx index 57f2cc38f..c4bc1b85d 100644 --- a/src/Terminal/ui/TerminalInput.tsx +++ b/src/Terminal/ui/TerminalInput.tsx @@ -8,9 +8,9 @@ import Popper from "@mui/material/Popper"; import TextField from "@mui/material/TextField"; import { KEY, KEYCODE } from "../../utils/helpers/keyCodes"; -import { ITerminal } from "../ITerminal"; -import { IRouter } from "../../ui/Router"; -import { IPlayer } from "../../PersonObjects/IPlayer"; +import { Terminal } from "../../Terminal"; +import { Router } from "../../ui/GameRoot"; +import { Player } from "../../Player"; import { determineAllPossibilitiesForTabCompletion } from "../determineAllPossibilitiesForTabCompletion"; import { tabCompletion } from "../tabCompletion"; import { Settings } from "../../Settings/Settings"; @@ -37,15 +37,10 @@ const useStyles = makeStyles((theme: Theme) => }), ); -interface IProps { - terminal: ITerminal; - router: IRouter; - player: IPlayer; -} // Save command in case we de-load this screen. let command = ""; -export function TerminalInput({ terminal, router, player }: IProps): React.ReactElement { +export function TerminalInput(): React.ReactElement { const terminalInput = useRef(null); const [value, setValue] = useState(command); @@ -54,9 +49,9 @@ export function TerminalInput({ terminal, router, player }: IProps): React.React const classes = useStyles(); // If we have no data in the current terminal history, let's initialize it from the player save - if (terminal.commandHistory.length === 0 && player.terminalCommandHistory.length > 0) { - terminal.commandHistory = player.terminalCommandHistory; - terminal.commandHistoryIndex = terminal.commandHistory.length; + if (Terminal.commandHistory.length === 0 && Player.terminalCommandHistory.length > 0) { + Terminal.commandHistory = Player.terminalCommandHistory; + Terminal.commandHistoryIndex = Terminal.commandHistory.length; } // Need to run after state updates, for example if we need to move cursor @@ -183,9 +178,9 @@ export function TerminalInput({ terminal, router, player }: IProps): React.React // Catch all key inputs and redirect them to the terminal. useEffect(() => { function keyDown(this: Document, event: KeyboardEvent): void { - if (terminal.contractOpen) return; - if (terminal.action !== null && event.key === KEY.C && event.ctrlKey) { - terminal.finishAction(router, player, true); + if (Terminal.contractOpen) return; + if (Terminal.action !== null && event.key === KEY.C && event.ctrlKey) { + Terminal.finishAction(true); return; } const ref = terminalInput.current; @@ -204,8 +199,8 @@ export function TerminalInput({ terminal, router, player }: IProps): React.React // Run command. if (event.key === KEY.ENTER && value !== "") { event.preventDefault(); - terminal.print(`[${player.getCurrentServer().hostname} ~${terminal.cwd()}]> ${value}`); - terminal.executeCommands(router, player, value); + Terminal.print(`[${Player.getCurrentServer().hostname} ~${Terminal.cwd()}]> ${value}`); + Terminal.executeCommands(value); saveValue(""); return; } @@ -228,7 +223,7 @@ export function TerminalInput({ terminal, router, player }: IProps): React.React if (index < -1) { index = 0; } - const allPos = await determineAllPossibilitiesForTabCompletion(player, copy, index, terminal.cwd()); + const allPos = await determineAllPossibilitiesForTabCompletion(Player, copy, index, Terminal.cwd()); if (allPos.length == 0) { return; } @@ -264,7 +259,7 @@ export function TerminalInput({ terminal, router, player }: IProps): React.React // Clear screen. if (event.key === KEY.L && event.ctrlKey) { event.preventDefault(); - terminal.clear(); + Terminal.clear(); } // Select previous command. @@ -272,20 +267,20 @@ export function TerminalInput({ terminal, router, player }: IProps): React.React if (Settings.EnableBashHotkeys) { event.preventDefault(); } - const i = terminal.commandHistoryIndex; - const len = terminal.commandHistory.length; + const i = Terminal.commandHistoryIndex; + const len = Terminal.commandHistory.length; if (len == 0) { return; } if (i < 0 || i > len) { - terminal.commandHistoryIndex = len; + Terminal.commandHistoryIndex = len; } if (i != 0) { - --terminal.commandHistoryIndex; + --Terminal.commandHistoryIndex; } - const prevCommand = terminal.commandHistory[terminal.commandHistoryIndex]; + const prevCommand = Terminal.commandHistory[Terminal.commandHistoryIndex]; saveValue(prevCommand); if (ref) { setTimeout(function () { @@ -299,23 +294,23 @@ export function TerminalInput({ terminal, router, player }: IProps): React.React if (Settings.EnableBashHotkeys) { event.preventDefault(); } - const i = terminal.commandHistoryIndex; - const len = terminal.commandHistory.length; + const i = Terminal.commandHistoryIndex; + const len = Terminal.commandHistory.length; if (len == 0) { return; } if (i < 0 || i > len) { - terminal.commandHistoryIndex = len; + Terminal.commandHistoryIndex = len; } // Latest command, put nothing if (i == len || i == len - 1) { - terminal.commandHistoryIndex = len; + Terminal.commandHistoryIndex = len; saveValue(""); } else { - ++terminal.commandHistoryIndex; - const prevCommand = terminal.commandHistory[terminal.commandHistoryIndex]; + ++Terminal.commandHistoryIndex; + const prevCommand = Terminal.commandHistory[Terminal.commandHistoryIndex]; saveValue(prevCommand); } } @@ -324,7 +319,7 @@ export function TerminalInput({ terminal, router, player }: IProps): React.React if (Settings.EnableBashHotkeys) { if (event.code === KEYCODE.C && event.ctrlKey && ref && ref.selectionStart === ref.selectionEnd) { event.preventDefault(); - terminal.print(`[${player.getCurrentServer().hostname} ~${terminal.cwd()}]> ${value}`); + Terminal.print(`[${Player.getCurrentServer().hostname} ~${Terminal.cwd()}]> ${value}`); modifyInput("clearall"); } @@ -389,9 +384,9 @@ export function TerminalInput({ terminal, router, player }: IProps): React.React <> - [{player.getCurrentServer().hostname} ~{terminal.cwd()}]>  + + [{Player.getCurrentServer().hostname} ~{Terminal.cwd()}]>  ), spellCheck: false, diff --git a/src/Terminal/ui/TerminalRoot.tsx b/src/Terminal/ui/TerminalRoot.tsx index ef1e99662..6eab48a5a 100644 --- a/src/Terminal/ui/TerminalRoot.tsx +++ b/src/Terminal/ui/TerminalRoot.tsx @@ -7,9 +7,8 @@ import { Theme } from "@mui/material/styles"; import makeStyles from "@mui/styles/makeStyles"; import createStyles from "@mui/styles/createStyles"; import Box from "@mui/material/Box"; -import { ITerminal, Output, Link, RawOutput } from "../ITerminal"; -import { IRouter } from "../../ui/Router"; -import { IPlayer } from "../../PersonObjects/IPlayer"; +import { Output, Link, RawOutput } from "../ITerminal"; +import { Terminal } from "../../Terminal"; import { TerminalInput } from "./TerminalInput"; import { TerminalEvents, TerminalClearEvents } from "../TerminalEvents"; import { BitFlumeModal } from "../../BitNode/ui/BitFlumeModal"; @@ -18,14 +17,10 @@ import { CodingContractModal } from "../../ui/React/CodingContractModal"; import _ from "lodash"; import { ANSIITypography } from "../../ui/React/ANSIITypography"; -interface IActionTimerProps { - terminal: ITerminal; -} - -function ActionTimer({ terminal }: IActionTimerProps): React.ReactElement { +function ActionTimer(): React.ReactElement { return ( - {terminal.getProgressText()} + {Terminal.getProgressText()} ); } @@ -47,13 +42,7 @@ const useStyles = makeStyles((theme: Theme) => }), ); -interface IProps { - terminal: ITerminal; - router: IRouter; - player: IPlayer; -} - -export function TerminalRoot({ terminal, router, player }: IProps): React.ReactElement { +export function TerminalRoot(): React.ReactElement { const scrollHook = useRef(null); const setRerender = useState(0)[1]; const [key, setKey] = useState(0); @@ -108,7 +97,7 @@ export function TerminalRoot({ terminal, router, player }: IProps): React.ReactE <> - {terminal.outputHistory.map((item, i) => ( + {Terminal.outputHistory.map((item, i) => ( {item instanceof Output && } {item instanceof RawOutput && ( @@ -123,7 +112,7 @@ export function TerminalRoot({ terminal, router, player }: IProps): React.ReactE classes={{ root: classes.preformatted }} color={"secondary"} paragraph={false} - onClick={() => terminal.connectToServer(player, item.hostname)} + onClick={() => Terminal.connectToServer(item.hostname)} > {item.hostname} @@ -134,16 +123,16 @@ export function TerminalRoot({ terminal, router, player }: IProps): React.ReactE ))} - {terminal.action !== null && ( + {Terminal.action !== null && ( - {" "} + {" "} )}
    - + diff --git a/src/Themes/ui/ThemeBrowser.tsx b/src/Themes/ui/ThemeBrowser.tsx index e39b28a52..e8cee63c7 100644 --- a/src/Themes/ui/ThemeBrowser.tsx +++ b/src/Themes/ui/ThemeBrowser.tsx @@ -5,7 +5,6 @@ import { ThemeEvents } from "./Theme"; import { Settings } from "../../Settings/Settings"; import { getPredefinedThemes, IPredefinedTheme } from "../Themes"; import { Box, ButtonGroup, Button } from "@mui/material"; -import { IRouter } from "../../ui/Router"; import { ThemeEditorButton } from "./ThemeEditorButton"; import { StyleEditorButton } from "./StyleEditorButton"; import { ThemeEntry } from "./ThemeEntry"; @@ -13,14 +12,10 @@ import { ThemeCollaborate } from "./ThemeCollaborate"; import { Modal } from "../../ui/React/Modal"; import { SnackbarEvents, ToastVariant } from "../../ui/React/Snackbar"; -interface IProps { - router: IRouter; -} - // Everything dies when the theme gets reloaded, so we'll keep the current scroll to not jump around. let previousScrollY = 0; -export function ThemeBrowser({ router }: IProps): React.ReactElement { +export function ThemeBrowser(): React.ReactElement { const [modalOpen, setModalOpen] = useState(false); const [modalImageSrc, setModalImageSrc] = useState(); const predefinedThemes = getPredefinedThemes(); @@ -80,7 +75,7 @@ export function ThemeBrowser({ router }: IProps): React.ReactElement { - + {themes} diff --git a/src/Themes/ui/ThemeEditorButton.tsx b/src/Themes/ui/ThemeEditorButton.tsx index e2509802f..7e03de676 100644 --- a/src/Themes/ui/ThemeEditorButton.tsx +++ b/src/Themes/ui/ThemeEditorButton.tsx @@ -2,14 +2,9 @@ import React, { useState } from "react"; import Button from "@mui/material/Button"; import Tooltip from "@mui/material/Tooltip"; import { ThemeEditorModal } from "./ThemeEditorModal"; -import { IRouter } from "../../ui/Router"; import ColorizeIcon from "@mui/icons-material/Colorize"; -interface IProps { - router: IRouter; -} - -export function ThemeEditorButton({ router }: IProps): React.ReactElement { +export function ThemeEditorButton(): React.ReactElement { const [themeEditorOpen, setThemeEditorOpen] = useState(false); return ( <> @@ -18,7 +13,7 @@ export function ThemeEditorButton({ router }: IProps): React.ReactElement { Theme Editor - setThemeEditorOpen(false)} router={router} /> + setThemeEditorOpen(false)} /> ); } diff --git a/src/Themes/ui/ThemeEditorModal.tsx b/src/Themes/ui/ThemeEditorModal.tsx index 11d5b57ff..f8fd3d823 100644 --- a/src/Themes/ui/ThemeEditorModal.tsx +++ b/src/Themes/ui/ThemeEditorModal.tsx @@ -15,13 +15,12 @@ import { ThemeEvents } from "./Theme"; import { Settings, defaultSettings } from "../../Settings/Settings"; import { defaultTheme } from "../Themes"; import { UserInterfaceTheme } from "../../ScriptEditor/NetscriptDefinitions"; -import { IRouter } from "../../ui/Router"; +import { Router } from "../../ui/GameRoot"; import { ThemeCollaborate } from "./ThemeCollaborate"; interface IProps { open: boolean; onClose: () => void; - router: IRouter; } interface IColorEditorProps { @@ -381,7 +380,7 @@ export function ThemeEditorModal(props: IProps): React.ReactElement { - diff --git a/src/Work/ClassWork.tsx b/src/Work/ClassWork.tsx index 1a5d7dc63..3690978d6 100644 --- a/src/Work/ClassWork.tsx +++ b/src/Work/ClassWork.tsx @@ -6,7 +6,7 @@ import { numeralWrapper } from "../ui/numeralFormat"; import { dialogBoxCreate } from "../ui/React/DialogBox"; import { Money } from "../ui/React/Money"; import { convertTimeMsToTimeElapsedString } from "../utils/StringHelperFunctions"; -import { IPlayer } from "../PersonObjects/IPlayer"; +import { Player } from "../Player"; import { calculateClassEarnings as calculateClassEarningsRate } from "./formulas/Class"; import { Work, WorkType } from "./Work"; import { applyWorkStats, newWorkStats, sumWorkStats, WorkStats } from "./WorkStats"; @@ -146,14 +146,14 @@ export class ClassWork extends Work { return Classes[this.classType]; } - calculateRates(player: IPlayer): WorkStats { - return calculateClassEarningsRate(player, player, this.classType, this.location); + calculateRates(): WorkStats { + return calculateClassEarningsRate(Player, this.classType, this.location); } - process(player: IPlayer, cycles: number): boolean { + process(cycles: number): boolean { this.cyclesWorked += cycles; - const rate = this.calculateRates(player); - const earnings = applyWorkStats(player, player, rate, cycles, "class"); + const rate = this.calculateRates(); + const earnings = applyWorkStats(Player, rate, cycles, "class"); this.earnings = sumWorkStats(this.earnings, earnings); return false; } diff --git a/src/Work/CompanyWork.tsx b/src/Work/CompanyWork.tsx index f601904eb..85110951d 100644 --- a/src/Work/CompanyWork.tsx +++ b/src/Work/CompanyWork.tsx @@ -1,6 +1,6 @@ import React from "react"; import { Reviver, Generic_toJSON, Generic_fromJSON, IReviverValue } from "../utils/JSONReviver"; -import { IPlayer } from "src/PersonObjects/IPlayer"; +import { Player } from "../Player"; import { Work, WorkType } from "./Work"; import { influenceStockThroughCompanyWork } from "../StockMarket/PlayerInfluencing"; import { LocationName } from "../Locations/data/LocationNames"; @@ -33,19 +33,19 @@ export class CompanyWork extends Work { return c; } - getGainRates(player: IPlayer): WorkStats { + getGainRates(): WorkStats { let focusBonus = 1; - if (!player.hasAugmentation(AugmentationNames.NeuroreceptorManager, true)) { - focusBonus = player.focus ? 1 : CONSTANTS.BaseFocusBonus; + if (!Player.hasAugmentation(AugmentationNames.NeuroreceptorManager, true)) { + focusBonus = Player.focus ? 1 : CONSTANTS.BaseFocusBonus; } - return scaleWorkStats(calculateCompanyWorkStats(player, player, this.getCompany()), focusBonus); + return scaleWorkStats(calculateCompanyWorkStats(Player, this.getCompany()), focusBonus); } - process(player: IPlayer, cycles: number): boolean { + process(cycles: number): boolean { this.cyclesWorked += cycles; const company = this.getCompany(); - const gains = this.getGainRates(player); - applyWorkStats(player, player, gains, cycles, "work"); + const gains = this.getGainRates(); + applyWorkStats(Player, gains, cycles, "work"); company.playerReputation += gains.reputation * cycles; influenceStockThroughCompanyWork(company, gains.reputation, cycles); return false; diff --git a/src/Work/CreateProgramWork.ts b/src/Work/CreateProgramWork.ts index be5cf30f3..1a8e97070 100644 --- a/src/Work/CreateProgramWork.ts +++ b/src/Work/CreateProgramWork.ts @@ -2,7 +2,7 @@ import { dialogBoxCreate } from "../ui/React/DialogBox"; import { Reviver, Generic_toJSON, Generic_fromJSON, IReviverValue } from "../utils/JSONReviver"; import { AugmentationNames } from "../Augmentation/data/AugmentationNames"; import { CONSTANTS } from "../Constants"; -import { IPlayer } from "../PersonObjects/IPlayer"; +import { Player } from "../Player"; import { Programs } from "../Programs/Programs"; import { Work, WorkType } from "./Work"; import { Program } from "../Programs/Program"; @@ -13,7 +13,6 @@ export const isCreateProgramWork = (w: Work | null): w is CreateProgramWork => interface CreateProgramWorkParams { programName: string; singularity: boolean; - player: IPlayer; } export class CreateProgramWork extends Work { @@ -26,10 +25,9 @@ export class CreateProgramWork extends Work { this.unitCompleted = 0; this.programName = params?.programName ?? ""; - if (params?.player) { - const player = params.player; - for (let i = 0; i < player.getHomeComputer().programs.length; ++i) { - const programFile = player.getHomeComputer().programs[i]; + if (params) { + for (let i = 0; i < Player.getHomeComputer().programs.length; ++i) { + const programFile = Player.getHomeComputer().programs[i]; if (programFile.startsWith(this.programName) && programFile.endsWith("%-INC")) { const res = programFile.split("-"); if (res.length != 3) { @@ -40,7 +38,7 @@ export class CreateProgramWork extends Work { break; } this.unitCompleted = (percComplete / 100) * this.unitNeeded(); - player.getHomeComputer().programs.splice(i, 1); + Player.getHomeComputer().programs.splice(i, 1); } } } @@ -56,14 +54,14 @@ export class CreateProgramWork extends Work { return p; } - process(player: IPlayer, cycles: number): boolean { + process(cycles: number): boolean { let focusBonus = 1; - if (!player.hasAugmentation(AugmentationNames.NeuroreceptorManager, true)) { - focusBonus = player.focus ? 1 : CONSTANTS.BaseFocusBonus; + if (!Player.hasAugmentation(AugmentationNames.NeuroreceptorManager, true)) { + focusBonus = Player.focus ? 1 : CONSTANTS.BaseFocusBonus; } //Higher hacking skill will allow you to create programs faster const reqLvl = this.getProgram().create?.level ?? 0; - let skillMult = (player.skills.hacking / reqLvl) * player.getIntelligenceBonus(3); //This should always be greater than 1; + let skillMult = (Player.skills.hacking / reqLvl) * Player.getIntelligenceBonus(3); //This should always be greater than 1; skillMult = 1 + (skillMult - 1) / 5; //The divider constant can be adjusted as necessary skillMult *= focusBonus; //Skill multiplier directly applied to "time worked" @@ -75,11 +73,11 @@ export class CreateProgramWork extends Work { } return false; } - finish(player: IPlayer, cancelled: boolean): void { + finish(cancelled: boolean): void { const programName = this.programName; if (!cancelled) { //Complete case - player.gainIntelligenceExp( + Player.gainIntelligenceExp( (CONSTANTS.IntelligenceProgramBaseExpGain * this.cyclesWorked * CONSTANTS._idleSpeed) / 1000, ); if (!this.singularity) { @@ -90,14 +88,14 @@ export class CreateProgramWork extends Work { dialogBoxCreate(lines.join("
    ")); } - if (!player.getHomeComputer().programs.includes(programName)) { - player.getHomeComputer().programs.push(programName); + if (!Player.getHomeComputer().programs.includes(programName)) { + Player.getHomeComputer().programs.push(programName); } - } else if (!player.getHomeComputer().programs.includes(programName)) { + } else if (!Player.getHomeComputer().programs.includes(programName)) { //Incomplete case const perc = ((100 * this.unitCompleted) / this.unitNeeded()).toFixed(2); const incompleteName = programName + "-" + perc + "%-INC"; - player.getHomeComputer().programs.push(incompleteName); + Player.getHomeComputer().programs.push(incompleteName); } } diff --git a/src/Work/CrimeWork.ts b/src/Work/CrimeWork.ts index d7876047d..2ea4a0cb2 100644 --- a/src/Work/CrimeWork.ts +++ b/src/Work/CrimeWork.ts @@ -3,7 +3,7 @@ import { Crime } from "../Crime/Crime"; import { CONSTANTS } from "../Constants"; import { determineCrimeSuccess } from "../Crime/CrimeHelpers"; import { Crimes } from "../Crime/Crimes"; -import { IPlayer } from "../PersonObjects/IPlayer"; +import { Player } from "../Player"; import { dialogBoxCreate } from "../ui/React/DialogBox"; import { CrimeType } from "../utils/WorkType"; import { Work, WorkType } from "./Work"; @@ -78,12 +78,12 @@ export class CrimeWork extends Work { return crime; } - process(player: IPlayer, cycles = 1): boolean { + process(cycles = 1): boolean { this.cyclesWorked += cycles; const time = Object.values(Crimes).find((c) => c.type === this.crimeType)?.time ?? 0; this.unitCompleted += CONSTANTS._idleSpeed * cycles; while (this.unitCompleted >= time) { - this.commit(player); + this.commit(); this.unitCompleted -= time; } return false; @@ -93,7 +93,7 @@ export class CrimeWork extends Work { return calculateCrimeWorkStats(this.getCrime()); } - commit(player: IPlayer): void { + commit(): void { const crime = this.getCrime(); if (crime == null) { dialogBoxCreate( @@ -101,27 +101,27 @@ export class CrimeWork extends Work { ); return; } - const focusPenalty = player.focusPenalty(); + const focusPenalty = Player.focusPenalty(); // exp times 2 because were trying to maintain the same numbers as before the conversion // Technically the definition of Crimes should have the success numbers and failure should divide by 4 let gains = scaleWorkStats(this.earnings(), focusPenalty, false); let karma = crime.karma; - const success = determineCrimeSuccess(player, crime.type); + const success = determineCrimeSuccess(crime.type); if (success) { - player.gainMoney(gains.money, "crime"); - player.numPeopleKilled += crime.kills; - player.gainIntelligenceExp(gains.intExp); + Player.gainMoney(gains.money, "crime"); + Player.numPeopleKilled += crime.kills; + Player.gainIntelligenceExp(gains.intExp); } else { gains = scaleWorkStats(gains, 0.25); karma /= 4; } - player.gainHackingExp(gains.hackExp); - player.gainStrengthExp(gains.strExp); - player.gainDefenseExp(gains.defExp); - player.gainDexterityExp(gains.dexExp); - player.gainAgilityExp(gains.agiExp); - player.gainCharismaExp(gains.chaExp); - player.karma -= karma * focusPenalty; + Player.gainHackingExp(gains.hackExp); + Player.gainStrengthExp(gains.strExp); + Player.gainDefenseExp(gains.defExp); + Player.gainDexterityExp(gains.dexExp); + Player.gainAgilityExp(gains.agiExp); + Player.gainCharismaExp(gains.chaExp); + Player.karma -= karma * focusPenalty; } finish(): void { diff --git a/src/Work/FactionWork.tsx b/src/Work/FactionWork.tsx index d1ad4e988..a8464ce86 100644 --- a/src/Work/FactionWork.tsx +++ b/src/Work/FactionWork.tsx @@ -1,7 +1,7 @@ import React from "react"; import { Work, WorkType } from "./Work"; import { Reviver, Generic_toJSON, Generic_fromJSON, IReviverValue } from "../utils/JSONReviver"; -import { IPlayer } from "../PersonObjects/IPlayer"; +import { Player } from "../Player"; import { FactionNames } from "../Faction/data/FactionNames"; import { Factions } from "../Faction/Factions"; import { Faction } from "../Faction/Faction"; @@ -37,29 +37,29 @@ export class FactionWork extends Work { return f; } - getReputationRate(player: IPlayer): number { + getReputationRate(): number { let focusBonus = 1; - if (!player.hasAugmentation(AugmentationNames.NeuroreceptorManager, true)) { - focusBonus = player.focus ? 1 : CONSTANTS.BaseFocusBonus; + if (!Player.hasAugmentation(AugmentationNames.NeuroreceptorManager, true)) { + focusBonus = Player.focus ? 1 : CONSTANTS.BaseFocusBonus; } - return calculateFactionRep(player, this.factionWorkType, this.getFaction().favor) * focusBonus; + return calculateFactionRep(Player, this.factionWorkType, this.getFaction().favor) * focusBonus; } - getExpRates(player: IPlayer): WorkStats { + getExpRates(): WorkStats { let focusBonus = 1; - if (!player.hasAugmentation(AugmentationNames.NeuroreceptorManager, true)) { - focusBonus = player.focus ? 1 : CONSTANTS.BaseFocusBonus; + if (!Player.hasAugmentation(AugmentationNames.NeuroreceptorManager, true)) { + focusBonus = Player.focus ? 1 : CONSTANTS.BaseFocusBonus; } - const rate = calculateFactionExp(player, this.factionWorkType); + const rate = calculateFactionExp(Player, this.factionWorkType); return scaleWorkStats(rate, focusBonus, false); } - process(player: IPlayer, cycles: number): boolean { + process(cycles: number): boolean { this.cyclesWorked += cycles; - this.getFaction().playerReputation += this.getReputationRate(player) * cycles; + this.getFaction().playerReputation += this.getReputationRate() * cycles; - const rate = this.getExpRates(player); - applyWorkStats(player, player, rate, cycles, "class"); + const rate = this.getExpRates(); + applyWorkStats(Player, rate, cycles, "class"); return false; } diff --git a/src/Work/GraftingWork.tsx b/src/Work/GraftingWork.tsx index c0279235d..6b8c75dc0 100644 --- a/src/Work/GraftingWork.tsx +++ b/src/Work/GraftingWork.tsx @@ -2,7 +2,7 @@ import React from "react"; import { CONSTANTS } from "../Constants"; import { AugmentationNames } from "../Augmentation/data/AugmentationNames"; import { GraftableAugmentations } from "../PersonObjects/Grafting/ui/GraftingRoot"; -import { IPlayer } from "../PersonObjects/IPlayer"; +import { Player } from "../Player"; import { Work, WorkType } from "./Work"; import { graftingIntBonus } from "../PersonObjects/Grafting/GraftingHelpers"; import { applyAugmentation } from "../Augmentation/AugmentationHelpers"; @@ -15,7 +15,6 @@ export const isGraftingWork = (w: Work | null): w is GraftingWork => w !== null interface GraftingWorkParams { augmentation: string; - player: IPlayer; singularity: boolean; } @@ -28,33 +27,33 @@ export class GraftingWork extends Work { this.unitCompleted = 0; this.augmentation = params?.augmentation ?? AugmentationNames.Targeting1; const gAugs = GraftableAugmentations(); - if (params?.player) params.player.loseMoney(gAugs[this.augmentation].cost, "augmentations"); + if (params) Player.loseMoney(gAugs[this.augmentation].cost, "augmentations"); } unitNeeded(): number { return new GraftableAugmentation(StaticAugmentations[this.augmentation]).time; } - process(player: IPlayer, cycles: number): boolean { + process(cycles: number): boolean { let focusBonus = 1; - if (!player.hasAugmentation(AugmentationNames.NeuroreceptorManager, true)) { - focusBonus = player.focus ? 1 : CONSTANTS.BaseFocusBonus; + if (!Player.hasAugmentation(AugmentationNames.NeuroreceptorManager, true)) { + focusBonus = Player.focus ? 1 : CONSTANTS.BaseFocusBonus; } this.cyclesWorked += cycles; - this.unitCompleted += CONSTANTS._idleSpeed * cycles * graftingIntBonus(player) * focusBonus; + this.unitCompleted += CONSTANTS._idleSpeed * cycles * graftingIntBonus() * focusBonus; return this.unitCompleted >= this.unitNeeded(); } - finish(player: IPlayer, cancelled: boolean): void { + finish(cancelled: boolean): void { const augName = this.augmentation; if (!cancelled) { applyAugmentation({ name: augName, level: 1 }); - if (!player.hasAugmentation(AugmentationNames.CongruityImplant, true)) { - player.entropy += 1; - player.applyEntropy(player.entropy); + if (!Player.hasAugmentation(AugmentationNames.CongruityImplant, true)) { + Player.entropy += 1; + Player.applyEntropy(Player.entropy); } if (!this.singularity) { @@ -62,7 +61,7 @@ export class GraftingWork extends Work { <> You've finished grafting {augName}.
    The augmentation has been applied to your body{" "} - {player.hasAugmentation(AugmentationNames.CongruityImplant, true) ? "." : ", but you feel a bit off."} + {Player.hasAugmentation(AugmentationNames.CongruityImplant, true) ? "." : ", but you feel a bit off."} , ); } @@ -78,7 +77,7 @@ export class GraftingWork extends Work { // Intelligence gain if (!cancelled) { - player.gainIntelligenceExp( + Player.gainIntelligenceExp( (CONSTANTS.IntelligenceGraftBaseExpGain * this.cyclesWorked * CONSTANTS._idleSpeed) / 10000, ); } diff --git a/src/Work/Work.ts b/src/Work/Work.ts index 9d76e36c8..2c0e3cd17 100644 --- a/src/Work/Work.ts +++ b/src/Work/Work.ts @@ -1,4 +1,3 @@ -import { IPlayer } from "../PersonObjects/IPlayer"; import { IReviverValue } from "../utils/JSONReviver"; export abstract class Work { @@ -12,8 +11,8 @@ export abstract class Work { this.cyclesWorked = 0; } - abstract process(player: IPlayer, cycles: number): boolean; - abstract finish(player: IPlayer, cancelled: boolean): void; + abstract process(cycles: number): boolean; + abstract finish(cancelled: boolean): void; abstract APICopy(): Record; abstract toJSON(): IReviverValue; } diff --git a/src/Work/WorkStats.ts b/src/Work/WorkStats.ts index 07472df41..ac3c5f25e 100644 --- a/src/Work/WorkStats.ts +++ b/src/Work/WorkStats.ts @@ -1,5 +1,5 @@ import { IPerson } from "src/PersonObjects/IPerson"; -import { IPlayer } from "../PersonObjects/IPlayer"; +import { Player } from "../Player"; export interface WorkStats { money: number; @@ -69,7 +69,6 @@ export const scaleWorkStats = (w: WorkStats, n: number, scaleMoney = true): Work }; export const applyWorkStats = ( - player: IPlayer, target: IPerson, workStats: WorkStats, cycles: number, @@ -87,7 +86,7 @@ export const applyWorkStats = ( chaExp: expStats.chaExp, intExp: expStats.intExp, }; - player.gainMoney(gains.money, source); + Player.gainMoney(gains.money, source); return gains; }; diff --git a/src/Work/formulas/Class.ts b/src/Work/formulas/Class.ts index b5263498c..46509366b 100644 --- a/src/Work/formulas/Class.ts +++ b/src/Work/formulas/Class.ts @@ -2,7 +2,7 @@ import { Locations } from "../../Locations/Locations"; import { Location } from "../../Locations/Location"; import { BitNodeMultipliers } from "../../BitNode/BitNodeMultipliers"; import { CONSTANTS } from "../../Constants"; -import { IPlayer } from "../../PersonObjects/IPlayer"; +import { Player } from "../../Player"; import { Class, Classes, ClassType } from "../ClassWork"; import { WorkStats } from "../WorkStats"; import { Server } from "../../Server/Server"; @@ -21,13 +21,12 @@ export function calculateCost(classs: Class, location: Location): number { } export function calculateClassEarnings( - player: IPlayer, - target: IPerson, + person: IPerson, type: ClassType, locationName: LocationName, ): WorkStats { //Find cost and exp gain per game cycle - const hashManager = player.hashManager; + const hashManager = Player.hashManager; const classs = Classes[type]; const location = Locations[locationName]; @@ -47,12 +46,12 @@ export function calculateClassEarnings( return { money: cost, reputation: 0, - hackExp: hackExp * target.mults.hacking_exp * BitNodeMultipliers.ClassGymExpGain, - strExp: strExp * target.mults.strength_exp * BitNodeMultipliers.ClassGymExpGain, - defExp: defExp * target.mults.defense_exp * BitNodeMultipliers.ClassGymExpGain, - dexExp: dexExp * target.mults.dexterity_exp * BitNodeMultipliers.ClassGymExpGain, - agiExp: agiExp * target.mults.agility_exp * BitNodeMultipliers.ClassGymExpGain, - chaExp: chaExp * target.mults.charisma_exp * BitNodeMultipliers.ClassGymExpGain, + hackExp: hackExp * person.mults.hacking_exp * BitNodeMultipliers.ClassGymExpGain, + strExp: strExp * person.mults.strength_exp * BitNodeMultipliers.ClassGymExpGain, + defExp: defExp * person.mults.defense_exp * BitNodeMultipliers.ClassGymExpGain, + dexExp: dexExp * person.mults.dexterity_exp * BitNodeMultipliers.ClassGymExpGain, + agiExp: agiExp * person.mults.agility_exp * BitNodeMultipliers.ClassGymExpGain, + chaExp: chaExp * person.mults.charisma_exp * BitNodeMultipliers.ClassGymExpGain, intExp: 0, }; } diff --git a/src/Work/formulas/Company.ts b/src/Work/formulas/Company.ts index 40b757161..801b8813b 100644 --- a/src/Work/formulas/Company.ts +++ b/src/Work/formulas/Company.ts @@ -1,13 +1,13 @@ import { CompanyPositions } from "../../Company/CompanyPositions"; import { Company } from "../../Company/Company"; -import { IPlayer } from "../../PersonObjects/IPlayer"; +import { Player } from "../../Player"; import { WorkStats } from "../WorkStats"; import { BitNodeMultipliers } from "../../BitNode/BitNodeMultipliers"; import { CONSTANTS } from "../../Constants"; import { IPerson } from "src/PersonObjects/IPerson"; -export const calculateCompanyWorkStats = (player: IPlayer, worker: IPerson, company: Company): WorkStats => { - const companyPositionName = player.jobs[company.name]; +export const calculateCompanyWorkStats = (worker: IPerson, company: Company): WorkStats => { + const companyPositionName = Player.jobs[company.name]; const companyPosition = CompanyPositions[companyPositionName]; // If player has SF-11, calculate salary multiplier from favor @@ -17,7 +17,7 @@ export const calculateCompanyWorkStats = (player: IPlayer, worker: IPerson, comp } let bn11Mult = 1; - if (player.sourceFileLvl(11) > 0) { + if (Player.sourceFileLvl(11) > 0) { bn11Mult = favorMult; } diff --git a/src/engine.tsx b/src/engine.tsx index f7037ee06..03ceac12d 100644 --- a/src/engine.tsx +++ b/src/engine.tsx @@ -91,7 +91,7 @@ const Engine: { Player.playtimeSinceLastAug += time; Player.playtimeSinceLastBitnode += time; - Terminal.process(Router, Player, numCycles); + Terminal.process(numCycles); Player.processWork(numCycles); @@ -120,7 +120,7 @@ const Engine: { // Sleeves for (let i = 0; i < Player.sleeves.length; ++i) { - Player.sleeves[i].process(Player, numCycles); + Player.sleeves[i].process(numCycles); } // Counters @@ -131,7 +131,7 @@ const Engine: { updateOnlineScriptTimes(numCycles); // Hacknet Nodes - processHacknetEarnings(Player, numCycles); + processHacknetEarnings(numCycles); }, /** @@ -205,12 +205,12 @@ const Engine: { } } if (Player.corporation instanceof Corporation) { - Player.corporation.process(Player); + Player.corporation.process(); } if (Engine.Counters.mechanicProcess <= 0) { if (Player.bladeburner instanceof Bladeburner) { try { - Player.bladeburner.process(Router, Player); + Player.bladeburner.process(); } catch (e) { exceptionAlert("Exception caught in Bladeburner.process(): " + e); } @@ -240,7 +240,7 @@ const Engine: { if (loadGame(saveString)) { ThemeEvents.emit(); - initBitNodeMultipliers(Player); + initBitNodeMultipliers(); initAugmentations(); // Also calls Player.reapplyAllAugmentations() Player.reapplyAllSourceFiles(); if (Player.hasWseAccount) { @@ -308,8 +308,8 @@ const Engine: { } // Hacknet Nodes offline progress - const offlineProductionFromHacknetNodes = processHacknetEarnings(Player, numCyclesOffline); - const hacknetProdInfo = hasHacknetServers(Player) ? ( + const offlineProductionFromHacknetNodes = processHacknetEarnings(numCyclesOffline); + const hacknetProdInfo = hasHacknetServers() ? ( <> hashes @@ -345,7 +345,7 @@ const Engine: { // Sleeves offline progress for (let i = 0; i < Player.sleeves.length; ++i) { - Player.sleeves[i].process(Player, numCyclesOffline); + Player.sleeves[i].process(numCyclesOffline); } // Update total playtime @@ -392,7 +392,7 @@ const Engine: { ); } else { // No save found, start new game - initBitNodeMultipliers(Player); + initBitNodeMultipliers(); Engine.start(); // Run main game loop and Scripts loop Player.init(); initForeignServers(Player.getHomeComputer()); diff --git a/src/ui/ErrorBoundary.tsx b/src/ui/ErrorBoundary.tsx index 67a808716..5a0ceb53a 100644 --- a/src/ui/ErrorBoundary.tsx +++ b/src/ui/ErrorBoundary.tsx @@ -2,10 +2,10 @@ import React, { ErrorInfo } from "react"; import { IErrorData, getErrorForDisplay } from "../utils/ErrorHelper"; import { RecoveryRoot } from "./React/RecoveryRoot"; -import { IRouter, Page } from "./Router"; +import { Page } from "./Router"; +import { Router } from "./GameRoot"; interface IProps { - router: IRouter; softReset: () => void; } @@ -31,7 +31,7 @@ export class ErrorBoundary extends React.Component { componentDidCatch(error: Error, errorInfo: ErrorInfo): void { this.setState({ errorInfo, - page: this.props.router.page(), + page: Router.page(), }); console.error(error, errorInfo); } @@ -47,14 +47,7 @@ export class ErrorBoundary extends React.Component { } } - return ( - this.reset()} - /> - ); + return this.reset()} />; } return this.props.children; } diff --git a/src/ui/GameRoot.tsx b/src/ui/GameRoot.tsx index 933521ac3..b7d48c2a2 100644 --- a/src/ui/GameRoot.tsx +++ b/src/ui/GameRoot.tsx @@ -1,8 +1,6 @@ import React, { useState, useEffect } from "react"; import { Player } from "../Player"; -import { Engine } from "../engine"; -import { Terminal } from "../Terminal"; import { installAugmentations } from "../Augmentation/AugmentationHelpers"; import { saveObject } from "../SaveObject"; import { onExport } from "../ExportBonus"; @@ -311,7 +309,7 @@ export function GameRoot(): React.ReactElement { let bypassGame = false; switch (page) { case Page.Recovery: { - mainPage = ; + mainPage = ; withSidebar = false; withPopups = false; bypassGame = true; @@ -341,7 +339,7 @@ export function GameRoot(): React.ReactElement { break; } case Page.Terminal: { - mainPage = ; + mainPage = ; break; } case Page.Sleeves: { @@ -357,15 +355,7 @@ export function GameRoot(): React.ReactElement { break; } case Page.ScriptEditor: { - mainPage = ( - - ); + mainPage = ; break; } case Page.ActiveScripts: { @@ -373,7 +363,7 @@ export function GameRoot(): React.ReactElement { break; } case Page.Hacknet: { - mainPage = ; + mainPage = ; break; } case Page.CreateProgram: { @@ -381,7 +371,7 @@ export function GameRoot(): React.ReactElement { break; } case Page.Factions: { - mainPage = ; + mainPage = ; break; } case Page.Faction: { @@ -389,7 +379,7 @@ export function GameRoot(): React.ReactElement { break; } case Page.Milestones: { - mainPage = ; + mainPage = ; break; } case Page.Tutorial: { @@ -405,7 +395,7 @@ export function GameRoot(): React.ReactElement { break; } case Page.DevMenu: { - mainPage = ; + mainPage = ; break; } case Page.Gang: { @@ -425,11 +415,11 @@ export function GameRoot(): React.ReactElement { break; } case Page.Travel: { - mainPage = ; + mainPage = ; break; } case Page.StockMarket: { - mainPage = ; + mainPage = ; break; } case Page.City: { @@ -444,12 +434,10 @@ export function GameRoot(): React.ReactElement { case Page.Options: { mainPage = ( saveObject.saveGame()} export={() => { // Apply the export bonus before saving the game - onExport(Player); + onExport(); saveObject.exportGame(); }} forceKill={killAllScripts} @@ -463,7 +451,7 @@ export function GameRoot(): React.ReactElement { { // Apply the export bonus before saving the game - onExport(Player); + onExport(); saveObject.exportGame(); }} installAugmentationsFn={() => { @@ -478,11 +466,11 @@ export function GameRoot(): React.ReactElement { break; } case Page.ThemeBrowser: { - mainPage = ; + mainPage = ; break; } case Page.ImportSave: { - mainPage = ; + mainPage = ; withSidebar = false; withPopups = false; bypassGame = true; @@ -492,7 +480,7 @@ export function GameRoot(): React.ReactElement { return ( - + @@ -505,8 +493,6 @@ export function GameRoot(): React.ReactElement { {withSidebar ? ( { diff --git a/src/ui/React/CharacterOverview.tsx b/src/ui/React/CharacterOverview.tsx index adbcdc2f5..c4f2ab166 100644 --- a/src/ui/React/CharacterOverview.tsx +++ b/src/ui/React/CharacterOverview.tsx @@ -197,7 +197,7 @@ function Work(): React.ReactElement { <> rep
    ( - ) + ) ); } @@ -217,7 +217,7 @@ function Work(): React.ReactElement { <> rep
    ( - ) + ) ); } diff --git a/src/ui/React/ImportSaveRoot.tsx b/src/ui/React/ImportSaveRoot.tsx index 90b9e1fc7..a9f2f1525 100644 --- a/src/ui/React/ImportSaveRoot.tsx +++ b/src/ui/React/ImportSaveRoot.tsx @@ -31,7 +31,7 @@ import { convertTimeMsToTimeElapsedString } from "../../utils/StringHelperFuncti import { numeralWrapper } from "../numeralFormat"; import { ConfirmationModal } from "./ConfirmationModal"; import { pushImportResult } from "../../Electron"; -import { IRouter } from "../Router"; +import { Router } from "../GameRoot"; const useStyles = makeStyles((theme: Theme) => createStyles({ @@ -105,7 +105,6 @@ function ComparisonIcon({ isBetter }: { isBetter: boolean }): JSX.Element { export interface IProps { importString: string; automatic: boolean; - router: IRouter; } let initialAutosave = 0; @@ -120,7 +119,7 @@ export function ImportSaveRoot(props: IProps): JSX.Element { function handleGoBack(): void { Settings.AutosaveInterval = initialAutosave; pushImportResult(false); - props.router.allowRouting(true); + Router.allowRouting(true); setHeadback(true); } @@ -133,11 +132,11 @@ export function ImportSaveRoot(props: IProps): JSX.Element { // We want to disable autosave while we're in this mode initialAutosave = Settings.AutosaveInterval; Settings.AutosaveInterval = 0; - props.router.allowRouting(false); + Router.allowRouting(false); }, []); useEffect(() => { - if (headback) props.router.toTerminal(); + if (headback) Router.toTerminal(); }, [headback]); useEffect(() => { diff --git a/src/ui/React/Money.tsx b/src/ui/React/Money.tsx index 90128d001..085bf65ad 100644 --- a/src/ui/React/Money.tsx +++ b/src/ui/React/Money.tsx @@ -1,6 +1,6 @@ import * as React from "react"; import { numeralWrapper } from "../numeralFormat"; -import { IPlayer } from "../../PersonObjects/IPlayer"; +import { Player } from "../../Player"; import { Theme } from "@mui/material/styles"; import makeStyles from "@mui/styles/makeStyles"; import createStyles from "@mui/styles/createStyles"; @@ -18,14 +18,13 @@ const useStyles = makeStyles((theme: Theme) => interface IProps { money: number | string; - player?: IPlayer; + forPurchase?: boolean; } export function Money(props: IProps): React.ReactElement { const classes = useStyles(); - if (props.player !== undefined) { - if (typeof props.money !== "number") throw new Error("if player if provided, money should be number, contact dev"); - if (!props.player.canAfford(props.money)) - return {numeralWrapper.formatMoney(props.money)}; + if (props.forPurchase){ + if (typeof props.money !== "number") throw new Error("if value is for a purchase, money should be number, contact dev"); + if (!Player.canAfford(props.money)) return {numeralWrapper.formatMoney(props.money)}; } return ( diff --git a/src/ui/React/RecoveryRoot.tsx b/src/ui/React/RecoveryRoot.tsx index 341cb791f..20f24acf2 100644 --- a/src/ui/React/RecoveryRoot.tsx +++ b/src/ui/React/RecoveryRoot.tsx @@ -3,7 +3,7 @@ import React, { useEffect } from "react"; import { Typography, Link, Button, ButtonGroup, Tooltip, Box, Paper, TextField } from "@mui/material"; import { Settings } from "../../Settings/Settings"; import { load } from "../../db"; -import { IRouter } from "../Router"; +import { Router } from "../GameRoot"; import { download } from "../../SaveObject"; import { IErrorData, newIssueUrl } from "../../utils/ErrorHelper"; import { DeleteGameButton } from "./DeleteGameButton"; @@ -19,17 +19,16 @@ export function ActivateRecoveryMode(): void { } interface IProps { - router: IRouter; softReset: () => void; errorData?: IErrorData; resetError?: () => void; } -export function RecoveryRoot({ router, softReset, errorData, resetError }: IProps): React.ReactElement { +export function RecoveryRoot({ softReset, errorData, resetError }: IProps): React.ReactElement { function recover(): void { if (resetError) resetError(); RecoveryMode = false; - router.toTerminal(); + Router.toTerminal(); } Settings.AutosaveInterval = 0; diff --git a/src/ui/WorkInProgressRoot.tsx b/src/ui/WorkInProgressRoot.tsx index f99730478..dd518ec6d 100644 --- a/src/ui/WorkInProgressRoot.tsx +++ b/src/ui/WorkInProgressRoot.tsx @@ -10,7 +10,8 @@ import { LocationName } from "../Locations/data/LocationNames"; import { Locations } from "../Locations/Locations"; import { Settings } from "../Settings/Settings"; import { convertTimeMsToTimeElapsedString } from "../utils/StringHelperFunctions"; -import { use } from "./Context"; +import { Player } from "../Player"; +import { Router } from "./GameRoot" import { numeralWrapper } from "./numeralFormat"; import { Money } from "./React/Money"; import { MoneyRate } from "./React/MoneyRate"; @@ -202,9 +203,6 @@ export function WorkInProgressRoot(): React.ReactElement { return () => clearInterval(id); }, []); - const player = use.Player(); - const router = use.Router(); - let workInfo: IWorkInfo = { buttons: { cancel: () => undefined, @@ -213,25 +211,25 @@ export function WorkInProgressRoot(): React.ReactElement { stopText: "", }; - if (player.currentWork === null) { - setTimeout(() => router.toTerminal()); + if (Player.currentWork === null) { + setTimeout(() => Router.toTerminal()); return <>; } - if (isCrimeWork(player.currentWork)) { - const crime = player.currentWork.getCrime(); - const completion = (player.currentWork.unitCompleted / crime.time) * 100; - const gains = player.currentWork.earnings(); - const successChance = crime.successRate(player); + if (isCrimeWork(Player.currentWork)) { + const crime = Player.currentWork.getCrime(); + const completion = (Player.currentWork.unitCompleted / crime.time) * 100; + const gains = Player.currentWork.earnings(); + const successChance = crime.successRate(Player); workInfo = { buttons: { cancel: () => { - router.toLocation(Locations[LocationName.Slums]); - player.finishWork(true); + Router.toLocation(Locations[LocationName.Slums]); + Player.finishWork(true); }, unfocus: () => { - router.toCity(); - player.stopFocusing(); + Router.toCity(); + Player.stopFocusing(); }, }, title: `You are attempting ${crime.workName}`, @@ -247,7 +245,7 @@ export function WorkInProgressRoot(): React.ReactElement { ...CrimeExpRows(gains), ], progress: { - remaining: crime.time - player.currentWork.unitCompleted, + remaining: crime.time - Player.currentWork.unitCompleted, percentage: completion, }, @@ -255,16 +253,16 @@ export function WorkInProgressRoot(): React.ReactElement { }; } - if (isClassWork(player.currentWork)) { - const classWork = player.currentWork; + if (isClassWork(Player.currentWork)) { + const classWork = Player.currentWork; function cancel(): void { - player.finishWork(true); - router.toCity(); + Player.finishWork(true); + Router.toCity(); } function unfocus(): void { - router.toCity(); - player.stopFocusing(); + Router.toCity(); + Player.stopFocusing(); } let stopText = ""; @@ -274,7 +272,7 @@ export function WorkInProgressRoot(): React.ReactElement { stopText = "Stop taking course"; } - const rates = classWork.calculateRates(player); + const rates = classWork.calculateRates(); workInfo = { buttons: { cancel: cancel, @@ -302,15 +300,15 @@ export function WorkInProgressRoot(): React.ReactElement { }; } - if (isCreateProgramWork(player.currentWork)) { - const create = player.currentWork; + if (isCreateProgramWork(Player.currentWork)) { + const create = Player.currentWork; function cancel(): void { - player.finishWork(true); - router.toTerminal(); + Player.finishWork(true); + Router.toTerminal(); } function unfocus(): void { - router.toTerminal(); - player.stopFocusing(); + Router.toTerminal(); + Player.stopFocusing(); } const completion = (create.unitCompleted / create.unitNeeded()) * 100; @@ -336,15 +334,15 @@ export function WorkInProgressRoot(): React.ReactElement { }; } - if (isGraftingWork(player.currentWork)) { - const graft = player.currentWork; + if (isGraftingWork(Player.currentWork)) { + const graft = Player.currentWork; function cancel(): void { - player.finishWork(true); - router.toTerminal(); + Player.finishWork(true); + Router.toTerminal(); } function unfocus(): void { - router.toTerminal(); - player.stopFocusing(); + Router.toTerminal(); + Player.stopFocusing(); } workInfo = { @@ -372,15 +370,15 @@ export function WorkInProgressRoot(): React.ReactElement { }; } - if (isFactionWork(player.currentWork)) { - const faction = player.currentWork.getFaction(); + if (isFactionWork(Player.currentWork)) { + const faction = Player.currentWork.getFaction(); if (!faction) { workInfo = { buttons: { - cancel: () => router.toFactions(), + cancel: () => Router.toFactions(), }, title: - `You have not joined ${player.currentWork.factionName || "(Faction not found)"} at this time,` + + `You have not joined ${Player.currentWork.factionName || "(Faction not found)"} at this time,` + " please try again if you think this should have worked", stopText: "Back to Factions", @@ -388,12 +386,12 @@ export function WorkInProgressRoot(): React.ReactElement { } function cancel(): void { - router.toFaction(faction); - player.finishWork(true); + Router.toFaction(faction); + Player.finishWork(true); } function unfocus(): void { - router.toFaction(faction); - player.stopFocusing(); + Router.toFaction(faction); + Player.stopFocusing(); } const description = { @@ -402,7 +400,7 @@ export function WorkInProgressRoot(): React.ReactElement { [FactionWorkType.SECURITY]: "performing security detail", }; - const exp = player.currentWork.getExpRates(player); + const exp = Player.currentWork.getExpRates(); workInfo = { buttons: { @@ -411,34 +409,34 @@ export function WorkInProgressRoot(): React.ReactElement { }, title: ( <> - You are currently {description[player.currentWork.factionWorkType]} for {faction.name} + You are currently {description[Player.currentWork.factionWorkType]} for {faction.name} ), description: ( <> Current Faction Reputation: ( - ) + ) ), gains: ExpRows(exp), progress: { - elapsed: player.currentWork.cyclesWorked * CONSTANTS._idleSpeed, + elapsed: Player.currentWork.cyclesWorked * CONSTANTS._idleSpeed, }, stopText: "Stop Faction work", }; } - if (isCompanyWork(player.currentWork)) { - const comp = Companies[player.currentWork.companyName]; + if (isCompanyWork(Player.currentWork)) { + const comp = Companies[Player.currentWork.companyName]; if (comp == null || !(comp instanceof Company)) { workInfo = { buttons: { - cancel: () => router.toTerminal(), + cancel: () => Router.toTerminal(), }, title: - `You cannot work for ${player.currentWork.companyName || "(Company not found)"} at this time,` + + `You cannot work for ${Player.currentWork.companyName || "(Company not found)"} at this time,` + " please try again if you think this should have worked", stopText: "Back to Terminal", @@ -448,16 +446,16 @@ export function WorkInProgressRoot(): React.ReactElement { const companyRep = comp.playerReputation; function cancel(): void { - player.finishWork(true); - router.toJob(Locations[comp.name]); + Player.finishWork(true); + Router.toJob(Locations[comp.name]); } function unfocus(): void { - player.stopFocusing(); - router.toJob(Locations[comp.name]); + Player.stopFocusing(); + Router.toJob(Locations[comp.name]); } - const position = player.jobs[player.currentWork.companyName]; - const gains = player.currentWork.getGainRates(player); + const position = Player.jobs[Player.currentWork.companyName]; + const gains = Player.currentWork.getGainRates(); workInfo = { buttons: { cancel: cancel, @@ -465,7 +463,7 @@ export function WorkInProgressRoot(): React.ReactElement { }, title: ( <> - You are currently working as a {position} at {player.currentWork.companyName} + You are currently working as a {position} at {Player.currentWork.companyName} ), @@ -488,7 +486,7 @@ export function WorkInProgressRoot(): React.ReactElement { ...ExpRows(gains), ], progress: { - elapsed: player.currentWork.cyclesWorked * CONSTANTS._idleSpeed, + elapsed: Player.currentWork.cyclesWorked * CONSTANTS._idleSpeed, }, stopText: "Stop working", From a21b1029d7c32fc79b9512339b4c2a1edb74e1a0 Mon Sep 17 00:00:00 2001 From: Snarling <84951833+Snarling@users.noreply.github.com> Date: Mon, 12 Sep 2022 18:00:09 -0400 Subject: [PATCH 13/46] No more player/router context --- src/Arcade/ui/ArcadeRoot.tsx | 5 +- src/Arcade/ui/BBCabinet.tsx | 5 +- src/Augmentation/ui/AugmentationsRoot.tsx | 11 +- .../ui/InstalledAugmentations.tsx | 5 +- .../ui/PurchaseAugmentationModal.tsx | 6 +- src/BitNode/ui/BitFlumeModal.tsx | 5 +- .../ui/BitnodeMultipliersDescription.tsx | 17 +- src/BitNode/ui/BitverseRoot.tsx | 26 +-- src/BitNode/ui/PortalModal.tsx | 7 +- src/Bladeburner/ui/ActionLevel.tsx | 3 - src/Bladeburner/ui/BlackOpPage.tsx | 5 +- src/Bladeburner/ui/BladeburnerCinematic.tsx | 5 +- src/Bladeburner/ui/BladeburnerRoot.tsx | 8 +- src/Bladeburner/ui/StartButton.tsx | 5 +- src/Company/ui/QuitJobModal.tsx | 5 +- src/Corporation/ICorporation.ts | 5 +- src/Corporation/ui/CorporationRoot.tsx | 5 +- src/Corporation/ui/Industry.tsx | 2 - src/Corporation/ui/Overview.tsx | 8 +- .../ui/modals/BribeFactionModal.tsx | 9 +- .../ui/modals/BuybackSharesModal.tsx | 5 +- .../ui/modals/CreateCorporationModal.tsx | 23 ++- src/Corporation/ui/modals/SellSharesModal.tsx | 2 - src/Crime/Crime.ts | 6 +- src/Exploits/Unclickable.tsx | 5 +- src/Faction/FactionInfo.tsx | 8 +- src/Faction/ui/CreateGangModal.tsx | 9 +- src/Faction/ui/GangButton.tsx | 19 +- src/Faction/ui/InvitationModal.tsx | 5 +- src/GameOptions/ui/GameplayPage.tsx | 5 +- src/Gang/GangMember.ts | 10 +- src/Gang/ui/EquipmentsSubpage.tsx | 11 +- src/Gang/ui/GangRoot.tsx | 7 +- src/Infiltration/ui/Game.tsx | 15 +- src/Infiltration/ui/GameTimer.tsx | 5 +- src/Infiltration/ui/InfiltrationRoot.tsx | 11 +- src/Infiltration/ui/Victory.tsx | 19 +- src/Locations/ui/ApplyToJobButton.tsx | 6 +- src/Locations/ui/City.tsx | 21 +-- src/Locations/ui/CompanyLocation.tsx | 39 ++--- src/Locations/ui/PurchaseServerModal.tsx | 5 +- src/Locations/ui/SlumsLocation.tsx | 101 ++++++----- src/Locations/ui/SpecialLocation.tsx | 86 +++++---- src/Locations/ui/TravelConfirmationModal.tsx | 2 - src/Locations/ui/UniversityLocation.tsx | 12 +- src/NetscriptFunctions/Gang.ts | 2 +- src/NetscriptFunctions/Singularity.ts | 6 +- .../Sleeve/ui/CovenantPurchasesRoot.tsx | 25 ++- src/PersonObjects/Sleeve/ui/SleeveRoot.tsx | 5 +- src/RedPill.tsx | 8 +- src/ui/ActiveScripts/ScriptProduction.tsx | 7 +- src/ui/CharacterStats.tsx | 165 +++++++++--------- src/ui/Context.ts | 19 -- src/ui/GameRoot.tsx | 4 +- src/ui/React/CharacterOverview.tsx | 115 ++++++------ src/ui/React/Overview.tsx | 5 +- 56 files changed, 418 insertions(+), 527 deletions(-) delete mode 100644 src/ui/Context.ts diff --git a/src/Arcade/ui/ArcadeRoot.tsx b/src/Arcade/ui/ArcadeRoot.tsx index efb1f92d9..ff353313e 100644 --- a/src/Arcade/ui/ArcadeRoot.tsx +++ b/src/Arcade/ui/ArcadeRoot.tsx @@ -2,7 +2,7 @@ import React, { useState } from "react"; import { BBCabinetRoot } from "./BBCabinet"; import Button from "@mui/material/Button"; -import { use } from "../../ui/Context"; +import { Player } from "../../Player"; import { AlertEvents } from "../../ui/React/AlertManager"; enum Page { @@ -11,11 +11,10 @@ enum Page { } export function ArcadeRoot(): React.ReactElement { - const player = use.Player(); const [page, setPage] = useState(Page.None); function mbBurner2000(): void { - if (player.sourceFileLvl(1) === 0) { + if (Player.sourceFileLvl(1) === 0) { AlertEvents.emit("This machine is broken."); } else { setPage(Page.Megabyteburner2000); diff --git a/src/Arcade/ui/BBCabinet.tsx b/src/Arcade/ui/BBCabinet.tsx index b0627b2f0..1b3c95a85 100644 --- a/src/Arcade/ui/BBCabinet.tsx +++ b/src/Arcade/ui/BBCabinet.tsx @@ -1,6 +1,6 @@ import React, { useEffect } from "react"; import Typography from "@mui/material/Typography"; -import { use } from "../../ui/Context"; +import { Player } from "../../Player"; import { Exploit } from "../../Exploits/Exploit"; const metaBB = "https://bitburner-official.github.io/bitburner-legacy/"; @@ -12,11 +12,10 @@ const style = { }; export function BBCabinetRoot(): React.ReactElement { - const player = use.Player(); useEffect(() => { window.addEventListener("message", function (this: Window, ev: MessageEvent) { if (ev.isTrusted && ev.origin == "https://bitburner-official.github.io" && ev.data) { - player.giveExploit(Exploit.TrueRecursion); + Player.giveExploit(Exploit.TrueRecursion); } }); }); diff --git a/src/Augmentation/ui/AugmentationsRoot.tsx b/src/Augmentation/ui/AugmentationsRoot.tsx index f5d024c86..912ebf540 100644 --- a/src/Augmentation/ui/AugmentationsRoot.tsx +++ b/src/Augmentation/ui/AugmentationsRoot.tsx @@ -10,8 +10,6 @@ import { PurchasedAugmentations } from "./PurchasedAugmentations"; import { SourceFilesElement } from "./SourceFiles"; import { canGetBonus } from "../../ExportBonus"; -import { use } from "../../ui/Context"; - import Typography from "@mui/material/Typography"; import Button from "@mui/material/Button"; import Tooltip from "@mui/material/Tooltip"; @@ -86,7 +84,6 @@ interface IProps { export function AugmentationsRoot(props: IProps): React.ReactElement { const [installOpen, setInstallOpen] = useState(false); - const player = use.Player(); const setRerender = useState(false)[1]; function rerender(): void { setRerender((o) => !o); @@ -179,7 +176,7 @@ export function AugmentationsRoot(props: IProps): React.ReactElement { 'I never asked for this'
    }> - @@ -191,7 +188,7 @@ export function AugmentationsRoot(props: IProps): React.ReactElement {
    - {player.queuedAugmentations.length > 0 ? ( + {Player.queuedAugmentations.length > 0 ? ( @@ -208,8 +205,8 @@ export function AugmentationsRoot(props: IProps): React.ReactElement { my: 1, display: "grid", gridTemplateColumns: `repeat(${ - +!!((player.augmentations.find((e) => e.name === AugmentationNames.NeuroFluxGovernor)?.level ?? 0) > 0) + - +!!(player.entropy > 0) + +!!((Player.augmentations.find((e) => e.name === AugmentationNames.NeuroFluxGovernor)?.level ?? 0) > 0) + + +!!(Player.entropy > 0) }, 1fr)`, gap: 1, }} diff --git a/src/Augmentation/ui/InstalledAugmentations.tsx b/src/Augmentation/ui/InstalledAugmentations.tsx index 1ec34391f..3c06a68a4 100644 --- a/src/Augmentation/ui/InstalledAugmentations.tsx +++ b/src/Augmentation/ui/InstalledAugmentations.tsx @@ -12,14 +12,13 @@ import Tooltip from "@mui/material/Tooltip"; import React, { useState } from "react"; import { OwnedAugmentationsOrderSetting } from "../../Settings/SettingEnums"; import { Settings } from "../../Settings/Settings"; -import { use } from "../../ui/Context"; +import { Player } from "../../Player"; import { StaticAugmentations } from "../StaticAugmentations"; import { AugmentationNames } from "../data/AugmentationNames"; export function InstalledAugmentations(): React.ReactElement { const setRerender = useState(true)[1]; - const player = use.Player(); - const sourceAugs = player.augmentations.slice().filter((aug) => aug.name !== AugmentationNames.NeuroFluxGovernor); + const sourceAugs = Player.augmentations.slice().filter((aug) => aug.name !== AugmentationNames.NeuroFluxGovernor); const [selectedAug, setSelectedAug] = useState(sourceAugs[0]); diff --git a/src/Augmentation/ui/PurchaseAugmentationModal.tsx b/src/Augmentation/ui/PurchaseAugmentationModal.tsx index bf3157a18..20990efb7 100644 --- a/src/Augmentation/ui/PurchaseAugmentationModal.tsx +++ b/src/Augmentation/ui/PurchaseAugmentationModal.tsx @@ -6,7 +6,7 @@ import { purchaseAugmentation } from "../../Faction/FactionHelpers"; import { isRepeatableAug } from "../AugmentationHelpers"; import { Money } from "../../ui/React/Money"; import { Modal } from "../../ui/React/Modal"; -import { use } from "../../ui/Context"; +import { Player } from "../../Player"; import Typography from "@mui/material/Typography"; import Button from "@mui/material/Button"; @@ -22,10 +22,8 @@ export function PurchaseAugmentationModal(props: IProps): React.ReactElement { return <>; } - const player = use.Player(); - function buy(): void { - if (!isRepeatableAug(props.aug as Augmentation) && player.hasAugmentation(props.aug as Augmentation)) { + if (!isRepeatableAug(props.aug as Augmentation) && Player.hasAugmentation(props.aug as Augmentation)) { return; } diff --git a/src/BitNode/ui/BitFlumeModal.tsx b/src/BitNode/ui/BitFlumeModal.tsx index 8fdd3e1fe..b55038b57 100644 --- a/src/BitNode/ui/BitFlumeModal.tsx +++ b/src/BitNode/ui/BitFlumeModal.tsx @@ -1,6 +1,6 @@ import React, { useState, useEffect } from "react"; import { Modal } from "../../ui/React/Modal"; -import { use } from "../../ui/Context"; +import { Router } from "../../ui/GameRoot"; import { EventEmitter } from "../../utils/EventEmitter"; import Typography from "@mui/material/Typography"; import Button from "@mui/material/Button"; @@ -8,10 +8,9 @@ import Button from "@mui/material/Button"; export const BitFlumeEvent = new EventEmitter<[]>(); export function BitFlumeModal(): React.ReactElement { - const router = use.Router(); const [open, setOpen] = useState(false); function flume(): void { - router.toBitVerse(true, false); + Router.toBitVerse(true, false); setOpen(false); } diff --git a/src/BitNode/ui/BitnodeMultipliersDescription.tsx b/src/BitNode/ui/BitnodeMultipliersDescription.tsx index 51516aaf9..21225d995 100644 --- a/src/BitNode/ui/BitnodeMultipliersDescription.tsx +++ b/src/BitNode/ui/BitnodeMultipliersDescription.tsx @@ -5,7 +5,7 @@ import { uniqueId } from "lodash"; import React from "react"; import { SpecialServers } from "../../Server/data/SpecialServers"; import { Settings } from "../../Settings/Settings"; -import { use } from "../../ui/Context"; +import { Player } from "../../ui/Player"; import { StatsRow } from "../../ui/React/StatsRow"; import { defaultMultipliers, getBitNodeMultipliers } from "../BitNode"; import { IBitNodeMultipliers } from "../BitNodeMultipliers"; @@ -33,13 +33,12 @@ export function BitnodeMultiplierDescription({ n, level }: IProps): React.ReactE } export const BitNodeMultipliersDisplay = ({ n, level }: IProps): React.ReactElement => { - const player = use.Player(); // If a level argument has been provided, use that as the multiplier level // If not, then we have to assume that we want the next level up from the // current node's source file, so we get the min of that, the SF's max level, // or if it's BN12, ∞ const maxSfLevel = n === 12 ? Infinity : 3; - const mults = getBitNodeMultipliers(n, level ?? Math.min(player.sourceFileLvl(n) + 1, maxSfLevel)); + const mults = getBitNodeMultipliers(n, level ?? Math.min(Player.sourceFileLvl(n) + 1, maxSfLevel)); return ( @@ -277,8 +276,7 @@ function InfiltrationMults({ mults }: IMultsProps): React.ReactElement { } function BladeburnerMults({ mults }: IMultsProps): React.ReactElement { - const player = use.Player(); - if (!player.canAccessBladeburner()) return <>; + if (!Player.canAccessBladeburner()) return <>; if (mults.BladeburnerRank === 0) { const rows: IBNMultRows = { @@ -297,8 +295,7 @@ function BladeburnerMults({ mults }: IMultsProps): React.ReactElement { } function StanekMults({ mults }: IMultsProps): React.ReactElement { - const player = use.Player(); - if (!player.canAccessCotMG()) return <>; + if (!Player.canAccessCotMG()) return <>; const extraSize = mults.StaneksGiftExtraSize.toFixed(3); const rows: IBNMultRows = { @@ -313,8 +310,7 @@ function StanekMults({ mults }: IMultsProps): React.ReactElement { } function GangMults({ mults }: IMultsProps): React.ReactElement { - const player = use.Player(); - if (player.bitNodeN !== 2 && player.sourceFileLvl(2) <= 0) return <>; + if (Player.bitNodeN !== 2 && Player.sourceFileLvl(2) <= 0) return <>; const rows: IBNMultRows = { GangSoftcap: { @@ -328,8 +324,7 @@ function GangMults({ mults }: IMultsProps): React.ReactElement { } function CorporationMults({ mults }: IMultsProps): React.ReactElement { - const player = use.Player(); - if (!player.canAccessCorporation()) return <>; + if (!Player.canAccessCorporation()) return <>; if (mults.CorporationSoftcap < 0.15) { const rows: IBNMultRows = { diff --git a/src/BitNode/ui/BitverseRoot.tsx b/src/BitNode/ui/BitverseRoot.tsx index 280e72bb0..a3483f832 100644 --- a/src/BitNode/ui/BitverseRoot.tsx +++ b/src/BitNode/ui/BitverseRoot.tsx @@ -1,10 +1,8 @@ import React, { useState } from "react"; -import { IRouter } from "../../ui/Router"; import { BitNodes } from "../BitNode"; -import { enterBitNode } from "../../RedPill"; import { PortalModal } from "./PortalModal"; import { CinematicText } from "../../ui/React/CinematicText"; -import { use } from "../../ui/Context"; +import { Player } from "../../Player"; import makeStyles from "@mui/styles/makeStyles"; import createStyles from "@mui/styles/createStyles"; import IconButton from "@mui/material/IconButton"; @@ -46,7 +44,6 @@ interface IPortalProps { level: number; destroyedBitNode: number; flume: boolean; - enter: (router: IRouter, flume: boolean, destroyedBitNode: number, newBitNode: number) => void; } function BitNodePortal(props: IPortalProps): React.ReactElement { const [portalOpen, setPortalOpen] = useState(false); @@ -105,7 +102,6 @@ function BitNodePortal(props: IPortalProps): React.ReactElement { onClose={() => setPortalOpen(false)} n={props.n} level={props.level} - enter={props.enter} destroyedBitNode={props.destroyedBitNode} flume={props.flume} /> @@ -118,13 +114,10 @@ function BitNodePortal(props: IPortalProps): React.ReactElement { interface IProps { flume: boolean; quick: boolean; - enter: (router: IRouter, flume: boolean, destroyedBitNode: number, newBitNode: number) => void; } export function BitverseRoot(props: IProps): React.ReactElement { - const player = use.Player(); - const enter = enterBitNode; - const destroyed = player.bitNodeN; + const destroyed = Player.bitNodeN; const [destroySequence, setDestroySequence] = useState(!props.quick); if (destroySequence) { @@ -158,7 +151,7 @@ export function BitverseRoot(props: IProps): React.ReactElement { } const nextSourceFileLvl = (n: number): number => { - const lvl = player.sourceFileLvl(n); + const lvl = Player.sourceFileLvl(n); if (n !== destroyed) { return lvl; } @@ -181,7 +174,6 @@ export function BitverseRoot(props: IProps): React.ReactElement { key={node.number} n={node.number} level={nextSourceFileLvl(node.number)} - enter={enter} flume={props.flume} destroyedBitNode={destroyed} /> @@ -234,19 +226,19 @@ export function BitverseRoot(props: IProps): React.ReactElement { O | | | \| | O / _/ | / O | |/ | | | O | | | |O / | | O / | O O | | \ O| | | | | | |/ \/ / __| | |/ \ | \ | |__ \ \/ \| | | - \| O | |_/ |\| \ \__| \_| | O |/ + \| O | |_/ |\| \ \__| \_| | O |/ | | |_/ | | \| / | \_| | | \| / \| | / / \ |/ - | | | / | | - | | | | | | | + | | | / | | + | | | | | | | | | | / / \ \ | | | - \| | / / \ \ | |/ + \| | / / \ \ | |/ \ | / / | | \ \ | / - \ \JUMP 3R | | | | | | R3 PMUJ/ / + \ \JUMP 3R | | | | | | R3 PMUJ/ / \|| | | | | | | | | ||/ \| \_ | | | | | | _/ |/ \ \| / \ / \ |/ / - |/ | | \| + |/ | | \| | | | | | | | | \JUMP3R|JUMP|3R| |R3|PMUJ|R3PMUJ/
    diff --git a/src/BitNode/ui/PortalModal.tsx b/src/BitNode/ui/PortalModal.tsx index 9b5cd560a..9bfaaa589 100644 --- a/src/BitNode/ui/PortalModal.tsx +++ b/src/BitNode/ui/PortalModal.tsx @@ -1,8 +1,7 @@ import React from "react"; +import { enterBitNode } from "../../RedPill"; import { BitNodes } from "../BitNode"; -import { IRouter } from "../../ui/Router"; -import { use } from "../../ui/Context"; import { Modal } from "../../ui/React/Modal"; import Typography from "@mui/material/Typography"; import Button from "@mui/material/Button"; @@ -15,11 +14,9 @@ interface IProps { level: number; destroyedBitNode: number; flume: boolean; - enter: (router: IRouter, flume: boolean, destroyedBitNode: number, newBitNode: number) => void; } export function PortalModal(props: IProps): React.ReactElement { - const router = use.Router(); const bitNodeKey = "BitNode" + props.n; const bitNode = BitNodes[bitNodeKey]; if (bitNode == null) throw new Error(`Could not find BitNode object for number: ${props.n}`); @@ -48,7 +45,7 @@ export function PortalModal(props: IProps): React.ReactElement { aria-label={`enter-bitnode-${bitNode.number.toString()}`} autoFocus={true} onClick={() => { - props.enter(router, props.flume, props.destroyedBitNode, props.n); + enterBitNode(props.flume, props.destroyedBitNode, props.n); props.onClose(); }} > diff --git a/src/Bladeburner/ui/ActionLevel.tsx b/src/Bladeburner/ui/ActionLevel.tsx index 2f4d1ae30..e87a466fe 100644 --- a/src/Bladeburner/ui/ActionLevel.tsx +++ b/src/Bladeburner/ui/ActionLevel.tsx @@ -2,7 +2,6 @@ import React from "react"; import { IAction } from "../IAction"; import { IBladeburner } from "../IBladeburner"; import { BladeburnerConstants } from "../data/Constants"; -import { use } from "../../ui/Context"; import Typography from "@mui/material/Typography"; import Tooltip from "@mui/material/Tooltip"; @@ -19,8 +18,6 @@ interface IProps { } export function ActionLevel({ action, isActive, bladeburner, rerender }: IProps): React.ReactElement { - const player = use.Player(); - const canIncrease = action.level < action.maxLevel; const canDecrease = action.level > 1; diff --git a/src/Bladeburner/ui/BlackOpPage.tsx b/src/Bladeburner/ui/BlackOpPage.tsx index 86061bafc..ecfede4c9 100644 --- a/src/Bladeburner/ui/BlackOpPage.tsx +++ b/src/Bladeburner/ui/BlackOpPage.tsx @@ -3,7 +3,7 @@ import { BlackOpList } from "./BlackOpList"; import { IBladeburner } from "../IBladeburner"; import Typography from "@mui/material/Typography"; import { FactionNames } from "../../Faction/data/FactionNames"; -import { use } from "../../ui/Context"; +import { Router } from "../../ui/GameRoot"; import { BlackOperationNames } from "../data/BlackOperationNames"; import { Button } from "@mui/material"; import { CorruptableText } from "../../ui/React/CorruptableText"; @@ -13,7 +13,6 @@ interface IProps { } export function BlackOpPage(props: IProps): React.ReactElement { - const router = use.Router(); return ( <> @@ -31,7 +30,7 @@ export function BlackOpPage(props: IProps): React.ReactElement { losses. {props.bladeburner.blackops[BlackOperationNames.OperationDaedalus] ? ( - ) : ( diff --git a/src/Bladeburner/ui/BladeburnerCinematic.tsx b/src/Bladeburner/ui/BladeburnerCinematic.tsx index 5be3e1030..8ce17ea5c 100644 --- a/src/Bladeburner/ui/BladeburnerCinematic.tsx +++ b/src/Bladeburner/ui/BladeburnerCinematic.tsx @@ -1,11 +1,10 @@ import React from "react"; import { FactionNames } from "../../Faction/data/FactionNames"; -import { use } from "../../ui/Context"; +import { Router } from "../../ui/GameRoot"; import { CinematicText } from "../../ui/React/CinematicText"; import { dialogBoxCreate } from "../../ui/React/DialogBox"; export function BladeburnerCinematic(): React.ReactElement { - const router = use.Router(); return ( { - router.toTerminal(); + Router.toTerminal(); dialogBoxCreate( `Visit the National Security Agency (NSA) to apply for their ${FactionNames.Bladeburners} ` + "division! You will need 100 of each combat stat before doing this.", diff --git a/src/Bladeburner/ui/BladeburnerRoot.tsx b/src/Bladeburner/ui/BladeburnerRoot.tsx index ca19f4c93..4d9103939 100644 --- a/src/Bladeburner/ui/BladeburnerRoot.tsx +++ b/src/Bladeburner/ui/BladeburnerRoot.tsx @@ -3,12 +3,10 @@ import { Stats } from "./Stats"; import { Console } from "./Console"; import { AllPages } from "./AllPages"; -import { use } from "../../ui/Context"; +import { Player } from "../../Player"; import Box from "@mui/material/Box"; export function BladeburnerRoot(): React.ReactElement { - const player = use.Player(); - const router = use.Router(); const setRerender = useState(false)[1]; function rerender(): void { setRerender((old) => !old); @@ -19,8 +17,8 @@ export function BladeburnerRoot(): React.ReactElement { return () => clearInterval(id); }, []); - const bladeburner = player.bladeburner; - if (bladeburner === null) return <>; + const bladeburner = Player.bladeburner; + if (!bladeburner) return <>; return ( diff --git a/src/Bladeburner/ui/StartButton.tsx b/src/Bladeburner/ui/StartButton.tsx index 2bbedb947..ce03674f3 100644 --- a/src/Bladeburner/ui/StartButton.tsx +++ b/src/Bladeburner/ui/StartButton.tsx @@ -2,7 +2,7 @@ import React from "react"; import { IBladeburner } from "../IBladeburner"; import { BlackOperation } from "../BlackOperation"; -import { use } from "../../ui/Context"; +import { Player } from "../../Player"; import Button from "@mui/material/Button"; import { AugmentationNames } from "../../Augmentation/data/AugmentationNames"; @@ -13,7 +13,6 @@ interface IProps { rerender: () => void; } export function StartButton(props: IProps): React.ReactElement { - const player = use.Player(); const action = props.bladeburner.getActionObject({ name: props.name, type: props.type }); if (action == null) { throw new Error("Failed to get Operation Object for: " + props.name); @@ -33,7 +32,7 @@ export function StartButton(props: IProps): React.ReactElement { if (disabled) return; props.bladeburner.action.type = props.type; props.bladeburner.action.name = props.name; - if (!player.hasAugmentation(AugmentationNames.BladesSimulacrum, true)) player.finishWork(true); + if (!Player.hasAugmentation(AugmentationNames.BladesSimulacrum, true)) Player.finishWork(true); props.bladeburner.startAction(props.bladeburner.action); props.rerender(); } diff --git a/src/Company/ui/QuitJobModal.tsx b/src/Company/ui/QuitJobModal.tsx index 7ee05b506..0b766c28a 100644 --- a/src/Company/ui/QuitJobModal.tsx +++ b/src/Company/ui/QuitJobModal.tsx @@ -1,6 +1,6 @@ import React from "react"; import { Company } from "../Company"; -import { use } from "../../ui/Context"; +import { Player } from "../../Player"; import { Modal } from "../../ui/React/Modal"; import Typography from "@mui/material/Typography"; import Button from "@mui/material/Button"; @@ -14,9 +14,8 @@ interface IProps { } export function QuitJobModal(props: IProps): React.ReactElement { - const player = use.Player(); function quit(): void { - player.quitJob(props.locName); + Player.quitJob(props.locName); props.onQuit(); props.onClose(); } diff --git a/src/Corporation/ICorporation.ts b/src/Corporation/ICorporation.ts index 4165d48a8..ea71c6cf5 100644 --- a/src/Corporation/ICorporation.ts +++ b/src/Corporation/ICorporation.ts @@ -1,5 +1,4 @@ import { Industry } from "./Industry"; -import { IPlayer } from "../PersonObjects/IPlayer"; import { CorporationUnlockUpgrade } from "./data/CorporationUnlockUpgrades"; import { CorporationUpgrade } from "./data/CorporationUpgrades"; import { CorporationState } from "./CorporationState"; @@ -36,7 +35,7 @@ export interface ICorporation { addFunds(amt: number): void; getState(): string; storeCycles(numCycles: number): void; - process(player: IPlayer): void; + process(): void; determineValuation(): void; determineCycleValuation(): number; getTargetSharePrice(): number; @@ -56,7 +55,7 @@ export interface ICorporation { getEmployeeEffMultiplier(): number; getSalesMultiplier(): number; getScientificResearchMultiplier(): number; - getStarterGuide(player: IPlayer): void; + getStarterGuide(): void; updateDividendTax(): void; getCycleDividends(): number; toJSON(): IReviverValue; diff --git a/src/Corporation/ui/CorporationRoot.tsx b/src/Corporation/ui/CorporationRoot.tsx index bf4766cf0..ba24dbae8 100644 --- a/src/Corporation/ui/CorporationRoot.tsx +++ b/src/Corporation/ui/CorporationRoot.tsx @@ -6,7 +6,7 @@ import { IIndustry } from "../IIndustry"; import { MainPanel } from "./MainPanel"; import { Industries } from "../IndustryData"; import { ExpandIndustryTab } from "./ExpandIndustryTab"; -import { use } from "../../ui/Context"; +import { Player } from "../../Player"; import { Context } from "./Context"; import { Overview } from "./Overview"; @@ -14,8 +14,7 @@ import Tabs from "@mui/material/Tabs"; import Tab from "@mui/material/Tab"; export function CorporationRoot(): React.ReactElement { - const player = use.Player(); - const corporation = player.corporation; + const corporation = Player.corporation; if (corporation === null) return <>; const setRerender = useState(false)[1]; function rerender(): void { diff --git a/src/Corporation/ui/Industry.tsx b/src/Corporation/ui/Industry.tsx index c02643db8..447e3ccbe 100644 --- a/src/Corporation/ui/Industry.tsx +++ b/src/Corporation/ui/Industry.tsx @@ -7,7 +7,6 @@ import { IndustryOverview } from "./IndustryOverview"; import { IndustryWarehouse } from "./IndustryWarehouse"; import { Warehouse } from "../Warehouse"; import { OfficeSpace } from "../OfficeSpace"; -import { use } from "../../ui/Context"; import { useCorporation, useDivision } from "./Context"; import Box from "@mui/material/Box"; @@ -19,7 +18,6 @@ interface IProps { } export function Industry(props: IProps): React.ReactElement { - const player = use.Player(); const corp = useCorporation(); const division = useDivision(); return ( diff --git a/src/Corporation/ui/Overview.tsx b/src/Corporation/ui/Overview.tsx index 1dc811f0c..10fb2f7b3 100644 --- a/src/Corporation/ui/Overview.tsx +++ b/src/Corporation/ui/Overview.tsx @@ -21,7 +21,7 @@ import { convertTimeMsToTimeElapsedString } from "../../utils/StringHelperFuncti import { Money } from "../../ui/React/Money"; import { MoneyRate } from "../../ui/React/MoneyRate"; import { StatsTable } from "../../ui/React/StatsTable"; -import { use } from "../../ui/Context"; +import { Player } from "../../Player"; import { useCorporation } from "./Context"; import Typography from "@mui/material/Typography"; import Tooltip from "@mui/material/Tooltip"; @@ -34,7 +34,6 @@ interface IProps { rerender: () => void; } export function Overview({ rerender }: IProps): React.ReactElement { - const player = use.Player(); const corp = useCorporation(); const profit: number = corp.revenue - corp.expenses; @@ -100,7 +99,7 @@ export function Overview({ rerender }: IProps): React.ReactElement { } > - + {corp.public ? : } @@ -240,12 +239,11 @@ function PublicButtons({ rerender }: IPublicButtonsProps): React.ReactElement { } function BribeButton(): React.ReactElement { - const player = use.Player(); const corp = useCorporation(); const [open, setOpen] = useState(false); const canBribe = corp.valuation >= CorporationConstants.BribeThreshold && - player.factions.filter((f) => Factions[f].getInfo().offersWork()).length > 0; + Player.factions.filter((f) => Factions[f].getInfo().offersWork()).length > 0; function openBribe(): void { if (!canBribe) return; diff --git a/src/Corporation/ui/modals/BribeFactionModal.tsx b/src/Corporation/ui/modals/BribeFactionModal.tsx index 341c56772..7c5668934 100644 --- a/src/Corporation/ui/modals/BribeFactionModal.tsx +++ b/src/Corporation/ui/modals/BribeFactionModal.tsx @@ -4,7 +4,7 @@ import { CorporationConstants } from "../../data/Constants"; import { numeralWrapper } from "../../../ui/numeralFormat"; import { dialogBoxCreate } from "../../../ui/React/DialogBox"; import { Modal } from "../../../ui/React/Modal"; -import { use } from "../../../ui/Context"; +import { Player } from "../../../Player"; import { useCorporation } from "../Context"; import Typography from "@mui/material/Typography"; import Button from "@mui/material/Button"; @@ -19,11 +19,10 @@ interface IProps { } export function BribeFactionModal(props: IProps): React.ReactElement { - const player = use.Player(); - const factions = player.factions.filter((name: string) => { + const factions = Player.factions.filter((name: string) => { const info = Factions[name].getInfo(); if (!info.offersWork()) return false; - if (player.hasGangWith(name)) return false; + if (Player.hasGangWith(name)) return false; return true; }); const corp = useCorporation(); @@ -77,7 +76,7 @@ export function BribeFactionModal(props: IProps): React.ReactElement { {factions.map((name: string) => { const info = Factions[name].getInfo(); if (!info.offersWork()) return; - if (player.hasGangWith(name)) return; + if (Player.hasGangWith(name)) return; return ( {name} diff --git a/src/Corporation/ui/modals/BuybackSharesModal.tsx b/src/Corporation/ui/modals/BuybackSharesModal.tsx index 2e92cdcd9..6083015e7 100644 --- a/src/Corporation/ui/modals/BuybackSharesModal.tsx +++ b/src/Corporation/ui/modals/BuybackSharesModal.tsx @@ -1,7 +1,7 @@ import React, { useState } from "react"; import { Modal } from "../../../ui/React/Modal"; import { numeralWrapper } from "../../../ui/numeralFormat"; -import { use } from "../../../ui/Context"; +import { Player } from "../../../Player"; import { useCorporation } from "../Context"; import Typography from "@mui/material/Typography"; import Button from "@mui/material/Button"; @@ -19,7 +19,6 @@ interface IProps { // Create a popup that lets the player buyback shares // This is created when the player clicks the "Buyback Shares" button in the overview panel export function BuybackSharesModal(props: IProps): React.ReactElement { - const player = use.Player(); const corp = useCorporation(); const [shares, setShares] = useState(NaN); @@ -30,7 +29,7 @@ export function BuybackSharesModal(props: IProps): React.ReactElement { isNaN(shares) || shares <= 0 || shares > corp.issuedShares || - shares * buybackPrice > player.money; + shares * buybackPrice > Player.money; function buy(): void { if (disabled) return; diff --git a/src/Corporation/ui/modals/CreateCorporationModal.tsx b/src/Corporation/ui/modals/CreateCorporationModal.tsx index 9e77fcc14..1b2b1b7a6 100644 --- a/src/Corporation/ui/modals/CreateCorporationModal.tsx +++ b/src/Corporation/ui/modals/CreateCorporationModal.tsx @@ -2,7 +2,8 @@ import React, { useState } from "react"; import { Money } from "../../../ui/React/Money"; import { Modal } from "../../../ui/React/Modal"; -import { use } from "../../../ui/Context"; +import { Router } from "../../../ui/GameRoot"; +import { Player } from "../../../Player"; import Typography from "@mui/material/Typography"; import Button from "@mui/material/Button"; import TextField from "@mui/material/TextField"; @@ -13,10 +14,8 @@ interface IProps { } export function CreateCorporationModal(props: IProps): React.ReactElement { - const player = use.Player(); - const router = use.Router(); - const canSelfFund = player.canAfford(150e9); - if (!player.canAccessCorporation() || player.hasCorporation()) { + const canSelfFund = Player.canAfford(150e9); + if (!Player.canAccessCorporation() || Player.hasCorporation()) { props.onClose(); return <>; } @@ -35,11 +34,11 @@ export function CreateCorporationModal(props: IProps): React.ReactElement { return; } - player.startCorporation(name); - player.loseMoney(150e9, "corporation"); + Player.startCorporation(name); + Player.loseMoney(150e9, "corporation"); props.onClose(); - router.toCorporation(); + Router.toCorporation(); } function seed(): void { @@ -47,17 +46,17 @@ export function CreateCorporationModal(props: IProps): React.ReactElement { return; } - player.startCorporation(name, 500e6); + Player.startCorporation(name, 500e6); props.onClose(); - router.toCorporation(); + Router.toCorporation(); } return ( Would you like to start a corporation? This will require $150b for registration and initial funding.{" "} - {player.bitNodeN === 3 && + {Player.bitNodeN === 3 && `This $150b can either be self-funded, or you can obtain the seed money from the government in exchange for 500 million shares`} @@ -66,7 +65,7 @@ export function CreateCorporationModal(props: IProps): React.ReactElement { If you would like to start one, please enter a name for your corporation below: - {player.bitNodeN === 3 && ( + {Player.bitNodeN === 3 && ( diff --git a/src/Corporation/ui/modals/SellSharesModal.tsx b/src/Corporation/ui/modals/SellSharesModal.tsx index fdb178029..455e6efcd 100644 --- a/src/Corporation/ui/modals/SellSharesModal.tsx +++ b/src/Corporation/ui/modals/SellSharesModal.tsx @@ -2,7 +2,6 @@ import React, { useState } from "react"; import { numeralWrapper } from "../../../ui/numeralFormat"; import { dialogBoxCreate } from "../../../ui/React/DialogBox"; import { Modal } from "../../../ui/React/Modal"; -import { use } from "../../../ui/Context"; import { useCorporation } from "../Context"; import { ICorporation } from "../../ICorporation"; import Typography from "@mui/material/Typography"; @@ -20,7 +19,6 @@ interface IProps { // Create a popup that lets the player sell Corporation shares // This is created when the player clicks the "Sell Shares" button in the overview panel export function SellSharesModal(props: IProps): React.ReactElement { - const player = use.Player(); const corp = useCorporation(); const [shares, setShares] = useState(NaN); diff --git a/src/Crime/Crime.ts b/src/Crime/Crime.ts index 8100d9c0e..8edf124f8 100644 --- a/src/Crime/Crime.ts +++ b/src/Crime/Crime.ts @@ -1,5 +1,5 @@ import { CONSTANTS } from "../Constants"; -import { IPlayer } from "../PersonObjects/IPlayer"; +import { Player } from "../Player"; import { IPerson } from "../PersonObjects/IPerson"; import { WorkerScript } from "../Netscript/WorkerScript"; import { CrimeType } from "../utils/WorkType"; @@ -101,11 +101,11 @@ export class Crime { this.kills = params.kills ? params.kills : 0; } - commit(p: IPlayer, div = 1, workerScript: WorkerScript | null = null): number { + commit(div = 1, workerScript: WorkerScript | null = null): number { if (div <= 0) { div = 1; } - p.startWork( + Player.startWork( new CrimeWork({ crimeType: this.type, singularity: workerScript !== null, diff --git a/src/Exploits/Unclickable.tsx b/src/Exploits/Unclickable.tsx index 1ab524d9e..8e6c5fe9c 100644 --- a/src/Exploits/Unclickable.tsx +++ b/src/Exploits/Unclickable.tsx @@ -1,16 +1,15 @@ import React from "react"; -import { use } from "../ui/Context"; +import { Player } from "../Player"; import { Exploit } from "./Exploit"; const getComputedStyle = window.getComputedStyle; export function Unclickable(): React.ReactElement { - const player = use.Player(); function unclickable(event: React.MouseEvent): void { if (!event.target || !(event.target instanceof Element)) return; const display = getComputedStyle(event.target).display; const visibility = getComputedStyle(event.target).visibility; - if (display === "none" && visibility === "hidden" && event.isTrusted) player.giveExploit(Exploit.Unclickable); + if (display === "none" && visibility === "hidden" && event.isTrusted) Player.giveExploit(Exploit.Unclickable); } return ( diff --git a/src/Faction/FactionInfo.tsx b/src/Faction/FactionInfo.tsx index 96c252fc3..0a63d868d 100644 --- a/src/Faction/FactionInfo.tsx +++ b/src/Faction/FactionInfo.tsx @@ -1,7 +1,7 @@ import React from "react"; import { IMap } from "../types"; import { FactionNames } from "./data/FactionNames"; -import { use } from "../ui/Context"; +import { Router } from "../ui/GameRoot"; import { Option } from "./ui/Option"; import { Typography } from "@mui/material"; @@ -449,12 +449,11 @@ export const FactionInfos: IMap = { special: true, assignment: (): React.ReactElement => { - const router = use.Router(); return (
  • )} - {Player.canAccessGrafting() && - !props.aug.isSpecial && - props.aug.name !== AugmentationNames.TheRedPill && ( -
  • - Grafting -
  • - )} + {Player.canAccessGrafting() && !props.aug.isSpecial && props.aug.name !== AugmentationNames.TheRedPill && ( +
  • + Grafting +
  • + )} @@ -209,8 +207,7 @@ export function PurchasableAugmentation(props: IPurchasableAugProps): React.Reac <> {props.augName} - {props.augName === AugmentationNames.NeuroFluxGovernor && - ` - Level ${aug.getLevel()}`} + {props.augName === AugmentationNames.NeuroFluxGovernor && ` - Level ${aug.getLevel()}`} {description} @@ -223,9 +220,7 @@ export function PurchasableAugmentation(props: IPurchasableAugProps): React.Reac whiteSpace: "nowrap", overflow: "hidden", color: - props.owned || !props.parent.canPurchase(aug) - ? Settings.theme.disabled - : Settings.theme.primary, + props.owned || !props.parent.canPurchase(aug) ? Settings.theme.disabled : Settings.theme.primary, }} > {aug.name} @@ -233,9 +228,7 @@ export function PurchasableAugmentation(props: IPurchasableAugProps): React.Reac - {aug.factions.length === 1 && !props.parent.sleeveAugs && ( - - )} + {aug.factions.length === 1 && !props.parent.sleeveAugs && } {aug.prereqs.length > 0 && !props.parent.sleeveAugs && } diff --git a/src/Bladeburner/IBladeburner.ts b/src/Bladeburner/IBladeburner.ts index 5294de30e..80062b3c2 100644 --- a/src/Bladeburner/IBladeburner.ts +++ b/src/Bladeburner/IBladeburner.ts @@ -120,5 +120,5 @@ export interface IBladeburner { process(): void; getActionStats(action: IAction, person: IPerson, success: boolean): ITaskTracker; sleeveSupport(joining: boolean): void; - toJSON():IReviverValue; + toJSON(): IReviverValue; } diff --git a/src/Casino/Blackjack.tsx b/src/Casino/Blackjack.tsx index 54eb13b85..445d59a7b 100644 --- a/src/Casino/Blackjack.tsx +++ b/src/Casino/Blackjack.tsx @@ -36,7 +36,7 @@ type State = { wagerInvalidHelperText: string; }; -export class Blackjack extends React.Component<{},State> { +export class Blackjack extends React.Component, State> { deck: Deck; constructor() { diff --git a/src/Casino/Game.ts b/src/Casino/Game.ts index 378f4f0cd..1a0d90032 100644 --- a/src/Casino/Game.ts +++ b/src/Casino/Game.ts @@ -13,4 +13,4 @@ export function reachedLimit(): boolean { dialogBoxCreate("Alright cheater get out of here. You're not allowed here anymore."); } return reached; -} \ No newline at end of file +} diff --git a/src/Exploits/Unclickable.tsx b/src/Exploits/Unclickable.tsx index 8e6c5fe9c..b5f9f354a 100644 --- a/src/Exploits/Unclickable.tsx +++ b/src/Exploits/Unclickable.tsx @@ -4,7 +4,6 @@ import { Exploit } from "./Exploit"; const getComputedStyle = window.getComputedStyle; export function Unclickable(): React.ReactElement { - function unclickable(event: React.MouseEvent): void { if (!event.target || !(event.target instanceof Element)) return; const display = getComputedStyle(event.target).display; diff --git a/src/Hacknet/HacknetHelpers.tsx b/src/Hacknet/HacknetHelpers.tsx index d3d710d0e..7dadce022 100644 --- a/src/Hacknet/HacknetHelpers.tsx +++ b/src/Hacknet/HacknetHelpers.tsx @@ -153,10 +153,7 @@ export function getMaxNumberRamUpgrades(nodeObj: HacknetNode | HacknetServer, ma } // Calculate the maximum number of times the Player can afford to upgrade a Hacknet Node's cores -export function getMaxNumberCoreUpgrades( - nodeObj: HacknetNode | HacknetServer, - maxLevel: number, -): number { +export function getMaxNumberCoreUpgrades(nodeObj: HacknetNode | HacknetServer, maxLevel: number): number { if (maxLevel == null) { throw new Error(`getMaxNumberCoreUpgrades() called without maxLevel arg`); } diff --git a/src/Hacknet/ui/HacknetNodeElem.tsx b/src/Hacknet/ui/HacknetNodeElem.tsx index b1074ddc9..818e853cb 100644 --- a/src/Hacknet/ui/HacknetNodeElem.tsx +++ b/src/Hacknet/ui/HacknetNodeElem.tsx @@ -77,9 +77,7 @@ export function HacknetNodeElem(props: IProps): React.ReactElement { } function upgradeLevelOnClick(): void { const numUpgrades = - purchaseMult === "MAX" - ? getMaxNumberLevelUpgrades(node, HacknetNodeConstants.MaxLevel) - : purchaseMult; + purchaseMult === "MAX" ? getMaxNumberLevelUpgrades(node, HacknetNodeConstants.MaxLevel) : purchaseMult; purchaseLevelUpgrade(node, numUpgrades); rerender(); } @@ -128,9 +126,7 @@ export function HacknetNodeElem(props: IProps): React.ReactElement { function upgradeCoresOnClick(): void { const numUpgrades = - purchaseMult === "MAX" - ? getMaxNumberCoreUpgrades(node, HacknetNodeConstants.MaxCores) - : purchaseMult; + purchaseMult === "MAX" ? getMaxNumberCoreUpgrades(node, HacknetNodeConstants.MaxCores) : purchaseMult; purchaseCoreUpgrade(node, numUpgrades); rerender(); } diff --git a/src/Hacknet/ui/HacknetServerElem.tsx b/src/Hacknet/ui/HacknetServerElem.tsx index 2a2a2d7ae..ef97988ef 100644 --- a/src/Hacknet/ui/HacknetServerElem.tsx +++ b/src/Hacknet/ui/HacknetServerElem.tsx @@ -60,13 +60,8 @@ export function HacknetServerElem(props: IProps): React.ReactElement { } const base_increase = - calculateHashGainRate( - node.level + multiplier, - 0, - node.maxRam, - node.cores, - Player.mults.hacknet_node_money, - ) - calculateHashGainRate(node.level, 0, node.maxRam, node.cores, Player.mults.hacknet_node_money); + calculateHashGainRate(node.level + multiplier, 0, node.maxRam, node.cores, Player.mults.hacknet_node_money) - + calculateHashGainRate(node.level, 0, node.maxRam, node.cores, Player.mults.hacknet_node_money); const modded_increase = (base_increase * (node.maxRam - node.ramUsed)) / node.maxRam; const upgradeLevelCost = node.calculateLevelUpgradeCost(multiplier, Player.mults.hacknet_node_level_cost); @@ -136,8 +131,7 @@ export function HacknetServerElem(props: IProps): React.ReactElement { node.maxRam * Math.pow(2, multiplier), node.cores, Player.mults.hacknet_node_money, - ) - - calculateHashGainRate(node.level, node.ramUsed, node.maxRam, node.cores, Player.mults.hacknet_node_money); + ) - calculateHashGainRate(node.level, node.ramUsed, node.maxRam, node.cores, Player.mults.hacknet_node_money); const upgradeRamCost = node.calculateRamUpgradeCost(multiplier, Player.mults.hacknet_node_ram_cost); upgradeRamButton = ( @@ -183,13 +177,8 @@ export function HacknetServerElem(props: IProps): React.ReactElement { } const base_increase = - calculateHashGainRate( - node.level, - 0, - node.maxRam, - node.cores + multiplier, - Player.mults.hacknet_node_money, - ) - calculateHashGainRate(node.level, 0, node.maxRam, node.cores, Player.mults.hacknet_node_money); + calculateHashGainRate(node.level, 0, node.maxRam, node.cores + multiplier, Player.mults.hacknet_node_money) - + calculateHashGainRate(node.level, 0, node.maxRam, node.cores, Player.mults.hacknet_node_money); const modded_increase = (base_increase * (node.maxRam - node.ramUsed)) / node.maxRam; const upgradeCoreCost = node.calculateCoreUpgradeCost(multiplier, Player.mults.hacknet_node_core_cost); diff --git a/src/Infiltration/ui/InfiltrationRoot.tsx b/src/Infiltration/ui/InfiltrationRoot.tsx index 5f86ea28b..30baf09ce 100644 --- a/src/Infiltration/ui/InfiltrationRoot.tsx +++ b/src/Infiltration/ui/InfiltrationRoot.tsx @@ -18,7 +18,7 @@ export function InfiltrationRoot(props: IProps): React.ReactElement { const reward = calculateReward(Player, startingSecurityLevel); function cancel(): void { - Router.toCity(); + Router.toCity(); } return ( diff --git a/src/Locations/ui/HospitalLocation.tsx b/src/Locations/ui/HospitalLocation.tsx index aabf4ae49..9467120f8 100644 --- a/src/Locations/ui/HospitalLocation.tsx +++ b/src/Locations/ui/HospitalLocation.tsx @@ -13,20 +13,18 @@ import { Money } from "../../ui/React/Money"; import { dialogBoxCreate } from "../../ui/React/DialogBox"; -type IProps = {}; - type IState = { currHp: number; }; -export class HospitalLocation extends React.Component { +export class HospitalLocation extends React.Component, IState> { /** * Stores button styling that sets them all to block display */ btnStyle = { display: "block" }; - constructor(props: IProps) { - super(props); + constructor() { + super({}); this.getCost = this.getCost.bind(this); this.getHealed = this.getHealed.bind(this); diff --git a/src/Locations/ui/TorButton.tsx b/src/Locations/ui/TorButton.tsx index aee55eb67..80e69671f 100644 --- a/src/Locations/ui/TorButton.tsx +++ b/src/Locations/ui/TorButton.tsx @@ -5,7 +5,6 @@ import { dialogBoxCreate } from "../../ui/React/DialogBox"; import { GetServer } from "../../Server/AllServers"; import { SpecialServers } from "../../Server/data/SpecialServers"; - import { CONSTANTS } from "../../Constants"; import { Player } from "../../Player"; @@ -14,7 +13,7 @@ import { Money } from "../../ui/React/Money"; /** * Attempt to purchase a TOR router using the button. */ - export function purchaseTorRouter(): void { +export function purchaseTorRouter(): void { if (Player.hasTorRouter()) { dialogBoxCreate(`You already have a TOR Router!`); return; diff --git a/src/PersonObjects/Grafting/ui/GraftingRoot.tsx b/src/PersonObjects/Grafting/ui/GraftingRoot.tsx index b2d106eef..07adf4e3c 100644 --- a/src/PersonObjects/Grafting/ui/GraftingRoot.tsx +++ b/src/PersonObjects/Grafting/ui/GraftingRoot.tsx @@ -124,9 +124,7 @@ export const GraftingRoot = (): React.ReactElement => { setSelectedAug(k)} selected={selectedAug === k}> {k} diff --git a/src/PersonObjects/Sleeve/Work/SleeveClassWork.ts b/src/PersonObjects/Sleeve/Work/SleeveClassWork.ts index 8d8213c6f..1b59b78fb 100644 --- a/src/PersonObjects/Sleeve/Work/SleeveClassWork.ts +++ b/src/PersonObjects/Sleeve/Work/SleeveClassWork.ts @@ -1,4 +1,3 @@ -import { IPlayer } from "../../IPlayer"; import { Generic_fromJSON, Generic_toJSON, IReviverValue, Reviver } from "../../../utils/JSONReviver"; import { applySleeveGains, Work, WorkType } from "./Work"; import { ClassType } from "../../../Work/ClassWork"; @@ -25,11 +24,7 @@ export class SleeveClassWork extends Work { } calculateRates(sleeve: Sleeve): WorkStats { - return scaleWorkStats( - calculateClassEarnings(sleeve, this.classType, this.location), - sleeve.shockBonus(), - false, - ); + return scaleWorkStats(calculateClassEarnings(sleeve, this.classType, this.location), sleeve.shockBonus(), false); } isGym(): boolean { diff --git a/src/PersonObjects/Sleeve/Work/SleeveCompanyWork.ts b/src/PersonObjects/Sleeve/Work/SleeveCompanyWork.ts index 795f3d451..a3a53e5a3 100644 --- a/src/PersonObjects/Sleeve/Work/SleeveCompanyWork.ts +++ b/src/PersonObjects/Sleeve/Work/SleeveCompanyWork.ts @@ -1,4 +1,3 @@ -import { IPlayer } from "../../IPlayer"; import { Generic_fromJSON, Generic_toJSON, IReviverValue, Reviver } from "../../../utils/JSONReviver"; import { Sleeve } from "../Sleeve"; import { applySleeveGains, Work, WorkType } from "./Work"; diff --git a/src/PersonObjects/Sleeve/ui/SleeveElem.tsx b/src/PersonObjects/Sleeve/ui/SleeveElem.tsx index 4d76044c9..a54ed2e3d 100644 --- a/src/PersonObjects/Sleeve/ui/SleeveElem.tsx +++ b/src/PersonObjects/Sleeve/ui/SleeveElem.tsx @@ -200,9 +200,7 @@ export function SleeveElem(props: IProps): React.ReactElement { diff --git a/src/PersonObjects/Sleeve/ui/TaskSelector.tsx b/src/PersonObjects/Sleeve/ui/TaskSelector.tsx index e6dde19ad..497bccaad 100644 --- a/src/PersonObjects/Sleeve/ui/TaskSelector.tsx +++ b/src/PersonObjects/Sleeve/ui/TaskSelector.tsx @@ -243,8 +243,7 @@ const canDo: { "Commit Crime": () => true, "Take University Course": (sleeve: Sleeve) => [CityName.Aevum, CityName.Sector12, CityName.Volhaven].includes(sleeve.city), - "Workout at Gym": (sleeve: Sleeve) => - [CityName.Aevum, CityName.Sector12, CityName.Volhaven].includes(sleeve.city), + "Workout at Gym": (sleeve: Sleeve) => [CityName.Aevum, CityName.Sector12, CityName.Volhaven].includes(sleeve.city), "Perform Bladeburner Actions": () => Player.inBladeburner(), "Shock Recovery": (sleeve: Sleeve) => sleeve.shock < 100, Synchronize: (sleeve: Sleeve) => sleeve.sync < 100, @@ -343,9 +342,7 @@ export function TaskSelector(props: IProps): React.ReactElement { const [s1, setS1] = useState(abc[1]); const [s2, setS2] = useState(abc[2]); - const validActions = Object.keys(canDo).filter((k) => - (canDo[k] as (sleeve: Sleeve) => boolean)(props.sleeve), - ); + const validActions = Object.keys(canDo).filter((k) => (canDo[k] as (sleeve: Sleeve) => boolean)(props.sleeve)); const detailsF = tasks[s0]; if (detailsF === undefined) throw new Error(`No function for task '${s0}'`); diff --git a/src/Prestige.ts b/src/Prestige.ts index 1c919d549..45ea6f26a 100755 --- a/src/Prestige.ts +++ b/src/Prestige.ts @@ -14,7 +14,6 @@ import { joinFaction } from "./Faction/FactionHelpers"; import { updateHashManagerCapacity } from "./Hacknet/HacknetHelpers"; import { prestigeWorkerScripts } from "./NetscriptWorker"; import { Player } from "./Player"; -import { Router } from "./ui/GameRoot"; import { recentScripts } from "./Netscript/RecentScripts"; import { resetPidCounter } from "./Netscript/Pid"; import { LiteratureNames } from "./Literature/data/LiteratureNames"; diff --git a/src/Programs/Program.ts b/src/Programs/Program.ts index e05ecff3a..6480eff48 100644 --- a/src/Programs/Program.ts +++ b/src/Programs/Program.ts @@ -12,11 +12,7 @@ export class Program { create: IProgramCreate | null; run: (args: string[], server: BaseServer) => void; - constructor( - name: string, - create: IProgramCreate | null, - run: (args: string[], server: BaseServer) => void, - ) { + constructor(name: string, create: IProgramCreate | null, run: (args: string[], server: BaseServer) => void) { this.name = name; this.create = create; this.run = run; diff --git a/src/Programs/data/ProgramsMetadata.ts b/src/Programs/data/ProgramsMetadata.ts index a0369c569..50e1c9597 100644 --- a/src/Programs/data/ProgramsMetadata.ts +++ b/src/Programs/data/ProgramsMetadata.ts @@ -41,7 +41,7 @@ export const programsMetadata: IProgramCreationParams[] = [ req: requireHackingLevel(1), time: CONSTANTS.MillisecondsPerFiveMinutes, }, - run: (_args:string[], server: BaseServer): void => { + run: (_args: string[], server: BaseServer): void => { if (!(server instanceof Server)) { Terminal.error("Cannot nuke this kind of server."); return; @@ -70,7 +70,7 @@ export const programsMetadata: IProgramCreationParams[] = [ req: requireHackingLevel(50), time: CONSTANTS.MillisecondsPerFiveMinutes * 2, }, - run: (_args:string[], server: BaseServer): void => { + run: (_args: string[], server: BaseServer): void => { if (!(server instanceof Server)) { Terminal.error("Cannot run BruteSSH.exe on this kind of server."); return; @@ -94,7 +94,7 @@ export const programsMetadata: IProgramCreationParams[] = [ req: requireHackingLevel(100), time: CONSTANTS.MillisecondsPerHalfHour, }, - run: (_args:string[], server: BaseServer): void => { + run: (_args: string[], server: BaseServer): void => { if (!(server instanceof Server)) { Terminal.error("Cannot run FTPCrack.exe on this kind of server."); return; @@ -118,7 +118,7 @@ export const programsMetadata: IProgramCreationParams[] = [ req: requireHackingLevel(250), time: CONSTANTS.MillisecondsPer2Hours, }, - run: (_args:string[], server: BaseServer): void => { + run: (_args: string[], server: BaseServer): void => { if (!(server instanceof Server)) { Terminal.error("Cannot run relaySMTP.exe on this kind of server."); return; @@ -142,7 +142,7 @@ export const programsMetadata: IProgramCreationParams[] = [ req: requireHackingLevel(500), time: CONSTANTS.MillisecondsPer4Hours, }, - run: (_args:string[], server: BaseServer): void => { + run: (_args: string[], server: BaseServer): void => { if (!(server instanceof Server)) { Terminal.error("Cannot run HTTPWorm.exe on this kind of server."); return; @@ -166,7 +166,7 @@ export const programsMetadata: IProgramCreationParams[] = [ req: requireHackingLevel(750), time: CONSTANTS.MillisecondsPer8Hours, }, - run: (_args:string[], server: BaseServer): void => { + run: (_args: string[], server: BaseServer): void => { if (!(server instanceof Server)) { Terminal.error("Cannot run SQLInject.exe on this kind of server."); return; diff --git a/src/Programs/ui/ProgramsRoot.tsx b/src/Programs/ui/ProgramsRoot.tsx index 767d6dda5..a834d4509 100644 --- a/src/Programs/ui/ProgramsRoot.tsx +++ b/src/Programs/ui/ProgramsRoot.tsx @@ -97,9 +97,7 @@ export function ProgramsRoot(): React.ReactElement { sx={{ my: 1, width: "100%" }} onClick={(event) => { if (!event.isTrusted) return; - Player.startWork( - new CreateProgramWork({singularity: false, programName: program.name }), - ); + Player.startWork(new CreateProgramWork({ singularity: false, programName: program.name })); Player.startFocusing(); Router.toWork(); }} diff --git a/src/ScriptEditor/ui/ScriptEditorRoot.tsx b/src/ScriptEditor/ui/ScriptEditorRoot.tsx index fc9367b63..9abec1208 100644 --- a/src/ScriptEditor/ui/ScriptEditorRoot.tsx +++ b/src/ScriptEditor/ui/ScriptEditorRoot.tsx @@ -463,12 +463,7 @@ export function Root(props: IProps): React.ReactElement { //If the current script already exists on the server, overwrite it for (let i = 0; i < server.scripts.length; i++) { if (scriptToSave.fileName == server.scripts[i].filename) { - server.scripts[i].saveScript( - scriptToSave.fileName, - scriptToSave.code, - Player.currentServer, - server.scripts, - ); + server.scripts[i].saveScript(scriptToSave.fileName, scriptToSave.code, Player.currentServer, server.scripts); if (Settings.SaveGameOnFileSave) saveObject.saveGame(); Router.toTerminal(); return; diff --git a/src/Sidebar/ui/SidebarRoot.tsx b/src/Sidebar/ui/SidebarRoot.tsx index ebef6ceb5..00fbc4240 100644 --- a/src/Sidebar/ui/SidebarRoot.tsx +++ b/src/Sidebar/ui/SidebarRoot.tsx @@ -151,9 +151,7 @@ export function SidebarRoot(props: IProps): React.ReactElement { Player.sourceFiles.length > 0; const canOpenAugmentations = - Player.augmentations.length > 0 || - Player.queuedAugmentations.length > 0 || - Player.sourceFiles.length > 0; + Player.augmentations.length > 0 || Player.queuedAugmentations.length > 0 || Player.sourceFiles.length > 0; const canOpenSleeves = Player.sleeves.length > 0; diff --git a/src/Terminal/Terminal.ts b/src/Terminal/Terminal.ts index e183eb19e..4cfe7517e 100644 --- a/src/Terminal/Terminal.ts +++ b/src/Terminal/Terminal.ts @@ -784,10 +784,7 @@ export class Terminal implements ITerminal { } const commands: { - [key: string]: ( - args: (string | number | boolean)[], - server: BaseServer, - ) => void; + [key: string]: (args: (string | number | boolean)[], server: BaseServer) => void; } = { "scan-analyze": scananalyze, alias: alias, diff --git a/src/Terminal/commands/cp.ts b/src/Terminal/commands/cp.ts index 1038cd6f7..f4a91cdfa 100644 --- a/src/Terminal/commands/cp.ts +++ b/src/Terminal/commands/cp.ts @@ -3,10 +3,7 @@ import { BaseServer } from "../../Server/BaseServer"; import { isScriptFilename } from "../../Script/isScriptFilename"; import { getDestinationFilepath, areFilesEqual } from "../DirectoryHelpers"; -export function cp( - args: (string | number | boolean)[], - server: BaseServer, -): void { +export function cp(args: (string | number | boolean)[], server: BaseServer): void { try { if (args.length !== 2) { Terminal.error("Incorrect usage of cp command. Usage: cp [src] [dst]"); diff --git a/src/Terminal/commands/grow.ts b/src/Terminal/commands/grow.ts index a87cd1847..a837a6ef6 100644 --- a/src/Terminal/commands/grow.ts +++ b/src/Terminal/commands/grow.ts @@ -3,10 +3,7 @@ import { Player } from "../../Player"; import { BaseServer } from "../../Server/BaseServer"; import { Server } from "../../Server/Server"; -export function grow( - args: (string | number | boolean)[], - server: BaseServer, -): void { +export function grow(args: (string | number | boolean)[], server: BaseServer): void { if (args.length !== 0) { Terminal.error("Incorrect usage of grow command. Usage: grow"); return; diff --git a/src/Terminal/commands/hack.ts b/src/Terminal/commands/hack.ts index 039ad6461..8866579bf 100644 --- a/src/Terminal/commands/hack.ts +++ b/src/Terminal/commands/hack.ts @@ -3,10 +3,7 @@ import { Player } from "../../Player"; import { BaseServer } from "../../Server/BaseServer"; import { Server } from "../../Server/Server"; -export function hack( - args: (string | number | boolean)[], - server: BaseServer, -): void { +export function hack(args: (string | number | boolean)[], server: BaseServer): void { if (args.length !== 0) { Terminal.error("Incorrect usage of hack command. Usage: hack"); return; diff --git a/src/Terminal/commands/home.ts b/src/Terminal/commands/home.ts index d26f44ef0..964d6f8b0 100644 --- a/src/Terminal/commands/home.ts +++ b/src/Terminal/commands/home.ts @@ -1,9 +1,7 @@ import { Terminal } from "../../Terminal"; import { Player } from "../../Player"; -export function home( - args: (string | number | boolean)[], -): void { +export function home(args: (string | number | boolean)[]): void { if (args.length !== 0) { Terminal.error("Incorrect usage of home command. Usage: home"); return; diff --git a/src/Terminal/commands/run.ts b/src/Terminal/commands/run.ts index b551d1453..dc35f649c 100644 --- a/src/Terminal/commands/run.ts +++ b/src/Terminal/commands/run.ts @@ -4,10 +4,7 @@ import { isScriptFilename } from "../../Script/isScriptFilename"; import { runScript } from "./runScript"; import { runProgram } from "./runProgram"; -export function run( - args: (string | number | boolean)[], - server: BaseServer, -): void { +export function run(args: (string | number | boolean)[], server: BaseServer): void { // Run a program or a script if (args.length < 1) { Terminal.error("Incorrect number of arguments. Usage: run [program/script] [-t] [num threads] [arg1] [arg2]..."); diff --git a/src/Terminal/commands/runScript.ts b/src/Terminal/commands/runScript.ts index 90e8b206c..1be4ad974 100644 --- a/src/Terminal/commands/runScript.ts +++ b/src/Terminal/commands/runScript.ts @@ -7,10 +7,7 @@ import { findRunningScript } from "../../Script/ScriptHelpers"; import * as libarg from "arg"; import { numeralWrapper } from "../../ui/numeralFormat"; -export function runScript( - commandArgs: (string | number | boolean)[], - server: BaseServer, -): void { +export function runScript(commandArgs: (string | number | boolean)[], server: BaseServer): void { if (commandArgs.length < 1) { Terminal.error( `Bug encountered with Terminal.runScript(). Command array has a length of less than 1: ${commandArgs}`, diff --git a/src/Terminal/commands/sudov.ts b/src/Terminal/commands/sudov.ts index f80bec452..9fac032c9 100644 --- a/src/Terminal/commands/sudov.ts +++ b/src/Terminal/commands/sudov.ts @@ -1,10 +1,7 @@ import { Terminal } from "../../Terminal"; import { BaseServer } from "../../Server/BaseServer"; -export function sudov( - args: (string | number | boolean)[], - server: BaseServer, -): void { +export function sudov(args: (string | number | boolean)[], server: BaseServer): void { if (args.length !== 0) { Terminal.error("Incorrect number of arguments. Usage: sudov"); return; diff --git a/src/Terminal/commands/top.ts b/src/Terminal/commands/top.ts index a57de4779..ee815d43d 100644 --- a/src/Terminal/commands/top.ts +++ b/src/Terminal/commands/top.ts @@ -3,10 +3,7 @@ import { BaseServer } from "../../Server/BaseServer"; import { getRamUsageFromRunningScript } from "../../Script/RunningScriptHelpers"; import { numeralWrapper } from "../../ui/numeralFormat"; -export function top( - args: (string | number | boolean)[], - server: BaseServer, -): void { +export function top(args: (string | number | boolean)[], server: BaseServer): void { if (args.length !== 0) { Terminal.error("Incorrect usage of top command. Usage: top"); return; diff --git a/src/Terminal/commands/unalias.ts b/src/Terminal/commands/unalias.ts index d2ebd5ada..868e0a00d 100644 --- a/src/Terminal/commands/unalias.ts +++ b/src/Terminal/commands/unalias.ts @@ -1,9 +1,7 @@ import { Terminal } from "../../Terminal"; import { removeAlias } from "../../Alias"; -export function unalias( - args: (string | number | boolean)[], -): void { +export function unalias(args: (string | number | boolean)[]): void { if (args.length !== 1) { Terminal.error("Incorrect usage of unalias name. Usage: unalias [alias]"); return; diff --git a/src/Terminal/commands/wget.ts b/src/Terminal/commands/wget.ts index afdcb0fdd..65a3e99e1 100644 --- a/src/Terminal/commands/wget.ts +++ b/src/Terminal/commands/wget.ts @@ -4,10 +4,7 @@ import { Terminal } from "../../Terminal"; import { BaseServer } from "../../Server/BaseServer"; import { isScriptFilename } from "../../Script/isScriptFilename"; -export function wget( - args: (string | number | boolean)[], - server: BaseServer, -): void { +export function wget(args: (string | number | boolean)[], server: BaseServer): void { if (args.length !== 2) { Terminal.error("Incorrect usage of wget command. Usage: wget [url] [target file]"); return; diff --git a/src/Terminal/ui/TerminalInput.tsx b/src/Terminal/ui/TerminalInput.tsx index c4bc1b85d..05ba2fa4f 100644 --- a/src/Terminal/ui/TerminalInput.tsx +++ b/src/Terminal/ui/TerminalInput.tsx @@ -9,7 +9,6 @@ import TextField from "@mui/material/TextField"; import { KEY, KEYCODE } from "../../utils/helpers/keyCodes"; import { Terminal } from "../../Terminal"; -import { Router } from "../../ui/GameRoot"; import { Player } from "../../Player"; import { determineAllPossibilitiesForTabCompletion } from "../determineAllPossibilitiesForTabCompletion"; import { tabCompletion } from "../tabCompletion"; diff --git a/src/Work/WorkStats.ts b/src/Work/WorkStats.ts index ac3c5f25e..442fbfd1b 100644 --- a/src/Work/WorkStats.ts +++ b/src/Work/WorkStats.ts @@ -68,12 +68,7 @@ export const scaleWorkStats = (w: WorkStats, n: number, scaleMoney = true): Work }; }; -export const applyWorkStats = ( - target: IPerson, - workStats: WorkStats, - cycles: number, - source: string, -): WorkStats => { +export const applyWorkStats = (target: IPerson, workStats: WorkStats, cycles: number, source: string): WorkStats => { const expStats = applyWorkStatsExp(target, workStats, cycles); const gains = { money: workStats.money * cycles, diff --git a/src/Work/formulas/Class.ts b/src/Work/formulas/Class.ts index 46509366b..54ede73fb 100644 --- a/src/Work/formulas/Class.ts +++ b/src/Work/formulas/Class.ts @@ -20,11 +20,7 @@ export function calculateCost(classs: Class, location: Location): number { return classs.earnings.money * location.costMult * discount; } -export function calculateClassEarnings( - person: IPerson, - type: ClassType, - locationName: LocationName, -): WorkStats { +export function calculateClassEarnings(person: IPerson, type: ClassType, locationName: LocationName): WorkStats { //Find cost and exp gain per game cycle const hashManager = Player.hashManager; const classs = Classes[type]; diff --git a/src/ui/React/CharacterOverview.tsx b/src/ui/React/CharacterOverview.tsx index d1b29aaed..bcd2cf565 100644 --- a/src/ui/React/CharacterOverview.tsx +++ b/src/ui/React/CharacterOverview.tsx @@ -21,7 +21,7 @@ import ClearAllIcon from "@mui/icons-material/ClearAll"; import { Settings } from "../../Settings/Settings"; import { Router } from "../GameRoot"; -import { Player } from "../../Player"; +import { Player } from "../../Player"; import { StatsProgressOverviewCell } from "./StatsProgressBar"; import { BitNodeMultipliers } from "../../BitNode/BitNodeMultipliers"; diff --git a/src/ui/React/Money.tsx b/src/ui/React/Money.tsx index 085bf65ad..ddaa11910 100644 --- a/src/ui/React/Money.tsx +++ b/src/ui/React/Money.tsx @@ -22,9 +22,11 @@ interface IProps { } export function Money(props: IProps): React.ReactElement { const classes = useStyles(); - if (props.forPurchase){ - if (typeof props.money !== "number") throw new Error("if value is for a purchase, money should be number, contact dev"); - if (!Player.canAfford(props.money)) return {numeralWrapper.formatMoney(props.money)}; + if (props.forPurchase) { + if (typeof props.money !== "number") + throw new Error("if value is for a purchase, money should be number, contact dev"); + if (!Player.canAfford(props.money)) + return {numeralWrapper.formatMoney(props.money)}; } return ( diff --git a/src/ui/WorkInProgressRoot.tsx b/src/ui/WorkInProgressRoot.tsx index dd518ec6d..d07fc6f40 100644 --- a/src/ui/WorkInProgressRoot.tsx +++ b/src/ui/WorkInProgressRoot.tsx @@ -11,7 +11,7 @@ import { Locations } from "../Locations/Locations"; import { Settings } from "../Settings/Settings"; import { convertTimeMsToTimeElapsedString } from "../utils/StringHelperFunctions"; import { Player } from "../Player"; -import { Router } from "./GameRoot" +import { Router } from "./GameRoot"; import { numeralWrapper } from "./numeralFormat"; import { Money } from "./React/Money"; import { MoneyRate } from "./React/MoneyRate"; From 1ac57d2e486f574b5b9f798d1c0d542d9acf8c63 Mon Sep 17 00:00:00 2001 From: Snarling <84951833+Snarling@users.noreply.github.com> Date: Tue, 13 Sep 2022 13:15:36 -0400 Subject: [PATCH 16/46] Fix use-before-defined import issue --- .../ui/BitnodeMultipliersDescription.tsx | 2 +- src/DarkWeb/DarkWebItems.ts | 35 ++++++++++--------- src/Locations/ui/GenericLocation.tsx | 18 +++++----- src/Locations/ui/HospitalLocation.tsx | 4 +-- src/engine.tsx | 3 ++ 5 files changed, 33 insertions(+), 29 deletions(-) diff --git a/src/BitNode/ui/BitnodeMultipliersDescription.tsx b/src/BitNode/ui/BitnodeMultipliersDescription.tsx index 21225d995..c42dc1a2a 100644 --- a/src/BitNode/ui/BitnodeMultipliersDescription.tsx +++ b/src/BitNode/ui/BitnodeMultipliersDescription.tsx @@ -5,7 +5,7 @@ import { uniqueId } from "lodash"; import React from "react"; import { SpecialServers } from "../../Server/data/SpecialServers"; import { Settings } from "../../Settings/Settings"; -import { Player } from "../../ui/Player"; +import { Player } from "../../Player"; import { StatsRow } from "../../ui/React/StatsRow"; import { defaultMultipliers, getBitNodeMultipliers } from "../BitNode"; import { IBitNodeMultipliers } from "../BitNodeMultipliers"; diff --git a/src/DarkWeb/DarkWebItems.ts b/src/DarkWeb/DarkWebItems.ts index ff9161f9e..c6515d032 100644 --- a/src/DarkWeb/DarkWebItems.ts +++ b/src/DarkWeb/DarkWebItems.ts @@ -2,19 +2,22 @@ import { DarkWebItem } from "./DarkWebItem"; import { IMap } from "../types"; import { Programs } from "../Programs/Programs"; -export const DarkWebItems: IMap = { - BruteSSHProgram: new DarkWebItem(Programs.BruteSSHProgram.name, 500e3, "Opens up SSH Ports."), - FTPCrackProgram: new DarkWebItem(Programs.FTPCrackProgram.name, 1500e3, "Opens up FTP Ports."), - RelaySMTPProgram: new DarkWebItem(Programs.RelaySMTPProgram.name, 5e6, "Opens up SMTP Ports."), - HTTPWormProgram: new DarkWebItem(Programs.HTTPWormProgram.name, 30e6, "Opens up HTTP Ports."), - SQLInjectProgram: new DarkWebItem(Programs.SQLInjectProgram.name, 250e6, "Opens up SQL Ports."), - ServerProfiler: new DarkWebItem( - Programs.ServerProfiler.name, - 500000, - "Displays detailed information about a server.", - ), - DeepscanV1: new DarkWebItem(Programs.DeepscanV1.name, 500000, "Enables 'scan-analyze' with a depth up to 5."), - DeepscanV2: new DarkWebItem(Programs.DeepscanV2.name, 25e6, "Enables 'scan-analyze' with a depth up to 10."), - AutolinkProgram: new DarkWebItem(Programs.AutoLink.name, 1e6, "Enables direct connect via 'scan-analyze'."), - FormulasProgram: new DarkWebItem(Programs.Formulas.name, 5e9, "Unlock access to the formulas API."), -}; +export const DarkWebItems: IMap = {}; +export function initDarkWebItems() { + Object.assign(DarkWebItems, { + BruteSSHProgram: new DarkWebItem(Programs.BruteSSHProgram.name, 500e3, "Opens up SSH Ports."), + FTPCrackProgram: new DarkWebItem(Programs.FTPCrackProgram.name, 1500e3, "Opens up FTP Ports."), + RelaySMTPProgram: new DarkWebItem(Programs.RelaySMTPProgram.name, 5e6, "Opens up SMTP Ports."), + HTTPWormProgram: new DarkWebItem(Programs.HTTPWormProgram.name, 30e6, "Opens up HTTP Ports."), + SQLInjectProgram: new DarkWebItem(Programs.SQLInjectProgram.name, 250e6, "Opens up SQL Ports."), + ServerProfiler: new DarkWebItem( + Programs.ServerProfiler.name, + 500000, + "Displays detailed information about a server.", + ), + DeepscanV1: new DarkWebItem(Programs.DeepscanV1.name, 500000, "Enables 'scan-analyze' with a depth up to 5."), + DeepscanV2: new DarkWebItem(Programs.DeepscanV2.name, 25e6, "Enables 'scan-analyze' with a depth up to 10."), + AutolinkProgram: new DarkWebItem(Programs.AutoLink.name, 1e6, "Enables direct connect via 'scan-analyze'."), + FormulasProgram: new DarkWebItem(Programs.Formulas.name, 5e9, "Unlock access to the formulas API."), + }); +} diff --git a/src/Locations/ui/GenericLocation.tsx b/src/Locations/ui/GenericLocation.tsx index 956dda058..97455a1e3 100644 --- a/src/Locations/ui/GenericLocation.tsx +++ b/src/Locations/ui/GenericLocation.tsx @@ -44,39 +44,39 @@ export function GenericLocation({ loc }: IProps): React.ReactElement { const content: React.ReactNode[] = []; if (loc.types.includes(LocationType.Company)) { - content.push(); + content.push(); } if (loc.types.includes(LocationType.Gym)) { - content.push(); + content.push(); } if (loc.types.includes(LocationType.Hospital)) { - content.push(); + content.push(); } if (loc.types.includes(LocationType.Slums)) { - content.push(); + content.push(); } if (loc.types.includes(LocationType.Special)) { - content.push(); + content.push(); } if (loc.types.includes(LocationType.TechVendor)) { - content.push(); + content.push(); } if (loc.types.includes(LocationType.TravelAgency)) { - content.push(); + content.push(); } if (loc.types.includes(LocationType.University)) { - content.push(); + content.push(); } if (loc.types.includes(LocationType.Casino)) { - content.push(); + content.push(); } return content; diff --git a/src/Locations/ui/HospitalLocation.tsx b/src/Locations/ui/HospitalLocation.tsx index 9467120f8..1268f621a 100644 --- a/src/Locations/ui/HospitalLocation.tsx +++ b/src/Locations/ui/HospitalLocation.tsx @@ -17,6 +17,7 @@ type IState = { currHp: number; }; +//Todo: Make this a functional component export class HospitalLocation extends React.Component, IState> { /** * Stores button styling that sets them all to block display @@ -26,9 +27,6 @@ export class HospitalLocation extends React.Component, ISt constructor() { super({}); - this.getCost = this.getCost.bind(this); - this.getHealed = this.getHealed.bind(this); - this.state = { currHp: Player.hp.current, }; diff --git a/src/engine.tsx b/src/engine.tsx index 03ceac12d..d12e408cf 100644 --- a/src/engine.tsx +++ b/src/engine.tsx @@ -5,6 +5,7 @@ import { convertTimeMsToTimeElapsedString } from "./utils/StringHelperFunctions" import { initAugmentations } from "./Augmentation/AugmentationHelpers"; import { AugmentationNames } from "./Augmentation/data/AugmentationNames"; import { initBitNodeMultipliers } from "./BitNode/BitNode"; +import { initDarkWebItems } from "./DarkWeb/DarkWebItems"; import { Bladeburner } from "./Bladeburner/Bladeburner"; import { generateRandomContract } from "./CodingContractGenerator"; import { initCompanies } from "./Company/Companies"; @@ -241,6 +242,7 @@ const Engine: { ThemeEvents.emit(); initBitNodeMultipliers(); + initDarkWebItems(); initAugmentations(); // Also calls Player.reapplyAllAugmentations() Player.reapplyAllSourceFiles(); if (Player.hasWseAccount) { @@ -398,6 +400,7 @@ const Engine: { initForeignServers(Player.getHomeComputer()); initCompanies(); initFactions(); + initDarkWebItems(); initAugmentations(); // Start interactive tutorial From 88e2cdf09c6f75c4db021e305e156ec3cdba0429 Mon Sep 17 00:00:00 2001 From: Snarling <84951833+Snarling@users.noreply.github.com> Date: Tue, 13 Sep 2022 13:18:09 -0400 Subject: [PATCH 17/46] Remove more execute-on-import code --- src/DarkWeb/DarkWebItems.ts | 3 ++- src/Programs/Programs.ts | 7 ++++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/DarkWeb/DarkWebItems.ts b/src/DarkWeb/DarkWebItems.ts index c6515d032..191540fbf 100644 --- a/src/DarkWeb/DarkWebItems.ts +++ b/src/DarkWeb/DarkWebItems.ts @@ -1,9 +1,10 @@ import { DarkWebItem } from "./DarkWebItem"; import { IMap } from "../types"; -import { Programs } from "../Programs/Programs"; +import { Programs, initPrograms } from "../Programs/Programs"; export const DarkWebItems: IMap = {}; export function initDarkWebItems() { + initPrograms(); Object.assign(DarkWebItems, { BruteSSHProgram: new DarkWebItem(Programs.BruteSSHProgram.name, 500e3, "Opens up SSH Ports."), FTPCrackProgram: new DarkWebItem(Programs.FTPCrackProgram.name, 1500e3, "Opens up FTP Ports."), diff --git a/src/Programs/Programs.ts b/src/Programs/Programs.ts index e17c5c7e0..c6885dbaa 100644 --- a/src/Programs/Programs.ts +++ b/src/Programs/Programs.ts @@ -3,7 +3,8 @@ import { programsMetadata } from "./data/ProgramsMetadata"; import { IMap } from "../types"; export const Programs: IMap = {}; - -for (const params of programsMetadata) { - Programs[params.key] = new Program(params.name, params.create, params.run); +export function initPrograms() { + for (const params of programsMetadata) { + Programs[params.key] = new Program(params.name, params.create, params.run); + } } From dc59a10e19b222c6a977886cd01292031f7bc791 Mon Sep 17 00:00:00 2001 From: Snarling <84951833+Snarling@users.noreply.github.com> Date: Sun, 11 Sep 2022 15:20:25 -0400 Subject: [PATCH 18/46] Fix lit files, reallow html alerts --- .../{LiteratureHelpers.ts => LiteratureHelpers.tsx} | 3 ++- src/NetscriptFunctions.ts | 2 +- src/ui/React/DialogBox.tsx | 12 ++++++++++-- 3 files changed, 13 insertions(+), 4 deletions(-) rename src/Literature/{LiteratureHelpers.ts => LiteratureHelpers.tsx} (83%) diff --git a/src/Literature/LiteratureHelpers.ts b/src/Literature/LiteratureHelpers.tsx similarity index 83% rename from src/Literature/LiteratureHelpers.ts rename to src/Literature/LiteratureHelpers.tsx index 0eecc2551..e2dad5a8d 100644 --- a/src/Literature/LiteratureHelpers.ts +++ b/src/Literature/LiteratureHelpers.tsx @@ -1,3 +1,4 @@ +import React from "react"; import { Literatures } from "./Literatures"; import { dialogBoxCreate } from "../ui/React/DialogBox"; @@ -7,5 +8,5 @@ export function showLiterature(fn: string): void { return; } const txt = `${litObj.title}

    ${litObj.txt}`; - dialogBoxCreate(txt); + dialogBoxCreate(txt, true); } diff --git a/src/NetscriptFunctions.ts b/src/NetscriptFunctions.ts index fa22e8fef..62bd40e35 100644 --- a/src/NetscriptFunctions.ts +++ b/src/NetscriptFunctions.ts @@ -1778,7 +1778,7 @@ const base: InternalAPI = { (ctx: NetscriptContext) => (_message: unknown): void => { const message = helpers.string(ctx, "message", _message); - dialogBoxCreate(message); + dialogBoxCreate(message, true); }, toast: (ctx: NetscriptContext) => diff --git a/src/ui/React/DialogBox.tsx b/src/ui/React/DialogBox.tsx index 3d32dbe9b..be44d0c45 100644 --- a/src/ui/React/DialogBox.tsx +++ b/src/ui/React/DialogBox.tsx @@ -3,6 +3,14 @@ import { AlertEvents } from "./AlertManager"; import React from "react"; import { Typography } from "@mui/material"; -export function dialogBoxCreate(txt: string | JSX.Element): void { - AlertEvents.emit(typeof txt === "string" ? {txt} : txt); +export function dialogBoxCreate(txt: string | JSX.Element, html = false): void { + AlertEvents.emit( + typeof txt !== "string" ? ( + txt + ) : html ? ( +
    + ) : ( + {txt} + ), + ); } From c864fd7edfd8a1302235e67fccf09610fbf05cad Mon Sep 17 00:00:00 2001 From: Snarling <84951833+Snarling@users.noreply.github.com> Date: Tue, 13 Sep 2022 13:28:18 -0400 Subject: [PATCH 19/46] revert unnecessary file rename --- src/Literature/{LiteratureHelpers.tsx => LiteratureHelpers.ts} | 1 - 1 file changed, 1 deletion(-) rename src/Literature/{LiteratureHelpers.tsx => LiteratureHelpers.ts} (92%) diff --git a/src/Literature/LiteratureHelpers.tsx b/src/Literature/LiteratureHelpers.ts similarity index 92% rename from src/Literature/LiteratureHelpers.tsx rename to src/Literature/LiteratureHelpers.ts index e2dad5a8d..b059d829e 100644 --- a/src/Literature/LiteratureHelpers.tsx +++ b/src/Literature/LiteratureHelpers.ts @@ -1,4 +1,3 @@ -import React from "react"; import { Literatures } from "./Literatures"; import { dialogBoxCreate } from "../ui/React/DialogBox"; From 21a2d49de7499e69345b077464fd81069ddb031e Mon Sep 17 00:00:00 2001 From: Snarling <84951833+Snarling@users.noreply.github.com> Date: Sat, 17 Sep 2022 21:09:15 -0400 Subject: [PATCH 20/46] Finish removing player passing --- src/CotMG/IStaneksGift.ts | 5 +- src/CotMG/StaneksGift.ts | 23 +++-- src/Gang/Gang.ts | 12 +-- src/Gang/IGang.ts | 5 +- src/Infiltration/formulas/game.ts | 34 +++---- src/Infiltration/formulas/victory.ts | 24 ++--- src/Infiltration/ui/InfiltrationRoot.tsx | 5 +- src/Infiltration/ui/Victory.tsx | 6 +- src/Milestones/Milestone.ts | 4 +- src/Milestones/Milestones.ts | 46 +++++----- src/Milestones/ui/MilestonesRoot.tsx | 5 +- src/Netscript/NetscriptHelpers.ts | 6 +- src/NetscriptFunctions.ts | 6 +- src/NetscriptFunctions/Infiltration.ts | 12 +-- src/NetscriptFunctions/Stanek.ts | 2 +- src/Prestige.ts | 4 +- src/Script/ScriptHelpers.ts | 2 +- src/Server/ServerHelpers.ts | 91 ++----------------- src/Server/formulas/grow.ts | 4 +- src/Terminal/Terminal.ts | 2 +- ...termineAllPossibilitiesForTabCompletion.ts | 7 +- src/Terminal/ui/TerminalInput.tsx | 2 +- src/engine.tsx | 8 +- 23 files changed, 112 insertions(+), 203 deletions(-) diff --git a/src/CotMG/IStaneksGift.ts b/src/CotMG/IStaneksGift.ts index a5a6c8912..9dbc2c329 100644 --- a/src/CotMG/IStaneksGift.ts +++ b/src/CotMG/IStaneksGift.ts @@ -1,14 +1,13 @@ import { ActiveFragment } from "./ActiveFragment"; import { Fragment } from "./Fragment"; -import { IPlayer } from "../PersonObjects/IPlayer"; export interface IStaneksGift { storedCycles: number; fragments: ActiveFragment[]; width(): number; height(): number; - charge(player: IPlayer, fragment: ActiveFragment, threads: number): void; - process(p: IPlayer, n: number): void; + charge(fragment: ActiveFragment, threads: number): void; + process(n: number): void; effect(fragment: ActiveFragment): number; canPlace(x: number, y: number, rotation: number, fragment: Fragment): boolean; place(x: number, y: number, rotation: number, fragment: Fragment): boolean; diff --git a/src/CotMG/StaneksGift.ts b/src/CotMG/StaneksGift.ts index 81425ed1f..2943eee4c 100644 --- a/src/CotMG/StaneksGift.ts +++ b/src/CotMG/StaneksGift.ts @@ -3,7 +3,6 @@ import { Fragment } from "./Fragment"; import { ActiveFragment } from "./ActiveFragment"; import { FragmentType } from "./FragmentType"; import { IStaneksGift } from "./IStaneksGift"; -import { IPlayer } from "../PersonObjects/IPlayer"; import { Factions } from "../Faction/Factions"; import { CalculateEffect } from "./formulas/effect"; import { StaneksGiftEvents } from "./StaneksGiftEvents"; @@ -30,7 +29,7 @@ export class StaneksGift implements IStaneksGift { return Math.max(3, Math.min(Math.floor(this.baseSize() / 2 + 0.6), StanekConstants.MaxSize)); } - charge(player: IPlayer, af: ActiveFragment, threads: number): void { + charge(af: ActiveFragment, threads: number): void { if (threads > af.highestCharge) { af.numCharge = (af.highestCharge * af.numCharge) / threads + 1; af.highestCharge = threads; @@ -39,19 +38,19 @@ export class StaneksGift implements IStaneksGift { } const cotmg = Factions[FactionNames.ChurchOfTheMachineGod]; - cotmg.playerReputation += (player.mults.faction_rep * (Math.pow(threads, 0.95) * (cotmg.favor + 100))) / 1000; + cotmg.playerReputation += (Player.mults.faction_rep * (Math.pow(threads, 0.95) * (cotmg.favor + 100))) / 1000; } inBonus(): boolean { return (this.storedCycles * CONSTANTS._idleSpeed) / 1000 > 1; } - process(p: IPlayer, numCycles = 1): void { - if (!p.hasAugmentation(AugmentationNames.StaneksGift1)) return; + process(numCycles = 1): void { + if (!Player.hasAugmentation(AugmentationNames.StaneksGift1)) return; this.storedCycles += numCycles; this.storedCycles -= 10; this.storedCycles = Math.max(0, this.storedCycles); - this.updateMults(p); + this.updateMults(); StaneksGiftEvents.emit(); } @@ -210,19 +209,19 @@ export class StaneksGift implements IStaneksGift { return mults; } - updateMults(p: IPlayer): void { + updateMults(): void { // applyEntropy also reapplies all augmentations and source files // This wraps up the reset nicely - p.applyEntropy(p.entropy); + Player.applyEntropy(Player.entropy); const mults = this.calculateMults(); - p.mults = mergeMultipliers(p.mults, mults); - p.updateSkillLevels(); - const zoeAmt = p.sleeves.reduce((n, sleeve) => n + (sleeve.hasAugmentation(AugmentationNames.ZOE) ? 1 : 0), 0); + Player.mults = mergeMultipliers(Player.mults, mults); + Player.updateSkillLevels(); + const zoeAmt = Player.sleeves.reduce((n, sleeve) => n + (sleeve.hasAugmentation(AugmentationNames.ZOE) ? 1 : 0), 0); if (zoeAmt === 0) return; // Less powerful for each copy. const scaling = 3 / (zoeAmt + 2); const sleeveMults = scaleMultipliers(mults, scaling); - for (const sleeve of p.sleeves) { + for (const sleeve of Player.sleeves) { if (!sleeve.hasAugmentation(AugmentationNames.ZOE)) continue; sleeve.resetMultipliers(); sleeve.mults = mergeMultipliers(sleeve.mults, sleeveMults); diff --git a/src/Gang/Gang.ts b/src/Gang/Gang.ts index 0ca99b964..1e29d2cd8 100644 --- a/src/Gang/Gang.ts +++ b/src/Gang/Gang.ts @@ -23,7 +23,7 @@ import { AllGangs } from "./AllGangs"; import { GangMember } from "./GangMember"; import { WorkerScript } from "../Netscript/WorkerScript"; -import { IPlayer } from "../PersonObjects/IPlayer"; +import { Player } from "../Player"; import { PowerMultiplier } from "./data/power"; import { IGang } from "./IGang"; @@ -82,7 +82,7 @@ export class Gang implements IGang { return AllGangs[this.facName].territory; } - process(numCycles = 1, player: IPlayer): void { + process(numCycles = 1): void { const CyclesPerSecond = 1000 / CONSTANTS._idleSpeed; if (isNaN(numCycles)) { @@ -95,7 +95,7 @@ export class Gang implements IGang { const cycles = Math.min(this.storedCycles, 5 * CyclesPerSecond); try { - this.processGains(cycles, player); + this.processGains(cycles); this.processExperienceGains(cycles); this.processTerritoryAndPowerGains(cycles); this.storedCycles -= cycles; @@ -104,7 +104,7 @@ export class Gang implements IGang { } } - processGains(numCycles = 1, player: IPlayer): void { + processGains(numCycles = 1): void { // Get gains per cycle let moneyGains = 0; let respectGains = 0; @@ -132,7 +132,7 @@ export class Gang implements IGang { } const favorMult = 1 + fac.favor / 100; - fac.playerReputation += (player.mults.faction_rep * gain * favorMult) / GangConstants.GangRespectToReputationRatio; + fac.playerReputation += (Player.mults.faction_rep * gain * favorMult) / GangConstants.GangRespectToReputationRatio; // Keep track of respect gained per member for (let i = 0; i < this.members.length; ++i) { @@ -148,7 +148,7 @@ export class Gang implements IGang { this.wanted = newWanted; if (this.wanted < 1) this.wanted = 1; } - player.gainMoney(moneyGains * numCycles, "gang"); + Player.gainMoney(moneyGains * numCycles, "gang"); } processTerritoryAndPowerGains(numCycles = 1): void { diff --git a/src/Gang/IGang.ts b/src/Gang/IGang.ts index 6d6400a19..e2037534d 100644 --- a/src/Gang/IGang.ts +++ b/src/Gang/IGang.ts @@ -1,7 +1,6 @@ import { GangMemberUpgrade } from "./GangMemberUpgrade"; import { GangMember } from "./GangMember"; import { WorkerScript } from "../Netscript/WorkerScript"; -import { IPlayer } from "../PersonObjects/IPlayer"; import { IAscensionResult } from "./IAscensionResult"; import { IReviverValue } from "src/utils/JSONReviver"; @@ -28,8 +27,8 @@ export interface IGang { getPower(): number; getTerritory(): number; - process(numCycles: number, player: IPlayer): void; - processGains(numCycles: number, player: IPlayer): void; + process(numCycles: number): void; + processGains(numCycles: number): void; processTerritoryAndPowerGains(numCycles: number): void; processExperienceGains(numCycles: number): void; clash(won: boolean): void; diff --git a/src/Infiltration/formulas/game.ts b/src/Infiltration/formulas/game.ts index e6ab67a54..7cc6599dd 100644 --- a/src/Infiltration/formulas/game.ts +++ b/src/Infiltration/formulas/game.ts @@ -1,30 +1,30 @@ -import { IPlayer } from "../../PersonObjects/IPlayer"; +import { Player } from "../../Player"; import { calculateSkill } from "../../PersonObjects/formulas/skill"; -function calculateRawDiff(player: IPlayer, stats: number, startingDifficulty: number): number { - const difficulty = startingDifficulty - Math.pow(stats, 0.9) / 250 - player.skills.intelligence / 1600; +function calculateRawDiff(stats: number, startingDifficulty: number): number { + const difficulty = startingDifficulty - Math.pow(stats, 0.9) / 250 - Player.skills.intelligence / 1600; if (difficulty < 0) return 0; if (difficulty > 3) return 3; return difficulty; } -export function calculateDifficulty(player: IPlayer, startingSecurityLevel: number): number { +export function calculateDifficulty(startingSecurityLevel: number): number { const totalStats = - player.skills.strength + - player.skills.defense + - player.skills.dexterity + - player.skills.agility + - player.skills.charisma; - return calculateRawDiff(player, totalStats, startingSecurityLevel); + Player.skills.strength + + Player.skills.defense + + Player.skills.dexterity + + Player.skills.agility + + Player.skills.charisma; + return calculateRawDiff(totalStats, startingSecurityLevel); } -export function calculateReward(player: IPlayer, startingSecurityLevel: number): number { +export function calculateReward(startingSecurityLevel: number): number { const xpMult = 10 * 60 * 15; const total = - calculateSkill(player.mults.strength_exp * xpMult, player.mults.strength) + - calculateSkill(player.mults.defense_exp * xpMult, player.mults.defense) + - calculateSkill(player.mults.agility_exp * xpMult, player.mults.agility) + - calculateSkill(player.mults.dexterity_exp * xpMult, player.mults.dexterity) + - calculateSkill(player.mults.charisma_exp * xpMult, player.mults.charisma); - return calculateRawDiff(player, total, startingSecurityLevel); + calculateSkill(Player.mults.strength_exp * xpMult, Player.mults.strength) + + calculateSkill(Player.mults.defense_exp * xpMult, Player.mults.defense) + + calculateSkill(Player.mults.agility_exp * xpMult, Player.mults.agility) + + calculateSkill(Player.mults.dexterity_exp * xpMult, Player.mults.dexterity) + + calculateSkill(Player.mults.charisma_exp * xpMult, Player.mults.charisma); + return calculateRawDiff(total, startingSecurityLevel); } diff --git a/src/Infiltration/formulas/victory.ts b/src/Infiltration/formulas/victory.ts index bbfbc263b..1aa317d1c 100644 --- a/src/Infiltration/formulas/victory.ts +++ b/src/Infiltration/formulas/victory.ts @@ -1,15 +1,10 @@ -import { IPlayer } from "../../PersonObjects/IPlayer"; +import { Player } from "../../Player"; import { BitNodeMultipliers } from "../../BitNode/BitNodeMultipliers"; import { LocationsMetadata } from "../../Locations/data/LocationsMetadata"; import { AugmentationNames } from "../../Augmentation/data/AugmentationNames"; import { Faction } from "../../Faction/Faction"; -export function calculateSellInformationCashReward( - player: IPlayer, - reward: number, - maxLevel: number, - difficulty: number, -): number { +export function calculateSellInformationCashReward(reward: number, maxLevel: number, difficulty: number): number { const levelBonus = maxLevel * Math.pow(1.01, maxLevel); return ( @@ -17,17 +12,12 @@ export function calculateSellInformationCashReward( Math.pow(difficulty, 3) * 3e3 * levelBonus * - (player.hasAugmentation(AugmentationNames.WKSharmonizer, true) ? 1.5 : 1) * + (Player.hasAugmentation(AugmentationNames.WKSharmonizer, true) ? 1.5 : 1) * BitNodeMultipliers.InfiltrationMoney ); } -export function calculateTradeInformationRepReward( - player: IPlayer, - reward: number, - maxLevel: number, - difficulty: number, -): number { +export function calculateTradeInformationRepReward(reward: number, maxLevel: number, difficulty: number): number { const levelBonus = maxLevel * Math.pow(1.01, maxLevel); return ( @@ -35,12 +25,12 @@ export function calculateTradeInformationRepReward( Math.pow(difficulty, 1.2) * 30 * levelBonus * - (player.hasAugmentation(AugmentationNames.WKSharmonizer, true) ? 1.5 : 1) * + (Player.hasAugmentation(AugmentationNames.WKSharmonizer, true) ? 1.5 : 1) * BitNodeMultipliers.InfiltrationRep ); } -export function calculateInfiltratorsRepReward(player: IPlayer, faction: Faction, difficulty: number): number { +export function calculateInfiltratorsRepReward(faction: Faction, difficulty: number): number { const maxStartingSecurityLevel = LocationsMetadata.reduce((acc, data): number => { const startingSecurityLevel = data.infiltrationData?.startingSecurityLevel || 0; return acc > startingSecurityLevel ? acc : startingSecurityLevel; @@ -48,6 +38,6 @@ export function calculateInfiltratorsRepReward(player: IPlayer, faction: Faction const baseRepGain = (difficulty / maxStartingSecurityLevel) * 5000; return ( - baseRepGain * (player.hasAugmentation(AugmentationNames.WKSharmonizer, true) ? 2 : 1) * (1 + faction.favor / 100) + baseRepGain * (Player.hasAugmentation(AugmentationNames.WKSharmonizer, true) ? 2 : 1) * (1 + faction.favor / 100) ); } diff --git a/src/Infiltration/ui/InfiltrationRoot.tsx b/src/Infiltration/ui/InfiltrationRoot.tsx index 30baf09ce..48170d32c 100644 --- a/src/Infiltration/ui/InfiltrationRoot.tsx +++ b/src/Infiltration/ui/InfiltrationRoot.tsx @@ -1,7 +1,6 @@ import React, { useState } from "react"; import { Location } from "../../Locations/Location"; import { Router } from "../../ui/GameRoot"; -import { Player } from "../../Player"; import { calculateDifficulty, calculateReward } from "../formulas/game"; import { Game } from "./Game"; import { Intro } from "./Intro"; @@ -14,8 +13,8 @@ export function InfiltrationRoot(props: IProps): React.ReactElement { if (props.location.infiltrationData === undefined) throw new Error("Trying to do infiltration on invalid location."); const startingSecurityLevel = props.location.infiltrationData.startingSecurityLevel; - const difficulty = calculateDifficulty(Player, startingSecurityLevel); - const reward = calculateReward(Player, startingSecurityLevel); + const difficulty = calculateDifficulty(startingSecurityLevel); + const reward = calculateReward(startingSecurityLevel); function cancel(): void { Router.toCity(); diff --git a/src/Infiltration/ui/Victory.tsx b/src/Infiltration/ui/Victory.tsx index bafb8f9eb..917708ad9 100644 --- a/src/Infiltration/ui/Victory.tsx +++ b/src/Infiltration/ui/Victory.tsx @@ -30,9 +30,9 @@ export function Victory(props: IProps): React.ReactElement { } const soa = Factions[FactionNames.ShadowsOfAnarchy]; - const repGain = calculateTradeInformationRepReward(Player, props.Reward, props.MaxLevel, props.StartingDifficulty); - const moneyGain = calculateSellInformationCashReward(Player, props.Reward, props.MaxLevel, props.StartingDifficulty); - const infiltrationRepGain = calculateInfiltratorsRepReward(Player, soa, props.StartingDifficulty); + const repGain = calculateTradeInformationRepReward(props.Reward, props.MaxLevel, props.StartingDifficulty); + const moneyGain = calculateSellInformationCashReward(props.Reward, props.MaxLevel, props.StartingDifficulty); + const infiltrationRepGain = calculateInfiltratorsRepReward(soa, props.StartingDifficulty); const isMemberOfInfiltrators = Player.factions.includes(FactionNames.ShadowsOfAnarchy); diff --git a/src/Milestones/Milestone.ts b/src/Milestones/Milestone.ts index dd5c0b7e9..641cabe1f 100644 --- a/src/Milestones/Milestone.ts +++ b/src/Milestones/Milestone.ts @@ -1,6 +1,4 @@ -import { IPlayer } from "../PersonObjects/IPlayer"; - export type Milestone = { title: string; - fulfilled: (p: IPlayer) => boolean; + fulfilled: () => boolean; }; diff --git a/src/Milestones/Milestones.ts b/src/Milestones/Milestones.ts index 24df22411..cf9cb9ad4 100644 --- a/src/Milestones/Milestones.ts +++ b/src/Milestones/Milestones.ts @@ -1,16 +1,16 @@ import { Milestone } from "./Milestone"; -import { IPlayer } from "../PersonObjects/IPlayer"; +import { Player } from "../Player"; import { Factions } from "../Faction/Factions"; import { Faction } from "../Faction/Faction"; import { GetServer } from "../Server/AllServers"; import { FactionNames } from "../Faction/data/FactionNames"; import { Server } from "../Server/Server"; -function allFactionAugs(p: IPlayer, f: Faction): boolean { +function allFactionAugs(f: Faction): boolean { const factionAugs = f.augmentations.slice().filter((aug) => aug !== "NeuroFlux Governor"); for (const factionAug of factionAugs) { if ( - !p.augmentations.some((aug) => { + !Player.augmentations.some((aug) => { return aug.name == factionAug; }) ) @@ -38,63 +38,63 @@ export const Milestones: Milestone[] = [ }, { title: "Join the faction hinted at in csec-test.msg", - fulfilled: (p: IPlayer): boolean => { - return p.factions.includes(FactionNames.CyberSec); + fulfilled: (): boolean => { + return Player.factions.includes(FactionNames.CyberSec); }, }, { title: `Install all the Augmentations from ${FactionNames.CyberSec}`, - fulfilled: (p: IPlayer): boolean => { - return allFactionAugs(p, Factions[FactionNames.CyberSec]); + fulfilled: (): boolean => { + return allFactionAugs(Factions[FactionNames.CyberSec]); }, }, { title: "Join the faction hinted at in nitesec-test.msg", - fulfilled: (p: IPlayer): boolean => { - return p.factions.includes(FactionNames.NiteSec); + fulfilled: (): boolean => { + return Player.factions.includes(FactionNames.NiteSec); }, }, { title: `Install all the Augmentations from ${FactionNames.NiteSec}`, - fulfilled: (p: IPlayer): boolean => { - return allFactionAugs(p, Factions[FactionNames.NiteSec]); + fulfilled: (): boolean => { + return allFactionAugs(Factions[FactionNames.NiteSec]); }, }, { title: "Join the faction hinted at in j3.msg", - fulfilled: (p: IPlayer): boolean => { - return p.factions.includes(FactionNames.TheBlackHand); + fulfilled: (): boolean => { + return Player.factions.includes(FactionNames.TheBlackHand); }, }, { title: `Install all the Augmentations from ${FactionNames.TheBlackHand}`, - fulfilled: (p: IPlayer): boolean => { - return allFactionAugs(p, Factions[FactionNames.TheBlackHand]); + fulfilled: (): boolean => { + return allFactionAugs(Factions[FactionNames.TheBlackHand]); }, }, { title: "Join the faction hinted at in 19dfj3l1nd.msg", - fulfilled: (p: IPlayer): boolean => { - return p.factions.includes(FactionNames.BitRunners); + fulfilled: (): boolean => { + return Player.factions.includes(FactionNames.BitRunners); }, }, { title: `Install all the Augmentations from ${FactionNames.BitRunners}`, - fulfilled: (p: IPlayer): boolean => { - return allFactionAugs(p, Factions[FactionNames.BitRunners]); + fulfilled: (): boolean => { + return allFactionAugs(Factions[FactionNames.BitRunners]); }, }, { title: "Complete fl1ght.exe", - fulfilled: (p: IPlayer): boolean => { + fulfilled: (): boolean => { // technically wrong but whatever - return p.factions.includes(FactionNames.Daedalus); + return Player.factions.includes(FactionNames.Daedalus); }, }, { title: `Install the special Augmentation from ${FactionNames.Daedalus}`, - fulfilled: (p: IPlayer): boolean => { - return p.augmentations.some((aug) => aug.name == "The Red Pill"); + fulfilled: (): boolean => { + return Player.augmentations.some((aug) => aug.name == "The Red Pill"); }, }, { diff --git a/src/Milestones/ui/MilestonesRoot.tsx b/src/Milestones/ui/MilestonesRoot.tsx index 7f12d24ea..911830cb8 100644 --- a/src/Milestones/ui/MilestonesRoot.tsx +++ b/src/Milestones/ui/MilestonesRoot.tsx @@ -1,4 +1,3 @@ -import { Player } from "../../Player"; import { Milestones } from "../Milestones"; import { Milestone } from "../Milestone"; import * as React from "react"; @@ -9,7 +8,7 @@ import Box from "@mui/material/Box"; function highestMilestone(milestones: Milestone[]): number { let n = -1; for (let i = 0; i < milestones.length; i++) { - if (milestones[i].fulfilled(Player)) n = i; + if (milestones[i].fulfilled()) n = i; } return n; @@ -21,7 +20,7 @@ export function MilestonesRoot(): JSX.Element { if (i <= n + 1) { return ( - [{milestone.fulfilled(Player) ? "x" : " "}] {milestone.title} + [{milestone.fulfilled() ? "x" : " "}] {milestone.title} ); } diff --git a/src/Netscript/NetscriptHelpers.ts b/src/Netscript/NetscriptHelpers.ts index 3a8c76282..79a2dc2bb 100644 --- a/src/Netscript/NetscriptHelpers.ts +++ b/src/Netscript/NetscriptHelpers.ts @@ -21,7 +21,7 @@ import { CONSTANTS } from "../Constants"; import { influenceStockThroughServerHack } from "../StockMarket/PlayerInfluencing"; import { IPort, NetscriptPort } from "../NetscriptPort"; import { NetscriptPorts } from "../NetscriptWorker"; -import { IPlayer } from "../PersonObjects/IPlayer"; +import { IPerson } from "../PersonObjects/IPerson"; import { FormulaGang } from "../Gang/formulas/formulas"; import { GangMember } from "../Gang/GangMember"; import { GangMemberTask } from "../Gang/GangMemberTask"; @@ -498,7 +498,7 @@ function getValidPort(ctx: NetscriptContext, port: number): IPort { return iport; } -function player(ctx: NetscriptContext, p: unknown): IPlayer { +function player(ctx: NetscriptContext, p: unknown): IPerson { const fakePlayer = { hp: undefined, mults: undefined, @@ -518,7 +518,7 @@ function player(ctx: NetscriptContext, p: unknown): IPlayer { entropy: undefined, }; if (!roughlyIs(fakePlayer, p)) throw makeRuntimeErrorMsg(ctx, `player should be a Player.`, "TYPE"); - return p as IPlayer; + return p as IPerson; } function server(ctx: NetscriptContext, s: unknown): Server { diff --git a/src/NetscriptFunctions.ts b/src/NetscriptFunctions.ts index 62bd40e35..bfdb9a378 100644 --- a/src/NetscriptFunctions.ts +++ b/src/NetscriptFunctions.ts @@ -266,7 +266,7 @@ const base: InternalAPI = { ); return helpers.netscriptDelay(ctx, growTime * 1000).then(function () { const moneyBefore = server.moneyAvailable <= 0 ? 1 : server.moneyAvailable; - processSingleServerGrowth(server, threads, Player, host.cpuCores); + processSingleServerGrowth(server, threads, host.cpuCores); const moneyAfter = server.moneyAvailable; ctx.workerScript.scriptRef.recordGrow(server.hostname, threads); const expGain = calculateHackingExpGain(server, Player) * threads; @@ -304,7 +304,7 @@ const base: InternalAPI = { throw helpers.makeRuntimeErrorMsg(ctx, `Invalid argument: growth must be numeric and >= 1, is ${growth}.`); } - return numCycleForGrowth(server, Number(growth), Player, cores); + return numCycleForGrowth(server, Number(growth), cores); }, growthAnalyzeSecurity: (ctx: NetscriptContext) => @@ -321,7 +321,7 @@ const base: InternalAPI = { } const maxThreadsNeeded = Math.ceil( - numCycleForGrowthCorrected(server, server.moneyMax, server.moneyAvailable, Player, cores), + numCycleForGrowthCorrected(server, server.moneyMax, server.moneyAvailable, cores), ); threads = Math.min(threads, maxThreadsNeeded); diff --git a/src/NetscriptFunctions/Infiltration.ts b/src/NetscriptFunctions/Infiltration.ts index 51325a4ab..620e5a4bf 100644 --- a/src/NetscriptFunctions/Infiltration.ts +++ b/src/NetscriptFunctions/Infiltration.ts @@ -1,5 +1,3 @@ -import { Player as player } from "../Player"; - import { Infiltration as IInfiltration, InfiltrationLocation, @@ -32,15 +30,15 @@ export function NetscriptInfiltration(): InternalAPI { if (location.infiltrationData === undefined) throw helpers.makeRuntimeErrorMsg(ctx, `Location '${location}' does not provide infiltrations.`); const startingSecurityLevel = location.infiltrationData.startingSecurityLevel; - const difficulty = calculateDifficulty(player, startingSecurityLevel); - const reward = calculateReward(player, startingSecurityLevel); + const difficulty = calculateDifficulty(startingSecurityLevel); + const reward = calculateReward(startingSecurityLevel); const maxLevel = location.infiltrationData.maxClearanceLevel; return { location: JSON.parse(JSON.stringify(location)), reward: { - tradeRep: calculateTradeInformationRepReward(player, reward, maxLevel, startingSecurityLevel), - sellCash: calculateSellInformationCashReward(player, reward, maxLevel, startingSecurityLevel), - SoARep: calculateInfiltratorsRepReward(player, Factions[FactionNames.ShadowsOfAnarchy], startingSecurityLevel), + tradeRep: calculateTradeInformationRepReward(reward, maxLevel, startingSecurityLevel), + sellCash: calculateSellInformationCashReward(reward, maxLevel, startingSecurityLevel), + SoARep: calculateInfiltratorsRepReward(Factions[FactionNames.ShadowsOfAnarchy], startingSecurityLevel), }, difficulty: difficulty, }; diff --git a/src/NetscriptFunctions/Stanek.ts b/src/NetscriptFunctions/Stanek.ts index f0753b379..84401dd9d 100644 --- a/src/NetscriptFunctions/Stanek.ts +++ b/src/NetscriptFunctions/Stanek.ts @@ -53,7 +53,7 @@ export function NetscriptStanek(): InternalAPI { //Charge the fragment const time = staneksGift.inBonus() ? 200 : 1000; return helpers.netscriptDelay(ctx, time).then(function () { - staneksGift.charge(player, fragment, ctx.workerScript.scriptRef.threads); + staneksGift.charge(fragment, ctx.workerScript.scriptRef.threads); helpers.log(ctx, () => `Charged fragment with ${ctx.workerScript.scriptRef.threads} threads.`); return Promise.resolve(); }); diff --git a/src/Prestige.ts b/src/Prestige.ts index 45ea6f26a..1ebbf1789 100755 --- a/src/Prestige.ts +++ b/src/Prestige.ts @@ -52,7 +52,7 @@ export function prestigeAugmentation(): void { // Reset home computer (only the programs) and add to AllServers AddToAllServers(homeComp); - prestigeHomeComputer(Player, homeComp); + prestigeHomeComputer(homeComp); if (augmentationExists(AugmentationNames.Neurolink) && Player.hasAugmentation(AugmentationNames.Neurolink, true)) { homeComp.programs.push(Programs.FTPCrackProgram.name); @@ -194,7 +194,7 @@ export function prestigeSourceFile(flume: boolean): void { // Reset home computer (only the programs) and add to AllServers AddToAllServers(homeComp); - prestigeHomeComputer(Player, homeComp); + prestigeHomeComputer(homeComp); // Re-create foreign servers initForeignServers(Player.getHomeComputer()); diff --git a/src/Script/ScriptHelpers.ts b/src/Script/ScriptHelpers.ts index 078634328..2333786a6 100644 --- a/src/Script/ScriptHelpers.ts +++ b/src/Script/ScriptHelpers.ts @@ -43,7 +43,7 @@ export function scriptCalculateOfflineProduction(runningScript: RunningScript): const host = GetServer(runningScript.server); if (host === null) throw new Error("getServer of null key?"); if (!(serv instanceof Server)) throw new Error("trying to grow a non-normal server"); - const growth = processSingleServerGrowth(serv, timesGrown, Player, host.cpuCores); + const growth = processSingleServerGrowth(serv, timesGrown, host.cpuCores); runningScript.log( `'${serv.hostname}' grown by ${numeralWrapper.format(growth * 100 - 100, "0.000000%")} while offline`, ); diff --git a/src/Server/ServerHelpers.ts b/src/Server/ServerHelpers.ts index 979ec91a3..8393f1904 100644 --- a/src/Server/ServerHelpers.ts +++ b/src/Server/ServerHelpers.ts @@ -5,7 +5,7 @@ import { calculateServerGrowth } from "./formulas/grow"; import { BitNodeMultipliers } from "../BitNode/BitNodeMultipliers"; import { CONSTANTS } from "../Constants"; -import { IPlayer } from "../PersonObjects/IPlayer"; +import { Player } from "../Player"; import { Programs } from "../Programs/Programs"; import { LiteratureNames } from "../Literature/data/LiteratureNames"; @@ -48,7 +48,7 @@ export function safetlyCreateUniqueServer(params: IConstructorParams): Server { * @param p - Reference to Player object * @returns Number of "growth cycles" needed */ -export function numCycleForGrowth(server: Server, growth: number, p: IPlayer, cores = 1): number { +export function numCycleForGrowth(server: Server, growth: number, cores = 1): number { let ajdGrowthRate = 1 + (CONSTANTS.ServerBaseGrowthRate - 1) / server.hackDifficulty; if (ajdGrowthRate > CONSTANTS.ServerMaxGrowthRate) { ajdGrowthRate = CONSTANTS.ServerMaxGrowthRate; @@ -60,7 +60,7 @@ export function numCycleForGrowth(server: Server, growth: number, p: IPlayer, co const cycles = Math.log(growth) / (Math.log(ajdGrowthRate) * - p.mults.hacking_grow * + Player.mults.hacking_grow * serverGrowthPercentage * BitNodeMultipliers.ServerGrowthRate * coreBonus); @@ -68,33 +68,6 @@ export function numCycleForGrowth(server: Server, growth: number, p: IPlayer, co return cycles; } -/** - * Replacement function for the above function that accounts for the +$1/thread functionality of grow - * with parameters that are the same (for compatibility), but functionality is slightly different. - * This function can ONLY be used to calculate the threads needed for a given server in its current state, - * and so wouldn't be appropriate to use for formulas.exe or ns.growthAnalyze (as those are meant to - * provide theoretical scenarios, or inverse hack respectively). Players COULD use this function with a - * custom server object with the correct moneyAvailable and moneyMax amounts, combined with a multiplier - * correctly calculated to bring the server to a new moneyAvailable (ie, passing in moneyAvailable 300 and x2 - * when you want the number of threads required to grow that particular server from 300 to 600), and this - * function would pass back the correct number of threads. But the key thing is that it doesn't just - * inverse/undo a hack (since the amount hacked from/to matters, not just the multiplier). - * The above is also a rather unnecessarily obtuse way of thinking about it for a formulas.exe type of - * application, so another function with different parameters is provided for that case below this one. - * Instead this function is meant to hand-off from the old numCycleForGrowth function to the new one - * where used internally for pro-rating or the like. Where you have applied a grow and want to determine - * how many threads were needed for THAT SPECIFIC grow case using a multiplier. - * Ideally, this function, and the original function above will be depreciated to use the methodology - * and inputs of the new function below this one. Even for internal cases (it's actually easier to do so). - * @param server - Server being grown - * @param growth - How much the server money is expected to be multiplied by (e.g. 1.5 for *1.5 / +50%) - * @param p - Reference to Player object - * @returns Number of "growth cycles" needed - */ -export function numCycleForGrowthTransition(server: Server, growth: number, p: IPlayer, cores = 1): number { - return numCycleForGrowthCorrected(server, server.moneyAvailable * growth, server.moneyAvailable, p, cores); -} - /** * This function calculates the number of threads needed to grow a server from one $amount to a higher $amount * (ie, how many threads to grow this server from $200 to $600 for example). Used primarily for a formulas (or possibly growthAnalyze) @@ -104,16 +77,10 @@ export function numCycleForGrowthTransition(server: Server, growth: number, p: I * @param server - Server being grown * @param targetMoney - How much you want the server grown TO (not by), for instance, to grow from 200 to 600, input 600 * @param startMoney - How much you are growing the server from, for instance, to grow from 200 to 600, input 200 - * @param p - Reference to Player object + * @param cores - Number of cores on the host performing grow * @returns Number of "growth cycles" needed */ -export function numCycleForGrowthCorrected( - server: Server, - targetMoney: number, - startMoney: number, - p: IPlayer, - cores = 1, -): number { +export function numCycleForGrowthCorrected(server: Server, targetMoney: number, startMoney: number, cores = 1): number { if (startMoney < 0) { startMoney = 0; } // servers "can't" have less than 0 dollars on them @@ -132,7 +99,7 @@ export function numCycleForGrowthCorrected( const serverGrowthPercentage = server.serverGrowth / 100.0; const coreMultiplier = 1 + (cores - 1) / 16; const threadMultiplier = - serverGrowthPercentage * p.mults.hacking_grow * coreMultiplier * BitNodeMultipliers.ServerGrowthRate; + serverGrowthPercentage * Player.mults.hacking_grow * coreMultiplier * BitNodeMultipliers.ServerGrowthRate; /* To understand what is done below we need to do some math. I hope the explanation is clear enough. * First of, the names will be shortened for ease of manipulation: @@ -241,47 +208,9 @@ export function numCycleForGrowthCorrected( return cca + 1; } -/** - * This function calculates the number of threads needed to grow a server based on a pre-hack money and hackAmt - * (ie, if you're hacking a server with $1e6 moneyAvail for 60%, this function will tell you how many threads to regrow it - * A good replacement for the current ns.growthAnalyze if you want players to have more control/responsibility - * @param server - Server being grown - * @param hackProp - the proportion of money hacked (total, not per thread, like 0.60 for hacking 60% of available money) - * @param prehackMoney - how much money the server had before being hacked (like 200000 for hacking a server that had $200000 on it at time of hacking) - * @param p - Reference to Player object - * @returns Number of "growth cycles" needed to reverse the described hack - */ -export function numCycleForGrowthByHackAmt( - server: Server, - hackProp: number, - prehackMoney: number, - p: IPlayer, - cores = 1, -): number { - if (prehackMoney > server.moneyMax) prehackMoney = server.moneyMax; - const posthackMoney = Math.floor(prehackMoney * Math.min(1, Math.max(0, 1 - hackProp))); - return numCycleForGrowthCorrected(server, prehackMoney, posthackMoney, p, cores); -} - -/** - * This function calculates the number of threads needed to grow a server based on an expected growth multiplier assuming it will max out - * (ie, if you expect to grow a server by 60% to reach maxMoney, this function will tell you how many threads to grow it) - * PROBABLY the best replacement for the current ns.growthAnalyze to maintain existing scripts - * @param server - Server being grown - * @param growth - How much the server is being grown by, as a multiple in DECIMAL form (e.g. 1.5 rather than 50). Infinity is acceptable. - * @param p - Reference to Player object - * @returns Number of "growth cycles" needed - */ -export function numCycleForGrowthByMultiplier(server: Server, growth: number, p: IPlayer, cores = 1): number { - if (growth < 1.0) growth = 1.0; - const targetMoney = server.moneyMax; - const startingMoney = server.moneyMax / growth; - return numCycleForGrowthCorrected(server, targetMoney, startingMoney, p, cores); -} - //Applied server growth for a single server. Returns the percentage growth -export function processSingleServerGrowth(server: Server, threads: number, p: IPlayer, cores = 1): number { - let serverGrowth = calculateServerGrowth(server, threads, p, cores); +export function processSingleServerGrowth(server: Server, threads: number, cores = 1): number { + let serverGrowth = calculateServerGrowth(server, threads, Player, cores); if (serverGrowth < 1) { console.warn("serverGrowth calculated to be less than 1"); serverGrowth = 1; @@ -303,7 +232,7 @@ export function processSingleServerGrowth(server: Server, threads: number, p: IP // if there was any growth at all, increase security if (oldMoneyAvailable !== server.moneyAvailable) { - let usedCycles = numCycleForGrowthCorrected(server, server.moneyAvailable, oldMoneyAvailable, p, cores); + let usedCycles = numCycleForGrowthCorrected(server, server.moneyAvailable, oldMoneyAvailable, cores); // Growing increases server security twice as much as hacking usedCycles = Math.min(Math.max(0, Math.ceil(usedCycles)), threads); server.fortify(2 * CONSTANTS.ServerFortifyAmount * usedCycles); @@ -311,7 +240,7 @@ export function processSingleServerGrowth(server: Server, threads: number, p: IP return server.moneyAvailable / oldMoneyAvailable; } -export function prestigeHomeComputer(player: IPlayer, homeComp: Server): void { +export function prestigeHomeComputer(homeComp: Server): void { const hasBitflume = homeComp.programs.includes(Programs.BitFlume.name); homeComp.programs.length = 0; //Remove programs diff --git a/src/Server/formulas/grow.ts b/src/Server/formulas/grow.ts index 68df5aef3..4ab2fa761 100644 --- a/src/Server/formulas/grow.ts +++ b/src/Server/formulas/grow.ts @@ -1,9 +1,9 @@ import { CONSTANTS } from "../../Constants"; import { Server } from "../Server"; import { BitNodeMultipliers } from "../../BitNode/BitNodeMultipliers"; -import { IPlayer } from "../../PersonObjects/IPlayer"; +import { IPerson } from "../../PersonObjects/IPerson"; -export function calculateServerGrowth(server: Server, threads: number, p: IPlayer, cores = 1): number { +export function calculateServerGrowth(server: Server, threads: number, p: IPerson, cores = 1): number { const numServerGrowthCycles = Math.max(Math.floor(threads), 0); //Get adjusted growth rate, which accounts for server security diff --git a/src/Terminal/Terminal.ts b/src/Terminal/Terminal.ts index 4cfe7517e..61c4a259c 100644 --- a/src/Terminal/Terminal.ts +++ b/src/Terminal/Terminal.ts @@ -250,7 +250,7 @@ export class Terminal implements ITerminal { if (!(server instanceof Server)) throw new Error("server should be normal server"); const expGain = calculateHackingExpGain(server, Player); const oldSec = server.hackDifficulty; - const growth = processSingleServerGrowth(server, 25, Player, server.cpuCores) - 1; + const growth = processSingleServerGrowth(server, 25, server.cpuCores) - 1; const newSec = server.hackDifficulty; Player.gainHackingExp(expGain); diff --git a/src/Terminal/determineAllPossibilitiesForTabCompletion.ts b/src/Terminal/determineAllPossibilitiesForTabCompletion.ts index 54393f894..d1a1fcd87 100644 --- a/src/Terminal/determineAllPossibilitiesForTabCompletion.ts +++ b/src/Terminal/determineAllPossibilitiesForTabCompletion.ts @@ -3,7 +3,7 @@ import { getSubdirectories } from "./DirectoryServerHelpers"; import { Aliases, GlobalAliases, substituteAliases } from "../Alias"; import { DarkWebItems } from "../DarkWeb/DarkWebItems"; -import { IPlayer } from "../PersonObjects/IPlayer"; +import { Player } from "../Player"; import { GetAllServers } from "../Server/AllServers"; import { Server } from "../Server/Server"; import { ParseCommand, ParseCommands } from "./Parser"; @@ -57,7 +57,6 @@ const commands = [ ]; export async function determineAllPossibilitiesForTabCompletion( - p: IPlayer, input: string, index: number, currPath = "", @@ -65,8 +64,8 @@ export async function determineAllPossibilitiesForTabCompletion( input = substituteAliases(input); let allPos: string[] = []; allPos = allPos.concat(Object.keys(GlobalAliases)); - const currServ = p.getCurrentServer(); - const homeComputer = p.getHomeComputer(); + const currServ = Player.getCurrentServer(); + const homeComputer = Player.getHomeComputer(); let parentDirPath = ""; let evaledParentDirPath: string | null = null; diff --git a/src/Terminal/ui/TerminalInput.tsx b/src/Terminal/ui/TerminalInput.tsx index 05ba2fa4f..2e9340e55 100644 --- a/src/Terminal/ui/TerminalInput.tsx +++ b/src/Terminal/ui/TerminalInput.tsx @@ -222,7 +222,7 @@ export function TerminalInput(): React.ReactElement { if (index < -1) { index = 0; } - const allPos = await determineAllPossibilitiesForTabCompletion(Player, copy, index, Terminal.cwd()); + const allPos = await determineAllPossibilitiesForTabCompletion(copy, index, Terminal.cwd()); if (allPos.length == 0) { return; } diff --git a/src/engine.tsx b/src/engine.tsx index d12e408cf..3c66e2c89 100644 --- a/src/engine.tsx +++ b/src/engine.tsx @@ -103,11 +103,11 @@ const Engine: { // Gang, if applicable if (Player.inGang() && Player.gang !== null) { - Player.gang.process(numCycles, Player); + Player.gang.process(numCycles); } // Staneks gift - staneksGift.process(Player, numCycles); + staneksGift.process(numCycles); // Corporation if (Player.corporation instanceof Corporation) { @@ -330,7 +330,7 @@ const Engine: { // Gang progress for BitNode 2 const gang = Player.gang; if (Player.inGang() && gang !== null) { - gang.process(numCyclesOffline, Player); + gang.process(numCyclesOffline); } // Corporation offline progress @@ -343,7 +343,7 @@ const Engine: { Player.bladeburner.storeCycles(numCyclesOffline); } - staneksGift.process(Player, numCyclesOffline); + staneksGift.process(numCyclesOffline); // Sleeves offline progress for (let i = 0; i < Player.sleeves.length; ++i) { From e578bd76814960917e0a76cacb684bb2949d0974 Mon Sep 17 00:00:00 2001 From: Snarling <84951833+Snarling@users.noreply.github.com> Date: Tue, 20 Sep 2022 00:14:17 -0400 Subject: [PATCH 21/46] Remove IPlayer interface Use PlayerObject instead when referring to the type of "The Player." --- src/PersonObjects/IPlayer.ts | 157 ------ src/PersonObjects/Player/PlayerObject.ts | 480 ++++++------------ .../Player/PlayerObjectAugmentationMethods.ts | 6 +- .../Player/PlayerObjectBladeburnerMethods.ts | 8 +- .../Player/PlayerObjectCorporationMethods.ts | 8 +- .../Player/PlayerObjectGangMethods.ts | 16 +- .../Player/PlayerObjectGeneralMethods.ts | 95 ++-- .../Player/PlayerObjectServerMethods.ts | 14 +- .../Player/PlayerObjectWorkMethods.ts | 8 +- 9 files changed, 225 insertions(+), 567 deletions(-) delete mode 100644 src/PersonObjects/IPlayer.ts diff --git a/src/PersonObjects/IPlayer.ts b/src/PersonObjects/IPlayer.ts deleted file mode 100644 index 4070fd0e1..000000000 --- a/src/PersonObjects/IPlayer.ts +++ /dev/null @@ -1,157 +0,0 @@ -/** - * Interface for an object that represents the player (PlayerObject) - * Used because at the time of implementation, the PlayerObject - * cant be converted to TypeScript. - */ -import { Sleeve } from "./Sleeve/Sleeve"; - -import { IMap } from "../types"; - -import { IPlayerOwnedAugmentation } from "../Augmentation/PlayerOwnedAugmentation"; -import { Augmentation } from "../Augmentation/Augmentation"; -import { Company } from "../Company/Company"; -import { CompanyPosition } from "../Company/CompanyPosition"; -import { CityName } from "../Locations/data/CityNames"; -import { Faction } from "../Faction/Faction"; -import { HashManager } from "../Hacknet/HashManager"; -import { HacknetNode } from "../Hacknet/HacknetNode"; -import { LocationName } from "../Locations/data/LocationNames"; -import { Server } from "../Server/Server"; -import { BaseServer } from "../Server/BaseServer"; -import { IPlayerOwnedSourceFile } from "../SourceFile/PlayerOwnedSourceFile"; -import { MoneySourceTracker } from "../utils/MoneySourceTracker"; -import { Exploit } from "../Exploits/Exploit"; -import { ICorporation } from "../Corporation/ICorporation"; -import { IGang } from "../Gang/IGang"; -import { IBladeburner } from "../Bladeburner/IBladeburner"; -import { ICodingContractReward } from "../CodingContracts"; -import { HacknetServer } from "../Hacknet/HacknetServer"; -import { ISkillProgress } from "./formulas/skill"; -import { PlayerAchievement } from "../Achievements/Achievements"; -import { IPerson } from "./IPerson"; -import { Work } from "../Work/Work"; -import { Multipliers } from "./Multipliers"; -import { Skills } from "./Skills"; -import { HP } from "./HP"; - -export interface IPlayer extends IPerson { - bitNodeN: number; - city: CityName; - corporation: ICorporation | null; - gang: IGang | null; - bladeburner: IBladeburner | null; - currentServer: string; - factions: string[]; - factionInvitations: string[]; - hacknetNodes: (HacknetNode | string)[]; // HacknetNode object or IP of Hacknet Server - has4SData: boolean; - has4SDataTixApi: boolean; - hashManager: HashManager; - hasTixApiAccess: boolean; - hasWseAccount: boolean; - jobs: IMap; - karma: number; - numPeopleKilled: number; - location: LocationName; - readonly money: number; - moneySourceA: MoneySourceTracker; - moneySourceB: MoneySourceTracker; - playtimeSinceLastAug: number; - playtimeSinceLastBitnode: number; - purchasedServers: string[]; - queuedAugmentations: IPlayerOwnedAugmentation[]; - scriptProdSinceLastAug: number; - sleeves: Sleeve[]; - sleevesFromCovenant: number; - sourceFiles: IPlayerOwnedSourceFile[]; - exploits: Exploit[]; - achievements: PlayerAchievement[]; - terminalCommandHistory: string[]; - lastUpdate: number; - totalPlaytime: number; - - hp: HP; - skills: Skills; - exp: Skills; - - mults: Multipliers; - - currentWork: Work | null; - focus: boolean; - - entropy: number; - - // Methods - init: () => void; - startWork(w: Work): void; - processWork(cycles: number): void; - finishWork(cancelled: boolean): void; - applyForAgentJob(sing?: boolean): boolean; - applyForBusinessConsultantJob(sing?: boolean): boolean; - applyForBusinessJob(sing?: boolean): boolean; - applyForEmployeeJob(sing?: boolean): boolean; - applyForItJob(sing?: boolean): boolean; - applyForJob(entryPosType: CompanyPosition, sing?: boolean): boolean; - applyForNetworkEngineerJob(sing?: boolean): boolean; - applyForPartTimeEmployeeJob(sing?: boolean): boolean; - applyForPartTimeWaiterJob(sing?: boolean): boolean; - applyForSecurityEngineerJob(sing?: boolean): boolean; - applyForSecurityJob(sing?: boolean): boolean; - applyForSoftwareConsultantJob(sing?: boolean): boolean; - applyForSoftwareJob(sing?: boolean): boolean; - applyForWaiterJob(sing?: boolean): boolean; - canAccessBladeburner(): boolean; - canAccessCorporation(): boolean; - canAccessGang(): boolean; - canAccessGrafting(): boolean; - canAfford(cost: number): boolean; - gainMoney(money: number, source: string): void; - getCurrentServer(): BaseServer; - getGangFaction(): Faction; - getGangName(): string; - getHomeComputer(): Server; - getNextCompanyPosition(company: Company, entryPosType: CompanyPosition): CompanyPosition | null; - getUpgradeHomeRamCost(): number; - getUpgradeHomeCoresCost(): number; - gotoLocation(to: LocationName): boolean; - hasAugmentation(aug: string | Augmentation, installed?: boolean): boolean; - hasCorporation(): boolean; - hasGangWith(facName: string): boolean; - hasTorRouter(): boolean; - hasProgram(program: string): boolean; - inBladeburner(): boolean; - inGang(): boolean; - isAwareOfGang(): boolean; - isQualified(company: Company, position: CompanyPosition): boolean; - loseMoney(money: number, source: string): void; - reapplyAllAugmentations(resetMultipliers?: boolean): void; - reapplyAllSourceFiles(): void; - setMoney(amt: number): void; - startBladeburner(): void; - startCorporation(corpName: string, additionalShares?: number): void; - startFocusing(): void; - startGang(facName: string, isHacking: boolean): void; - travel(to: CityName): boolean; - giveExploit(exploit: Exploit): void; - giveAchievement(achievementId: string): void; - getCasinoWinnings(): number; - quitJob(company: string, sing?: boolean): void; - hasJob(): boolean; - createHacknetServer(): HacknetServer; - queueAugmentation(augmentationName: string): void; - receiveInvite(factionName: string): void; - updateSkillLevels(): void; - gainCodingContractReward(reward: ICodingContractReward, difficulty?: number): string; - stopFocusing(): void; - resetMultipliers(): void; - prestigeAugmentation(): void; - prestigeSourceFile(): void; - calculateSkillProgress(exp: number, mult?: number): ISkillProgress; - hospitalize(): void; - checkForFactionInvitations(): Faction[]; - setBitNodeNumber(n: number): void; - canAccessCotMG(): boolean; - sourceFileLvl(n: number): number; - applyEntropy(stacks?: number): void; - focusPenalty(): number; -} diff --git a/src/PersonObjects/Player/PlayerObject.ts b/src/PersonObjects/Player/PlayerObject.ts index 50e3f4a21..af67f569a 100644 --- a/src/PersonObjects/Player/PlayerObject.ts +++ b/src/PersonObjects/Player/PlayerObject.ts @@ -10,16 +10,8 @@ import { IMap } from "../../types"; import { Sleeve } from "../Sleeve/Sleeve"; import { IPlayerOwnedSourceFile } from "../../SourceFile/PlayerOwnedSourceFile"; import { Exploit } from "../../Exploits/Exploit"; -import { CompanyPosition } from "../../Company/CompanyPosition"; -import { Server } from "../../Server/Server"; -import { BaseServer } from "../../Server/BaseServer"; -import { HacknetServer } from "../../Hacknet/HacknetServer"; -import { Faction } from "../../Faction/Faction"; -import { Company } from "../../Company/Company"; -import { Augmentation } from "../../Augmentation/Augmentation"; -import { ICodingContractReward } from "../../CodingContracts"; -import { IPlayer } from "../IPlayer"; +import { IPerson } from "../IPerson"; import { LocationName } from "../../Locations/data/LocationNames"; import { IPlayerOwnedAugmentation } from "../../Augmentation/PlayerOwnedAugmentation"; import { ICorporation } from "../../Corporation/ICorporation"; @@ -32,257 +24,171 @@ import { CityName } from "../../Locations/data/CityNames"; import { MoneySourceTracker } from "../../utils/MoneySourceTracker"; import { Reviver, Generic_toJSON, Generic_fromJSON, IReviverValue } from "../../utils/JSONReviver"; -import { ISkillProgress } from "../formulas/skill"; import { PlayerAchievement } from "../../Achievements/Achievements"; import { cyrb53 } from "../../utils/StringHelperFunctions"; import { getRandomInt } from "../../utils/helpers/getRandomInt"; -import { ITaskTracker } from "../ITaskTracker"; import { CONSTANTS } from "../../Constants"; import { Work } from "src/Work/Work"; -import { defaultMultipliers, Multipliers } from "../Multipliers"; +import { defaultMultipliers } from "../Multipliers"; import { HP } from "../HP"; import { Skills } from "../Skills"; -export class PlayerObject implements IPlayer { +export class PlayerObject implements IPerson { // Class members - augmentations: IPlayerOwnedAugmentation[]; - bitNodeN: number; - city: CityName; - corporation: ICorporation | null; - gang: IGang | null; - bladeburner: IBladeburner | null; - currentServer: string; - factions: string[]; - factionInvitations: string[]; - hacknetNodes: (HacknetNode | string)[]; // HacknetNode object or IP of Hacknet Server - has4SData: boolean; - has4SDataTixApi: boolean; - hashManager: HashManager; - hasTixApiAccess: boolean; - hasWseAccount: boolean; - jobs: IMap; - init: () => void; - karma: number; - numPeopleKilled: number; - location: LocationName; - money: number; - moneySourceA: MoneySourceTracker; - moneySourceB: MoneySourceTracker; - playtimeSinceLastAug: number; - playtimeSinceLastBitnode: number; - purchasedServers: string[]; - queuedAugmentations: IPlayerOwnedAugmentation[]; - scriptProdSinceLastAug: number; - sleeves: Sleeve[]; - sleevesFromCovenant: number; - sourceFiles: IPlayerOwnedSourceFile[]; - exploits: Exploit[]; - achievements: PlayerAchievement[]; - terminalCommandHistory: string[]; + augmentations: IPlayerOwnedAugmentation[] = []; + bitNodeN = 1; //current bitnode + city = CityName.Sector12; + corporation: ICorporation | null = null; + gang: IGang | null = null; + bladeburner: IBladeburner | null = null; + currentServer = ""; + factions: string[] = []; + factionInvitations: string[] = []; + hacknetNodes: (HacknetNode | string)[] = []; // HacknetNode object or hostname of Hacknet Server + has4SData = false; + has4SDataTixApi = false; + hashManager = new HashManager(); + hasTixApiAccess = false; + hasWseAccount = false; + jobs: IMap = {}; + karma = 0; + numPeopleKilled = 0; + location = LocationName.TravelAgency; + money = 1000 + CONSTANTS.Donations; + moneySourceA = new MoneySourceTracker(); + moneySourceB = new MoneySourceTracker(); + playtimeSinceLastAug = 0; + playtimeSinceLastBitnode = 0; + purchasedServers: string[] = []; + queuedAugmentations: IPlayerOwnedAugmentation[] = []; + scriptProdSinceLastAug = 0; + sleeves: Sleeve[] = []; + sleevesFromCovenant = 0; + sourceFiles: IPlayerOwnedSourceFile[] = []; + exploits: Exploit[] = []; + achievements: PlayerAchievement[] = []; + terminalCommandHistory: string[] = []; identifier: string; - lastUpdate: number; - lastSave: number; - totalPlaytime: number; + lastUpdate = 0; + lastSave = 0; + totalPlaytime = 0; - hp: HP; - skills: Skills; - exp: Skills; + hp: HP = { current: 10, max: 10 }; + skills: Skills = { + hacking: 1, + strength: 1, + defense: 1, + dexterity: 1, + agility: 1, + charisma: 1, + intelligence: 0, + }; + exp: Skills = { + hacking: 0, + strength: 0, + defense: 0, + dexterity: 0, + agility: 0, + charisma: 0, + intelligence: 0, + }; - mults: Multipliers; + mults = defaultMultipliers(); - currentWork: Work | null; - focus: boolean; + currentWork: Work | null = null; + focus = false; - entropy: number; + entropy = 0; // Methods - startWork: (w: Work) => void; - processWork: (cycles: number) => void; - finishWork: (cancelled: boolean) => void; - applyForAgentJob: (sing?: boolean) => boolean; - applyForBusinessConsultantJob: (sing?: boolean) => boolean; - applyForBusinessJob: (sing?: boolean) => boolean; - applyForEmployeeJob: (sing?: boolean) => boolean; - applyForItJob: (sing?: boolean) => boolean; - applyForJob: (entryPosType: CompanyPosition, sing?: boolean) => boolean; - applyForNetworkEngineerJob: (sing?: boolean) => boolean; - applyForPartTimeEmployeeJob: (sing?: boolean) => boolean; - applyForPartTimeWaiterJob: (sing?: boolean) => boolean; - applyForSecurityEngineerJob: (sing?: boolean) => boolean; - applyForSecurityJob: (sing?: boolean) => boolean; - applyForSoftwareConsultantJob: (sing?: boolean) => boolean; - applyForSoftwareJob: (sing?: boolean) => boolean; - applyForWaiterJob: (sing?: boolean) => boolean; - canAccessBladeburner: () => boolean; - canAccessCorporation: () => boolean; - canAccessGang: () => boolean; - canAccessGrafting: () => boolean; - canAfford: (cost: number) => boolean; - gainHackingExp: (exp: number) => void; - gainStrengthExp: (exp: number) => void; - gainDefenseExp: (exp: number) => void; - gainDexterityExp: (exp: number) => void; - gainAgilityExp: (exp: number) => void; - gainCharismaExp: (exp: number) => void; - gainIntelligenceExp: (exp: number) => void; - gainStats: (retValue: ITaskTracker) => void; - gainMoney: (money: number, source: string) => void; - getCurrentServer: () => BaseServer; - getGangFaction: () => Faction; - getGangName: () => string; - getHomeComputer: () => Server; - getNextCompanyPosition: (company: Company, entryPosType: CompanyPosition) => CompanyPosition | null; - getUpgradeHomeRamCost: () => number; - getUpgradeHomeCoresCost: () => number; - gotoLocation: (to: LocationName) => boolean; - hasAugmentation: (aug: string | Augmentation, installed?: boolean) => boolean; - hasCorporation: () => boolean; - hasGangWith: (facName: string) => boolean; - hasTorRouter: () => boolean; - hasProgram: (program: string) => boolean; - inBladeburner: () => boolean; - inGang: () => boolean; - isAwareOfGang: () => boolean; - isQualified: (company: Company, position: CompanyPosition) => boolean; - loseMoney: (money: number, source: string) => void; - reapplyAllAugmentations: (resetMultipliers?: boolean) => void; - reapplyAllSourceFiles: () => void; - regenerateHp: (amt: number) => void; - recordMoneySource: (amt: number, source: string) => void; - setMoney: (amt: number) => void; - startBladeburner: () => void; - startCorporation: (corpName: string, additionalShares?: number) => void; - startFocusing: () => void; - startGang: (facName: string, isHacking: boolean) => void; - takeDamage: (amt: number) => boolean; - travel: (to: CityName) => boolean; - giveExploit: (exploit: Exploit) => void; - giveAchievement: (achievementId: string) => void; - queryStatFromString: (str: string) => number; - getIntelligenceBonus: (weight: number) => number; - getCasinoWinnings: () => number; - quitJob: (company: string, sing?: boolean) => void; - hasJob: () => boolean; - createHacknetServer: () => HacknetServer; - queueAugmentation: (augmentationName: string) => void; - receiveInvite: (factionName: string) => void; - updateSkillLevels: () => void; - gainCodingContractReward: (reward: ICodingContractReward, difficulty?: number) => string; - stopFocusing: () => void; - resetMultipliers: () => void; - prestigeAugmentation: () => void; - prestigeSourceFile: () => void; - calculateSkill: (exp: number, mult?: number) => number; - calculateSkillProgress: (exp: number, mult?: number) => ISkillProgress; - hospitalize: () => void; - checkForFactionInvitations: () => Faction[]; - setBitNodeNumber: (n: number) => void; - canAccessCotMG: () => boolean; - sourceFileLvl: (n: number) => number; - applyEntropy: (stacks?: number) => void; - focusPenalty: () => number; + init = generalMethods.init; + startWork = workMethods.startWork; + processWork = workMethods.processWork; + finishWork = workMethods.finishWork; + applyForSoftwareJob = generalMethods.applyForSoftwareJob; + applyForSoftwareConsultantJob = generalMethods.applyForSoftwareConsultantJob; + applyForItJob = generalMethods.applyForItJob; + applyForSecurityEngineerJob = generalMethods.applyForSecurityEngineerJob; + applyForNetworkEngineerJob = generalMethods.applyForNetworkEngineerJob; + applyForBusinessJob = generalMethods.applyForBusinessJob; + applyForBusinessConsultantJob = generalMethods.applyForBusinessConsultantJob; + applyForSecurityJob = generalMethods.applyForSecurityJob; + applyForAgentJob = generalMethods.applyForAgentJob; + applyForEmployeeJob = generalMethods.applyForEmployeeJob; + applyForPartTimeEmployeeJob = generalMethods.applyForPartTimeEmployeeJob; + applyForWaiterJob = generalMethods.applyForWaiterJob; + applyForPartTimeWaiterJob = generalMethods.applyForPartTimeWaiterJob; + applyForJob = generalMethods.applyForJob; + canAccessBladeburner = bladeburnerMethods.canAccessBladeburner; + canAccessCorporation = corporationMethods.canAccessCorporation; + canAccessGang = gangMethods.canAccessGang; + canAccessGrafting = generalMethods.canAccessGrafting; + canAfford = generalMethods.canAfford; + gainHackingExp = generalMethods.gainHackingExp; + gainStrengthExp = generalMethods.gainStrengthExp; + gainDefenseExp = generalMethods.gainDefenseExp; + gainDexterityExp = generalMethods.gainDexterityExp; + gainAgilityExp = generalMethods.gainAgilityExp; + gainCharismaExp = generalMethods.gainCharismaExp; + gainIntelligenceExp = generalMethods.gainIntelligenceExp; + gainStats = generalMethods.gainStats; + gainMoney = generalMethods.gainMoney; + getCurrentServer = serverMethods.getCurrentServer; + getGangFaction = gangMethods.getGangFaction; + getGangName = gangMethods.getGangName; + getHomeComputer = serverMethods.getHomeComputer; + getNextCompanyPosition = generalMethods.getNextCompanyPosition; + getUpgradeHomeRamCost = serverMethods.getUpgradeHomeRamCost; + getUpgradeHomeCoresCost = serverMethods.getUpgradeHomeCoresCost; + gotoLocation = generalMethods.gotoLocation; + hasAugmentation = augmentationMethods.hasAugmentation; + hasCorporation = corporationMethods.hasCorporation; + hasGangWith = gangMethods.hasGangWith; + hasTorRouter = serverMethods.hasTorRouter; + hasProgram = generalMethods.hasProgram; + inBladeburner = bladeburnerMethods.inBladeburner; + inGang = gangMethods.inGang; + isAwareOfGang = gangMethods.isAwareOfGang; + isQualified = generalMethods.isQualified; + loseMoney = generalMethods.loseMoney; + reapplyAllAugmentations = generalMethods.reapplyAllAugmentations; + reapplyAllSourceFiles = generalMethods.reapplyAllSourceFiles; + regenerateHp = generalMethods.regenerateHp; + recordMoneySource = generalMethods.recordMoneySource; + setMoney = generalMethods.setMoney; + startBladeburner = bladeburnerMethods.startBladeburner; + startCorporation = corporationMethods.startCorporation; + startFocusing = generalMethods.startFocusing; + startGang = gangMethods.startGang; + takeDamage = generalMethods.takeDamage; + travel = generalMethods.travel; + giveExploit = generalMethods.giveExploit; + giveAchievement = generalMethods.giveAchievement; + queryStatFromString = generalMethods.queryStatFromString; + getIntelligenceBonus = generalMethods.getIntelligenceBonus; + getCasinoWinnings = generalMethods.getCasinoWinnings; + quitJob = generalMethods.quitJob; + hasJob = generalMethods.hasJob; + createHacknetServer = serverMethods.createHacknetServer; + queueAugmentation = generalMethods.queueAugmentation; + receiveInvite = generalMethods.receiveInvite; + updateSkillLevels = generalMethods.updateSkillLevels; + gainCodingContractReward = generalMethods.gainCodingContractReward; + stopFocusing = generalMethods.stopFocusing; + resetMultipliers = generalMethods.resetMultipliers; + prestigeAugmentation = generalMethods.prestigeAugmentation; + prestigeSourceFile = generalMethods.prestigeSourceFile; + calculateSkill = generalMethods.calculateSkill; + calculateSkillProgress = generalMethods.calculateSkillProgress; + hospitalize = generalMethods.hospitalize; + checkForFactionInvitations = generalMethods.checkForFactionInvitations; + setBitNodeNumber = generalMethods.setBitNodeNumber; + canAccessCotMG = generalMethods.canAccessCotMG; + sourceFileLvl = generalMethods.sourceFileLvl; + applyEntropy = augmentationMethods.applyEntropy; + focusPenalty = generalMethods.focusPenalty; constructor() { - this.hp = { current: 10, max: 10 }; - this.skills = { - hacking: 1, - strength: 1, - defense: 1, - dexterity: 1, - agility: 1, - charisma: 1, - intelligence: 0, - }; - this.exp = { - hacking: 0, - strength: 0, - defense: 0, - dexterity: 0, - agility: 0, - charisma: 0, - intelligence: 0, - }; - - this.mults = defaultMultipliers(); - - //Money - this.money = 1000 + CONSTANTS.Donations; - - //Location information - this.city = CityName.Sector12; - this.location = LocationName.TravelAgency; - - // Jobs that the player holds - // Map of company name (key) -> name of company position (value. Just the name, not the CompanyPosition object) - // The CompanyPosition name must match a key value in CompanyPositions - this.jobs = {}; - - // Servers - this.currentServer = ""; //hostname of Server currently being accessed through termina; - this.purchasedServers = []; //hostnames of purchased server; - - // Hacknet Nodes/Servers - this.hacknetNodes = []; // Note= For Hacknet Servers, this array holds the hostnames of the server; - this.hashManager = new HashManager(); - - //Factions - this.factions = []; //Names of all factions player has joine; - this.factionInvitations = []; //Outstanding faction invitation; - - //Augmentations - this.queuedAugmentations = []; - this.augmentations = []; - - this.sourceFiles = []; - - //Crime statistics - this.numPeopleKilled = 0; - this.karma = 0; - - //Stock Market - this.hasWseAccount = false; - this.hasTixApiAccess = false; - this.has4SData = false; - this.has4SDataTixApi = false; - - //Gang - this.gang = null; - - //Corporation - this.corporation = null; - - //Bladeburner - this.bladeburner = null; - - // Sleeves & Re-sleeving - this.sleeves = []; - this.sleevesFromCovenant = 0; // # of Duplicate sleeves purchased from the covenant - //bitnode - this.bitNodeN = 1; - - this.entropy = 0; - - //Used to store the last update time. - this.lastUpdate = 0; - this.lastSave = 0; - this.totalPlaytime = 0; - - this.playtimeSinceLastAug = 0; - this.playtimeSinceLastBitnode = 0; - - // Keep track of where money comes from - this.moneySourceA = new MoneySourceTracker(); // Where money comes from since last-installed Augmentation - this.moneySourceB = new MoneySourceTracker(); // Where money comes from for this entire BitNode run - // Production since last Augmentation installation - this.scriptProdSinceLastAug = 0; - - this.exploits = []; - this.achievements = []; - this.terminalCommandHistory = []; - - this.focus = false; - this.currentWork = null; - // Let's get a hash of some semi-random stuff so we have something unique. this.identifier = cyrb53( "I-" + @@ -292,96 +198,6 @@ export class PlayerObject implements IPlayer { window.innerHeight + getRandomInt(100, 999), ); - - this.init = generalMethods.init; - this.prestigeAugmentation = generalMethods.prestigeAugmentation; - this.prestigeSourceFile = generalMethods.prestigeSourceFile; - this.receiveInvite = generalMethods.receiveInvite; - this.calculateSkill = generalMethods.calculateSkill; - this.calculateSkillProgress = generalMethods.calculateSkillProgress; - this.updateSkillLevels = generalMethods.updateSkillLevels; - this.resetMultipliers = generalMethods.resetMultipliers; - this.hasProgram = generalMethods.hasProgram; - this.setMoney = generalMethods.setMoney; - this.gainMoney = generalMethods.gainMoney; - this.loseMoney = generalMethods.loseMoney; - this.canAfford = generalMethods.canAfford; - this.recordMoneySource = generalMethods.recordMoneySource; - this.gainHackingExp = generalMethods.gainHackingExp; - this.gainStrengthExp = generalMethods.gainStrengthExp; - this.gainDefenseExp = generalMethods.gainDefenseExp; - this.gainDexterityExp = generalMethods.gainDexterityExp; - this.gainAgilityExp = generalMethods.gainAgilityExp; - this.gainCharismaExp = generalMethods.gainCharismaExp; - this.gainIntelligenceExp = generalMethods.gainIntelligenceExp; - this.gainStats = generalMethods.gainStats; - this.queryStatFromString = generalMethods.queryStatFromString; - this.startWork = workMethods.start; - this.processWork = workMethods.process; - this.finishWork = workMethods.finish; - this.startFocusing = generalMethods.startFocusing; - this.stopFocusing = generalMethods.stopFocusing; - this.takeDamage = generalMethods.takeDamage; - this.regenerateHp = generalMethods.regenerateHp; - this.hospitalize = generalMethods.hospitalize; - this.applyForJob = generalMethods.applyForJob; - this.getNextCompanyPosition = generalMethods.getNextCompanyPosition; - this.quitJob = generalMethods.quitJob; - this.hasJob = generalMethods.hasJob; - this.applyForSoftwareJob = generalMethods.applyForSoftwareJob; - this.applyForSoftwareConsultantJob = generalMethods.applyForSoftwareConsultantJob; - this.applyForItJob = generalMethods.applyForItJob; - this.applyForSecurityEngineerJob = generalMethods.applyForSecurityEngineerJob; - this.applyForNetworkEngineerJob = generalMethods.applyForNetworkEngineerJob; - this.applyForBusinessJob = generalMethods.applyForBusinessJob; - this.applyForBusinessConsultantJob = generalMethods.applyForBusinessConsultantJob; - this.applyForSecurityJob = generalMethods.applyForSecurityJob; - this.applyForAgentJob = generalMethods.applyForAgentJob; - this.applyForEmployeeJob = generalMethods.applyForEmployeeJob; - this.applyForPartTimeEmployeeJob = generalMethods.applyForPartTimeEmployeeJob; - this.applyForWaiterJob = generalMethods.applyForWaiterJob; - this.applyForPartTimeWaiterJob = generalMethods.applyForPartTimeWaiterJob; - this.isQualified = generalMethods.isQualified; - this.reapplyAllAugmentations = generalMethods.reapplyAllAugmentations; - this.reapplyAllSourceFiles = generalMethods.reapplyAllSourceFiles; - this.checkForFactionInvitations = generalMethods.checkForFactionInvitations; - this.setBitNodeNumber = generalMethods.setBitNodeNumber; - this.queueAugmentation = generalMethods.queueAugmentation; - this.gainCodingContractReward = generalMethods.gainCodingContractReward; - this.travel = generalMethods.travel; - this.gotoLocation = generalMethods.gotoLocation; - this.canAccessGrafting = generalMethods.canAccessGrafting; - this.giveExploit = generalMethods.giveExploit; - this.giveAchievement = generalMethods.giveAchievement; - this.getIntelligenceBonus = generalMethods.getIntelligenceBonus; - this.getCasinoWinnings = generalMethods.getCasinoWinnings; - this.hasAugmentation = augmentationMethods.hasAugmentation; - this.canAccessBladeburner = bladeburnerMethods.canAccessBladeburner; - this.inBladeburner = bladeburnerMethods.inBladeburner; - this.startBladeburner = bladeburnerMethods.startBladeburner; - this.canAccessCorporation = corporationMethods.canAccessCorporation; - this.hasCorporation = corporationMethods.hasCorporation; - this.startCorporation = corporationMethods.startCorporation; - this.canAccessGang = gangMethods.canAccessGang; - this.isAwareOfGang = gangMethods.isAwareOfGang; - this.getGangFaction = gangMethods.getGangFaction; - this.getGangName = gangMethods.getGangName; - this.hasGangWith = gangMethods.hasGangWith; - this.inGang = gangMethods.inGang; - this.startGang = gangMethods.startGang; - - this.hasTorRouter = serverMethods.hasTorRouter; - this.getCurrentServer = serverMethods.getCurrentServer; - this.getHomeComputer = serverMethods.getHomeComputer; - this.getUpgradeHomeRamCost = serverMethods.getUpgradeHomeRamCost; - this.getUpgradeHomeCoresCost = serverMethods.getUpgradeHomeCoresCost; - this.createHacknetServer = serverMethods.createHacknetServer; - - this.canAccessCotMG = generalMethods.canAccessCotMG; - this.sourceFileLvl = generalMethods.sourceFileLvl; - - this.applyEntropy = augmentationMethods.applyEntropy; - this.focusPenalty = generalMethods.focusPenalty; } whoAmI(): string { diff --git a/src/PersonObjects/Player/PlayerObjectAugmentationMethods.ts b/src/PersonObjects/Player/PlayerObjectAugmentationMethods.ts index d7cd35177..45bfbd44a 100644 --- a/src/PersonObjects/Player/PlayerObjectAugmentationMethods.ts +++ b/src/PersonObjects/Player/PlayerObjectAugmentationMethods.ts @@ -1,13 +1,13 @@ /** * Augmentation-related methods for the Player class (PlayerObject) */ -import { IPlayer } from "../IPlayer"; +import { PlayerObject } from "./PlayerObject"; import { Augmentation } from "../../Augmentation/Augmentation"; import { calculateEntropy } from "../Grafting/EntropyAccumulation"; -export function hasAugmentation(this: IPlayer, aug: string | Augmentation, ignoreQueued = false): boolean { +export function hasAugmentation(this: PlayerObject, aug: string | Augmentation, ignoreQueued = false): boolean { const augName: string = aug instanceof Augmentation ? aug.name : aug; for (const owned of this.augmentations) { @@ -27,7 +27,7 @@ export function hasAugmentation(this: IPlayer, aug: string | Augmentation, ignor return false; } -export function applyEntropy(this: IPlayer, stacks = 1): void { +export function applyEntropy(this: PlayerObject, stacks = 1): void { // Re-apply all multipliers this.reapplyAllAugmentations(); this.reapplyAllSourceFiles(); diff --git a/src/PersonObjects/Player/PlayerObjectBladeburnerMethods.ts b/src/PersonObjects/Player/PlayerObjectBladeburnerMethods.ts index cf8d9e2ce..b8e9e31ad 100644 --- a/src/PersonObjects/Player/PlayerObjectBladeburnerMethods.ts +++ b/src/PersonObjects/Player/PlayerObjectBladeburnerMethods.ts @@ -1,17 +1,17 @@ import { Bladeburner } from "../../Bladeburner/Bladeburner"; -import { IPlayer } from "../IPlayer"; +import { PlayerObject } from "./PlayerObject"; -export function canAccessBladeburner(this: IPlayer): boolean { +export function canAccessBladeburner(this: PlayerObject): boolean { return this.bitNodeN === 6 || this.bitNodeN === 7 || this.sourceFileLvl(6) > 0 || this.sourceFileLvl(7) > 0; } -export function inBladeburner(this: IPlayer): boolean { +export function inBladeburner(this: PlayerObject): boolean { if (this.bladeburner == null) { return false; } return this.bladeburner instanceof Bladeburner; } -export function startBladeburner(this: IPlayer): void { +export function startBladeburner(this: PlayerObject): void { this.bladeburner = new Bladeburner(); } diff --git a/src/PersonObjects/Player/PlayerObjectCorporationMethods.ts b/src/PersonObjects/Player/PlayerObjectCorporationMethods.ts index c853aceae..95acac366 100644 --- a/src/PersonObjects/Player/PlayerObjectCorporationMethods.ts +++ b/src/PersonObjects/Player/PlayerObjectCorporationMethods.ts @@ -3,20 +3,20 @@ import { CorporationUnlockUpgradeIndex, CorporationUnlockUpgrades, } from "../../Corporation/data/CorporationUnlockUpgrades"; -import { IPlayer } from "../IPlayer"; +import { PlayerObject } from "./PlayerObject"; -export function canAccessCorporation(this: IPlayer): boolean { +export function canAccessCorporation(this: PlayerObject): boolean { return this.bitNodeN === 3 || this.sourceFileLvl(3) > 0; } -export function hasCorporation(this: IPlayer): boolean { +export function hasCorporation(this: PlayerObject): boolean { if (this.corporation == null) { return false; } return this.corporation instanceof Corporation; } -export function startCorporation(this: IPlayer, corpName: string, additionalShares = 0): void { +export function startCorporation(this: PlayerObject, corpName: string, additionalShares = 0): void { this.corporation = new Corporation({ name: corpName, }); diff --git a/src/PersonObjects/Player/PlayerObjectGangMethods.ts b/src/PersonObjects/Player/PlayerObjectGangMethods.ts index 77568ee60..fbe765a74 100644 --- a/src/PersonObjects/Player/PlayerObjectGangMethods.ts +++ b/src/PersonObjects/Player/PlayerObjectGangMethods.ts @@ -1,10 +1,10 @@ import { Factions } from "../../Faction/Factions"; import { Faction } from "../../Faction/Faction"; import { Gang } from "../../Gang/Gang"; -import { IPlayer } from "../IPlayer"; +import { PlayerObject } from "./PlayerObject"; import { GangConstants } from "../../Gang/data/Constants"; -export function canAccessGang(this: IPlayer): boolean { +export function canAccessGang(this: PlayerObject): boolean { if (this.bitNodeN === 2) { return true; } @@ -15,11 +15,11 @@ export function canAccessGang(this: IPlayer): boolean { return this.karma <= GangConstants.GangKarmaRequirement; } -export function isAwareOfGang(this: IPlayer): boolean { +export function isAwareOfGang(this: PlayerObject): boolean { return this.bitNodeN === 2 || this.sourceFileLvl(2) >= 1; } -export function getGangFaction(this: IPlayer): Faction { +export function getGangFaction(this: PlayerObject): Faction { const gang = this.gang; if (gang === null) { throw new Error("Cannot get gang faction because player is not in a gang."); @@ -32,7 +32,7 @@ export function getGangFaction(this: IPlayer): Faction { return fac; } -export function getGangName(this: IPlayer): string { +export function getGangName(this: PlayerObject): string { if (!this.inGang()) return ""; const gang = this.gang; if (gang === null) { @@ -41,7 +41,7 @@ export function getGangName(this: IPlayer): string { return gang.facName; } -export function hasGangWith(this: IPlayer, facName: string): boolean { +export function hasGangWith(this: PlayerObject, facName: string): boolean { if (!this.inGang()) return false; const gang = this.gang; if (gang === null) { @@ -50,7 +50,7 @@ export function hasGangWith(this: IPlayer, facName: string): boolean { return gang.facName === facName; } -export function inGang(this: IPlayer): boolean { +export function inGang(this: PlayerObject): boolean { if (this.gang == null || this.gang == undefined) { return false; } @@ -58,7 +58,7 @@ export function inGang(this: IPlayer): boolean { return this.gang instanceof Gang; } -export function startGang(this: IPlayer, factionName: string, hacking: boolean): void { +export function startGang(this: PlayerObject, factionName: string, hacking: boolean): void { this.gang = new Gang(factionName, hacking); const fac = Factions[factionName]; diff --git a/src/PersonObjects/Player/PlayerObjectGeneralMethods.ts b/src/PersonObjects/Player/PlayerObjectGeneralMethods.ts index dc13eb4d7..e44277f8f 100644 --- a/src/PersonObjects/Player/PlayerObjectGeneralMethods.ts +++ b/src/PersonObjects/Player/PlayerObjectGeneralMethods.ts @@ -1,4 +1,3 @@ -import { IPlayer } from "../IPlayer"; import { PlayerObject } from "./PlayerObject"; import { applyAugmentation } from "../../Augmentation/AugmentationHelpers"; import { PlayerOwnedAugmentation } from "../../Augmentation/PlayerOwnedAugmentation"; @@ -56,7 +55,7 @@ import { isCompanyWork } from "../../Work/CompanyWork"; import { defaultMultipliers } from "../Multipliers"; import { serverMetadata } from "../../Server/data/servers"; -export function init(this: IPlayer): void { +export function init(this: PlayerObject): void { /* Initialize Player's home computer */ const t_homeComp = safetlyCreateUniqueServer({ adminRights: true, @@ -142,7 +141,7 @@ export function prestigeAugmentation(this: PlayerObject): void { this.finishWork(true); } -export function prestigeSourceFile(this: IPlayer): void { +export function prestigeSourceFile(this: PlayerObject): void { this.entropy = 0; this.prestigeAugmentation(); this.karma = 0; @@ -180,7 +179,7 @@ export function prestigeSourceFile(this: IPlayer): void { this.augmentations = []; } -export function receiveInvite(this: IPlayer, factionName: string): void { +export function receiveInvite(this: PlayerObject, factionName: string): void { if (this.factionInvitations.includes(factionName) || this.factions.includes(factionName)) { return; } @@ -193,11 +192,11 @@ export function calculateSkill(this: IPerson, exp: number, mult = 1): number { } //Calculates skill level progress based on experience. The same formula will be used for every skill -export function calculateSkillProgress(this: IPlayer, exp: number, mult = 1): ISkillProgress { +export function calculateSkillProgress(this: PlayerObject, exp: number, mult = 1): ISkillProgress { return calculateSkillProgressF(exp, mult); } -export function updateSkillLevels(this: IPlayer): void { +export function updateSkillLevels(this: PlayerObject): void { this.skills.hacking = Math.max( 1, Math.floor(this.calculateSkill(this.exp.hacking, this.mults.hacking * BitNodeMultipliers.HackingLevelMultiplier)), @@ -240,11 +239,11 @@ export function updateSkillLevels(this: IPlayer): void { this.hp.current = Math.round(this.hp.max * ratio); } -export function resetMultipliers(this: IPlayer): void { +export function resetMultipliers(this: PlayerObject): void { this.mults = defaultMultipliers(); } -export function hasProgram(this: IPlayer, programName: string): boolean { +export function hasProgram(this: PlayerObject, programName: string): boolean { const home = this.getHomeComputer(); if (home == null) { return false; @@ -286,7 +285,7 @@ export function loseMoney(this: PlayerObject, money: number, source: string): vo this.recordMoneySource(-1 * money, source); } -export function canAfford(this: IPlayer, cost: number): boolean { +export function canAfford(this: PlayerObject, cost: number): boolean { if (isNaN(cost)) { console.error(`NaN passed into Player.canAfford()`); return false; @@ -428,7 +427,7 @@ export function gainStats(this: IPerson, retValue: ITaskTracker): void { } //Given a string expression like "str" or "strength", returns the given stat -export function queryStatFromString(this: IPlayer, str: string): number { +export function queryStatFromString(this: PlayerObject, str: string): number { const tempStr = str.toLowerCase(); if (tempStr.includes("hack")) { return this.skills.hacking; @@ -454,16 +453,16 @@ export function queryStatFromString(this: IPlayer, str: string): number { return 0; } -export function startFocusing(this: IPlayer): void { +export function startFocusing(this: PlayerObject): void { this.focus = true; } -export function stopFocusing(this: IPlayer): void { +export function stopFocusing(this: PlayerObject): void { this.focus = false; } // Returns true if hospitalized, false otherwise -export function takeDamage(this: IPlayer, amt: number): boolean { +export function takeDamage(this: PlayerObject, amt: number): boolean { if (typeof amt !== "number") { console.warn(`Player.takeDamage() called without a numeric argument: ${amt}`); return false; @@ -489,7 +488,7 @@ export function regenerateHp(this: IPerson, amt: number): void { } } -export function hospitalize(this: IPlayer): number { +export function hospitalize(this: PlayerObject): number { const cost = getHospitalizationCost(); SnackbarEvents.emit(`You've been Hospitalized for ${numeralWrapper.formatMoney(cost)}`, ToastVariant.WARNING, 2000); @@ -502,7 +501,7 @@ export function hospitalize(this: IPlayer): number { //Determines the job that the Player should get (if any) at the current company //The 'sing' argument designates whether or not this is being called from //the applyToCompany() Netscript Singularity function -export function applyForJob(this: IPlayer, entryPosType: CompanyPosition, sing = false): boolean { +export function applyForJob(this: PlayerObject, entryPosType: CompanyPosition, sing = false): boolean { const company = Companies[this.location]; //Company being applied to if (!(company instanceof Company)) { console.error(`Could not find company that matches the location: ${this.location}. Player.applyToCompany() failed`); @@ -555,7 +554,7 @@ export function applyForJob(this: IPlayer, entryPosType: CompanyPosition, sing = //Returns your next position at a company given the field (software, business, etc.) export function getNextCompanyPosition( - this: IPlayer, + this: PlayerObject, company: Company, entryPosType: CompanyPosition, ): CompanyPosition | null { @@ -590,7 +589,7 @@ export function getNextCompanyPosition( return entryPosType; } -export function quitJob(this: IPlayer, company: string): void { +export function quitJob(this: PlayerObject, company: string): void { if (isCompanyWork(this.currentWork) && this.currentWork.companyName === company) { this.finishWork(true); } @@ -608,23 +607,23 @@ export function quitJob(this: IPlayer, company: string): void { * @param this The player instance * @returns Whether the user has at least one job */ -export function hasJob(this: IPlayer): boolean { +export function hasJob(this: PlayerObject): boolean { return Boolean(Object.keys(this.jobs).length); } -export function applyForSoftwareJob(this: IPlayer, sing = false): boolean { +export function applyForSoftwareJob(this: PlayerObject, sing = false): boolean { return this.applyForJob(CompanyPositions[posNames.SoftwareCompanyPositions[0]], sing); } -export function applyForSoftwareConsultantJob(this: IPlayer, sing = false): boolean { +export function applyForSoftwareConsultantJob(this: PlayerObject, sing = false): boolean { return this.applyForJob(CompanyPositions[posNames.SoftwareConsultantCompanyPositions[0]], sing); } -export function applyForItJob(this: IPlayer, sing = false): boolean { +export function applyForItJob(this: PlayerObject, sing = false): boolean { return this.applyForJob(CompanyPositions[posNames.ITCompanyPositions[0]], sing); } -export function applyForSecurityEngineerJob(this: IPlayer, sing = false): boolean { +export function applyForSecurityEngineerJob(this: PlayerObject, sing = false): boolean { const company = Companies[this.location]; //Company being applied to if (this.isQualified(company, CompanyPositions[posNames.SecurityEngineerCompanyPositions[0]])) { return this.applyForJob(CompanyPositions[posNames.SecurityEngineerCompanyPositions[0]], sing); @@ -636,7 +635,7 @@ export function applyForSecurityEngineerJob(this: IPlayer, sing = false): boolea } } -export function applyForNetworkEngineerJob(this: IPlayer, sing = false): boolean { +export function applyForNetworkEngineerJob(this: PlayerObject, sing = false): boolean { const company = Companies[this.location]; //Company being applied to if (this.isQualified(company, CompanyPositions[posNames.NetworkEngineerCompanyPositions[0]])) { const pos = CompanyPositions[posNames.NetworkEngineerCompanyPositions[0]]; @@ -649,21 +648,21 @@ export function applyForNetworkEngineerJob(this: IPlayer, sing = false): boolean } } -export function applyForBusinessJob(this: IPlayer, sing = false): boolean { +export function applyForBusinessJob(this: PlayerObject, sing = false): boolean { return this.applyForJob(CompanyPositions[posNames.BusinessCompanyPositions[0]], sing); } -export function applyForBusinessConsultantJob(this: IPlayer, sing = false): boolean { +export function applyForBusinessConsultantJob(this: PlayerObject, sing = false): boolean { return this.applyForJob(CompanyPositions[posNames.BusinessConsultantCompanyPositions[0]], sing); } -export function applyForSecurityJob(this: IPlayer, sing = false): boolean { +export function applyForSecurityJob(this: PlayerObject, sing = false): boolean { // TODO Police Jobs // Indexing starts at 2 because 0 is for police officer return this.applyForJob(CompanyPositions[posNames.SecurityCompanyPositions[2]], sing); } -export function applyForAgentJob(this: IPlayer, sing = false): boolean { +export function applyForAgentJob(this: PlayerObject, sing = false): boolean { const company = Companies[this.location]; //Company being applied to if (this.isQualified(company, CompanyPositions[posNames.AgentCompanyPositions[0]])) { const pos = CompanyPositions[posNames.AgentCompanyPositions[0]]; @@ -676,7 +675,7 @@ export function applyForAgentJob(this: IPlayer, sing = false): boolean { } } -export function applyForEmployeeJob(this: IPlayer, sing = false): boolean { +export function applyForEmployeeJob(this: PlayerObject, sing = false): boolean { const company = Companies[this.location]; //Company being applied to const position = posNames.MiscCompanyPositions[1]; // Check if this company has the position @@ -700,7 +699,7 @@ export function applyForEmployeeJob(this: IPlayer, sing = false): boolean { } } -export function applyForPartTimeEmployeeJob(this: IPlayer, sing = false): boolean { +export function applyForPartTimeEmployeeJob(this: PlayerObject, sing = false): boolean { const company = Companies[this.location]; //Company being applied to const position = posNames.PartTimeCompanyPositions[1]; // Check if this company has the position @@ -723,7 +722,7 @@ export function applyForPartTimeEmployeeJob(this: IPlayer, sing = false): boolea } } -export function applyForWaiterJob(this: IPlayer, sing = false): boolean { +export function applyForWaiterJob(this: PlayerObject, sing = false): boolean { const company = Companies[this.location]; //Company being applied to const position = posNames.MiscCompanyPositions[0]; // Check if this company has the position @@ -744,7 +743,7 @@ export function applyForWaiterJob(this: IPlayer, sing = false): boolean { } } -export function applyForPartTimeWaiterJob(this: IPlayer, sing = false): boolean { +export function applyForPartTimeWaiterJob(this: PlayerObject, sing = false): boolean { const company = Companies[this.location]; //Company being applied to const position = posNames.PartTimeCompanyPositions[0]; // Check if this company has the position @@ -766,7 +765,7 @@ export function applyForPartTimeWaiterJob(this: IPlayer, sing = false): boolean } //Checks if the Player is qualified for a certain position -export function isQualified(this: IPlayer, company: Company, position: CompanyPosition): boolean { +export function isQualified(this: PlayerObject, company: Company, position: CompanyPosition): boolean { const offset = company.jobStatReqOffset; const reqHacking = position.requiredHacking > 0 ? position.requiredHacking + offset : 0; const reqStrength = position.requiredStrength > 0 ? position.requiredStrength + offset : 0; @@ -787,7 +786,7 @@ export function isQualified(this: IPlayer, company: Company, position: CompanyPo } /********** Reapplying Augmentations and Source File ***********/ -export function reapplyAllAugmentations(this: IPlayer, resetMultipliers = true): void { +export function reapplyAllAugmentations(this: PlayerObject, resetMultipliers = true): void { if (resetMultipliers) { this.resetMultipliers(); } @@ -813,7 +812,7 @@ export function reapplyAllAugmentations(this: IPlayer, resetMultipliers = true): this.updateSkillLevels(); } -export function reapplyAllSourceFiles(this: IPlayer): void { +export function reapplyAllSourceFiles(this: PlayerObject): void { //Will always be called after reapplyAllAugmentations() so multipliers do not have to be reset //this.resetMultipliers(); @@ -834,7 +833,7 @@ export function reapplyAllSourceFiles(this: IPlayer): void { //This function sets the requirements to join a Faction. It checks whether the Player meets //those requirements and will return an array of all factions that the Player should //receive an invitation to -export function checkForFactionInvitations(this: IPlayer): Faction[] { +export function checkForFactionInvitations(this: PlayerObject): Faction[] { const invitedFactions: Faction[] = []; //Array which will hold all Factions the player should be invited to const numAugmentations = this.augmentations.length; @@ -1320,11 +1319,11 @@ export function checkForFactionInvitations(this: IPlayer): Faction[] { } /************* BitNodes **************/ -export function setBitNodeNumber(this: IPlayer, n: number): void { +export function setBitNodeNumber(this: PlayerObject, n: number): void { this.bitNodeN = n; } -export function queueAugmentation(this: IPlayer, name: string): void { +export function queueAugmentation(this: PlayerObject, name: string): void { for (const aug of this.queuedAugmentations) { if (aug.name == name) { console.warn(`tried to queue ${name} twice, this may be a bug`); @@ -1343,7 +1342,7 @@ export function queueAugmentation(this: IPlayer, name: string): void { } /************* Coding Contracts **************/ -export function gainCodingContractReward(this: IPlayer, reward: ICodingContractReward, difficulty = 1): string { +export function gainCodingContractReward(this: PlayerObject, reward: ICodingContractReward, difficulty = 1): string { if (reward == null || reward.type == null) { return `No reward for this contract`; } @@ -1402,7 +1401,7 @@ export function gainCodingContractReward(this: IPlayer, reward: ICodingContractR /* eslint-enable no-case-declarations */ } -export function travel(this: IPlayer, to: CityName): boolean { +export function travel(this: PlayerObject, to: CityName): boolean { if (Cities[to] == null) { console.warn(`Player.travel() called with invalid city: ${to}`); return false; @@ -1412,7 +1411,7 @@ export function travel(this: IPlayer, to: CityName): boolean { return true; } -export function gotoLocation(this: IPlayer, to: LocationName): boolean { +export function gotoLocation(this: PlayerObject, to: LocationName): boolean { if (Locations[to] == null) { console.warn(`Player.gotoLocation() called with invalid location: ${to}`); return false; @@ -1422,18 +1421,18 @@ export function gotoLocation(this: IPlayer, to: LocationName): boolean { return true; } -export function canAccessGrafting(this: IPlayer): boolean { +export function canAccessGrafting(this: PlayerObject): boolean { return this.bitNodeN === 10 || this.sourceFileLvl(10) > 0; } -export function giveExploit(this: IPlayer, exploit: Exploit): void { +export function giveExploit(this: PlayerObject, exploit: Exploit): void { if (!this.exploits.includes(exploit)) { this.exploits.push(exploit); SnackbarEvents.emit("SF -1 acquired!", ToastVariant.SUCCESS, 2000); } } -export function giveAchievement(this: IPlayer, achievementId: string): void { +export function giveAchievement(this: PlayerObject, achievementId: string): void { const achievement = achievements[achievementId]; if (!achievement) return; if (!this.achievements.map((a) => a.ID).includes(achievementId)) { @@ -1442,25 +1441,25 @@ export function giveAchievement(this: IPlayer, achievementId: string): void { } } -export function getIntelligenceBonus(this: IPlayer, weight: number): number { +export function getIntelligenceBonus(this: PlayerObject, weight: number): number { return calculateIntelligenceBonus(this.skills.intelligence, weight); } -export function getCasinoWinnings(this: IPlayer): number { +export function getCasinoWinnings(this: PlayerObject): number { return this.moneySourceA.casino; } -export function canAccessCotMG(this: IPlayer): boolean { +export function canAccessCotMG(this: PlayerObject): boolean { return this.bitNodeN === 13 || this.sourceFileLvl(13) > 0; } -export function sourceFileLvl(this: IPlayer, n: number): number { +export function sourceFileLvl(this: PlayerObject, n: number): number { const sf = this.sourceFiles.find((sf) => sf.n === n); if (!sf) return 0; return sf.lvl; } -export function focusPenalty(this: IPlayer): number { +export function focusPenalty(this: PlayerObject): number { let focus = 1; if (!this.hasAugmentation(AugmentationNames.NeuroreceptorManager, true)) { focus = this.focus ? 1 : CONSTANTS.BaseFocusBonus; diff --git a/src/PersonObjects/Player/PlayerObjectServerMethods.ts b/src/PersonObjects/Player/PlayerObjectServerMethods.ts index 8f706fbdd..a8ff2c456 100644 --- a/src/PersonObjects/Player/PlayerObjectServerMethods.ts +++ b/src/PersonObjects/Player/PlayerObjectServerMethods.ts @@ -1,7 +1,7 @@ /** * Server and HacknetServer-related methods for the Player class (PlayerObject) */ -import { IPlayer } from "../IPlayer"; +import { PlayerObject } from "./PlayerObject"; import { CONSTANTS } from "../../Constants"; @@ -12,23 +12,23 @@ import { HacknetServer } from "../../Hacknet/HacknetServer"; import { GetServer, AddToAllServers, createUniqueRandomIp } from "../../Server/AllServers"; import { SpecialServers } from "../../Server/data/SpecialServers"; -export function hasTorRouter(this: IPlayer): boolean { +export function hasTorRouter(this: PlayerObject): boolean { return this.getHomeComputer().serversOnNetwork.includes(SpecialServers.DarkWeb); } -export function getCurrentServer(this: IPlayer): BaseServer { +export function getCurrentServer(this: PlayerObject): BaseServer { const server = GetServer(this.currentServer); if (server === null) throw new Error(`somehow connected to a server that does not exist. ${this.currentServer}`); return server; } -export function getHomeComputer(this: IPlayer): Server { +export function getHomeComputer(this: PlayerObject): Server { const home = GetServer("home"); if (home instanceof Server) return home; throw new Error("home computer was not a normal server"); } -export function getUpgradeHomeRamCost(this: IPlayer): number { +export function getUpgradeHomeRamCost(this: PlayerObject): number { //Calculate how many times ram has been upgraded (doubled) const currentRam = this.getHomeComputer().maxRam; const numUpgrades = Math.log2(currentRam); @@ -40,11 +40,11 @@ export function getUpgradeHomeRamCost(this: IPlayer): number { return cost; } -export function getUpgradeHomeCoresCost(this: IPlayer): number { +export function getUpgradeHomeCoresCost(this: PlayerObject): number { return 1e9 * Math.pow(7.5, this.getHomeComputer().cpuCores); } -export function createHacknetServer(this: IPlayer): HacknetServer { +export function createHacknetServer(this: PlayerObject): HacknetServer { const numOwned = this.hacknetNodes.length; const name = `hacknet-node-${numOwned}`; const server = new HacknetServer({ diff --git a/src/PersonObjects/Player/PlayerObjectWorkMethods.ts b/src/PersonObjects/Player/PlayerObjectWorkMethods.ts index c2c306db5..41dfb2d30 100644 --- a/src/PersonObjects/Player/PlayerObjectWorkMethods.ts +++ b/src/PersonObjects/Player/PlayerObjectWorkMethods.ts @@ -1,20 +1,20 @@ import { Work } from "../../Work/Work"; -import { IPlayer } from "../IPlayer"; +import { PlayerObject } from "./PlayerObject"; -export function start(this: IPlayer, w: Work): void { +export function startWork(this: PlayerObject, w: Work): void { if (this.currentWork !== null) { this.currentWork.finish(true); } this.currentWork = w; } -export function process(this: IPlayer, cycles = 1): void { +export function processWork(this: PlayerObject, cycles = 1): void { if (this.currentWork === null) return; const finished = this.currentWork.process(cycles); if (finished) { this.finishWork(false); } } -export function finish(this: IPlayer, cancelled: boolean): void { +export function finishWork(this: PlayerObject, cancelled: boolean): void { if (this.currentWork === null) return; this.currentWork.finish(cancelled); this.currentWork = null; From dcd9023b93ac18b5f028954f4ee70916f174b350 Mon Sep 17 00:00:00 2001 From: Snarling <84951833+Snarling@users.noreply.github.com> Date: Tue, 20 Sep 2022 00:26:56 -0400 Subject: [PATCH 22/46] Remove more unused interfaces --- src/IEngine.ts | 28 --------- src/Terminal/ITerminal.tsx | 105 ------------------------------- src/Terminal/OutputTypes.tsx | 51 +++++++++++++++ src/Terminal/Terminal.ts | 4 +- src/Terminal/ui/TerminalRoot.tsx | 2 +- 5 files changed, 54 insertions(+), 136 deletions(-) delete mode 100644 src/IEngine.ts delete mode 100644 src/Terminal/ITerminal.tsx create mode 100644 src/Terminal/OutputTypes.tsx diff --git a/src/IEngine.ts b/src/IEngine.ts deleted file mode 100644 index 5f99fdf97..000000000 --- a/src/IEngine.ts +++ /dev/null @@ -1,28 +0,0 @@ -/** - * TypeScript interface for the game engine (engine.js), which can't be converted - * to TypeScript at the moment - */ -export interface IEngine { - _lastUpdate: number; - updateGame: (numCycles?: number) => void; - Counters: { - [key: string]: number | undefined; - autoSaveCounter: number; - updateSkillLevelsCounter: number; - updateDisplays: number; - updateDisplaysLong: number; - updateActiveScriptsDisplay: number; - createProgramNotifications: number; - augmentationsNotifications: number; - checkFactionInvitations: number; - passiveFactionGrowth: number; - messages: number; - mechanicProcess: number; - contractGeneration: number; - achievementsCounter: number; - }; - decrementAllCounters: (numCycles?: number) => void; - checkCounters: () => void; - load: (saveString: string) => void; - start: () => void; -} diff --git a/src/Terminal/ITerminal.tsx b/src/Terminal/ITerminal.tsx deleted file mode 100644 index c76e9e5b2..000000000 --- a/src/Terminal/ITerminal.tsx +++ /dev/null @@ -1,105 +0,0 @@ -import React from "react"; -import { TextFile } from "../TextFile"; -import { Script } from "../Script/Script"; -import { Settings } from "../Settings/Settings"; -import { formatTime } from "../utils/helpers/formatTime"; -import { BaseServer } from "../Server/BaseServer"; - -export class Output { - text: string; - color: "primary" | "error" | "success" | "info" | "warn"; - constructor(text: string, color: "primary" | "error" | "success" | "info" | "warn") { - if (Settings.TimestampsFormat) text = "[" + formatTime(Settings.TimestampsFormat) + "] " + text; - this.text = text; - this.color = color; - } -} - -export class RawOutput { - raw: React.ReactNode; - constructor(node: React.ReactNode) { - if (Settings.TimestampsFormat) - node = ( - <> - [{formatTime(Settings.TimestampsFormat)}] {node} - - ); - this.raw = node; - } -} - -export class Link { - hostname: string; - dashes: string; - constructor(dashes: string, hostname: string) { - if (Settings.TimestampsFormat) dashes = "[" + formatTime(Settings.TimestampsFormat) + "] " + dashes; - this.hostname = hostname; - this.dashes = dashes; - } -} - -export class TTimer { - time: number; - timeLeft: number; - action: "h" | "b" | "a" | "g" | "w"; - server?: BaseServer; - - constructor(time: number, action: "h" | "b" | "a" | "g" | "w", server?: BaseServer) { - this.time = time; - this.timeLeft = time; - this.action = action; - this.server = server; - } -} - -export interface ITerminal { - action: TTimer | null; - - commandHistory: string[]; - commandHistoryIndex: number; - - outputHistory: (Output | Link | RawOutput)[]; - - // True if a Coding Contract prompt is opened - contractOpen: boolean; - - // Full Path of current directory - // Excludes the trailing forward slash - currDir: string; - - print(s: string): void; - printRaw(node: React.ReactNode): void; - error(s: string): void; - success(s: string): void; - info(s: string): void; - warn(s: string): void; - - clear(): void; - startAnalyze(): void; - startBackdoor(): void; - startHack(): void; - startGrow(): void; - startWeaken(): void; - finishHack(server: BaseServer, cancelled?: boolean): void; - finishGrow(server: BaseServer, cancelled?: boolean): void; - finishWeaken(server: BaseServer, cancelled?: boolean): void; - finishBackdoor(server: BaseServer, cancelled?: boolean): void; - finishAnalyze(server: BaseServer, cancelled?: boolean): void; - finishAction(cancelled?: boolean): void; - getFilepath(filename: string): string; - getFile(filename: string): Script | TextFile | string | null; - getScript(filename: string): Script | null; - getTextFile(filename: string): TextFile | null; - getLitFile(filename: string): string | null; - cwd(): string; - setcwd(dir: string): void; - runContract(name: string): void; - executeScanAnalyzeCommand(depth?: number, all?: boolean): void; - connectToServer(server: string): void; - executeCommand(command: string): void; - executeCommands(commands: string): void; - // If there was any changes, will return true, once. - process(cycles: number): void; - prestige(): void; - getProgressText(): string; -} diff --git a/src/Terminal/OutputTypes.tsx b/src/Terminal/OutputTypes.tsx new file mode 100644 index 000000000..9f6148b87 --- /dev/null +++ b/src/Terminal/OutputTypes.tsx @@ -0,0 +1,51 @@ +import React from "react"; +import { Settings } from "../Settings/Settings"; +import { formatTime } from "../utils/helpers/formatTime"; +import { BaseServer } from "../Server/BaseServer"; + +export class Output { + text: string; + color: "primary" | "error" | "success" | "info" | "warn"; + constructor(text: string, color: "primary" | "error" | "success" | "info" | "warn") { + if (Settings.TimestampsFormat) text = "[" + formatTime(Settings.TimestampsFormat) + "] " + text; + this.text = text; + this.color = color; + } +} + +export class RawOutput { + raw: React.ReactNode; + constructor(node: React.ReactNode) { + if (Settings.TimestampsFormat) + node = ( + <> + [{formatTime(Settings.TimestampsFormat)}] {node} + + ); + this.raw = node; + } +} + +export class Link { + hostname: string; + dashes: string; + constructor(dashes: string, hostname: string) { + if (Settings.TimestampsFormat) dashes = "[" + formatTime(Settings.TimestampsFormat) + "] " + dashes; + this.hostname = hostname; + this.dashes = dashes; + } +} + +export class TTimer { + time: number; + timeLeft: number; + action: "h" | "b" | "a" | "g" | "w"; + server?: BaseServer; + + constructor(time: number, action: "h" | "b" | "a" | "g" | "w", server?: BaseServer) { + this.time = time; + this.timeLeft = time; + this.action = action; + this.server = server; + } +} diff --git a/src/Terminal/Terminal.ts b/src/Terminal/Terminal.ts index 61c4a259c..9e56f6a19 100644 --- a/src/Terminal/Terminal.ts +++ b/src/Terminal/Terminal.ts @@ -1,4 +1,4 @@ -import { ITerminal, Output, Link, RawOutput, TTimer } from "./ITerminal"; +import { Output, Link, RawOutput, TTimer } from "./OutputTypes"; import { Router } from "../ui/GameRoot"; import { Player } from "../Player"; import { HacknetServer } from "../Hacknet/HacknetServer"; @@ -75,7 +75,7 @@ import { hash } from "../hash/hash"; import { apr1 } from "./commands/apr1"; import { BitNodeMultipliers } from "../BitNode/BitNodeMultipliers"; -export class Terminal implements ITerminal { +export class Terminal { // Flags to determine whether the player is currently running a hack or an analyze action: TTimer | null = null; diff --git a/src/Terminal/ui/TerminalRoot.tsx b/src/Terminal/ui/TerminalRoot.tsx index 6eab48a5a..7f983b0af 100644 --- a/src/Terminal/ui/TerminalRoot.tsx +++ b/src/Terminal/ui/TerminalRoot.tsx @@ -7,7 +7,7 @@ import { Theme } from "@mui/material/styles"; import makeStyles from "@mui/styles/makeStyles"; import createStyles from "@mui/styles/createStyles"; import Box from "@mui/material/Box"; -import { Output, Link, RawOutput } from "../ITerminal"; +import { Output, Link, RawOutput } from "../OutputTypes"; import { Terminal } from "../../Terminal"; import { TerminalInput } from "./TerminalInput"; import { TerminalEvents, TerminalClearEvents } from "../TerminalEvents"; From 475a8812bb0ce212c5bcd4c16d482a60ce0a0f08 Mon Sep 17 00:00:00 2001 From: Snarling <84951833+Snarling@users.noreply.github.com> Date: Tue, 20 Sep 2022 00:40:07 -0400 Subject: [PATCH 23/46] findSleevePurchasableAugs as a class member --- src/NetscriptFunctions/Sleeve.ts | 3 +-- src/PersonObjects/Sleeve/Sleeve.ts | 3 +++ .../Sleeve/{SleeveHelpers.ts => SleeveMethods.ts} | 6 +++--- src/PersonObjects/Sleeve/ui/SleeveAugmentationsModal.tsx | 3 +-- 4 files changed, 8 insertions(+), 7 deletions(-) rename src/PersonObjects/Sleeve/{SleeveHelpers.ts => SleeveMethods.ts} (91%) diff --git a/src/NetscriptFunctions/Sleeve.ts b/src/NetscriptFunctions/Sleeve.ts index d523ccaf3..db24151dd 100644 --- a/src/NetscriptFunctions/Sleeve.ts +++ b/src/NetscriptFunctions/Sleeve.ts @@ -1,5 +1,4 @@ import { Player } from "../Player"; -import { findSleevePurchasableAugs } from "../PersonObjects/Sleeve/SleeveHelpers"; import { StaticAugmentations } from "../Augmentation/StaticAugmentations"; import { CityName } from "../Locations/data/CityNames"; import { findCrime } from "../Crime/CrimeHelpers"; @@ -251,7 +250,7 @@ export function NetscriptSleeve(): InternalAPI { checkSleeveAPIAccess(ctx); checkSleeveNumber(ctx, sleeveNumber); - const purchasableAugs = findSleevePurchasableAugs(Player.sleeves[sleeveNumber]); + const purchasableAugs = Player.sleeves[sleeveNumber].findPurchasableAugs(); const augs = []; for (let i = 0; i < purchasableAugs.length; i++) { const aug = purchasableAugs[i]; diff --git a/src/PersonObjects/Sleeve/Sleeve.ts b/src/PersonObjects/Sleeve/Sleeve.ts index 189496e75..ff0f92f40 100644 --- a/src/PersonObjects/Sleeve/Sleeve.ts +++ b/src/PersonObjects/Sleeve/Sleeve.ts @@ -44,6 +44,7 @@ import { SleeveInfiltrateWork } from "./Work/SleeveInfiltrateWork"; import { SleeveSupportWork } from "./Work/SleeveSupportWork"; import { SleeveBladeburnerWork } from "./Work/SleeveBladeburnerWork"; import { SleeveCrimeWork } from "./Work/SleeveCrimeWork"; +import * as sleeveMethods from "./SleeveMethods"; export class Sleeve extends Person { currentWork: Work | null = null; @@ -79,6 +80,8 @@ export class Sleeve extends Person { this.shockRecovery(); } + findPurchasableAugs = sleeveMethods.findPurchasableAugs; + shockBonus(): number { return this.shock / 100; } diff --git a/src/PersonObjects/Sleeve/SleeveHelpers.ts b/src/PersonObjects/Sleeve/SleeveMethods.ts similarity index 91% rename from src/PersonObjects/Sleeve/SleeveHelpers.ts rename to src/PersonObjects/Sleeve/SleeveMethods.ts index 87460fe4c..08d762d29 100644 --- a/src/PersonObjects/Sleeve/SleeveHelpers.ts +++ b/src/PersonObjects/Sleeve/SleeveMethods.ts @@ -10,12 +10,12 @@ import { Multipliers } from "../Multipliers"; import { AugmentationNames } from "../../Augmentation/data/AugmentationNames"; import { getFactionAugmentationsFiltered } from "../../Faction/FactionHelpers"; -export function findSleevePurchasableAugs(sleeve: Sleeve): Augmentation[] { +export function findPurchasableAugs(this: Sleeve): Augmentation[] { // You can only purchase Augmentations that are actually available from // your factions. I.e. you must be in a faction that has the Augmentation // and you must also have enough rep in that faction in order to purchase it. - const ownedAugNames = sleeve.augmentations.map((e) => e.name); + const ownedAugNames = this.augmentations.map((e) => e.name); const availableAugs: Augmentation[] = []; // Helper function that helps filter out augs that are already owned @@ -85,7 +85,7 @@ export function findSleevePurchasableAugs(sleeve: Sleeve): Augmentation[] { } // Add the stanek sleeve aug - if (!ownedAugNames.includes(AugmentationNames.ZOE) && p.factions.includes(FactionNames.ChurchOfTheMachineGod)) { + if (!ownedAugNames.includes(AugmentationNames.ZOE) && Player.factions.includes(FactionNames.ChurchOfTheMachineGod)) { const aug = StaticAugmentations[AugmentationNames.ZOE]; availableAugs.push(aug); } diff --git a/src/PersonObjects/Sleeve/ui/SleeveAugmentationsModal.tsx b/src/PersonObjects/Sleeve/ui/SleeveAugmentationsModal.tsx index 76e5c73a3..0fe9a52e0 100644 --- a/src/PersonObjects/Sleeve/ui/SleeveAugmentationsModal.tsx +++ b/src/PersonObjects/Sleeve/ui/SleeveAugmentationsModal.tsx @@ -4,7 +4,6 @@ import { PurchasableAugmentations } from "../../../Augmentation/ui/PurchasableAu import { Player } from "../../../Player"; import { Modal } from "../../../ui/React/Modal"; import { Sleeve } from "../Sleeve"; -import { findSleevePurchasableAugs } from "../SleeveHelpers"; interface IProps { open: boolean; @@ -29,7 +28,7 @@ export function SleeveAugmentationsModal(props: IProps): React.ReactElement { // You can only purchase Augmentations that are actually available from // your factions. I.e. you must be in a faction that has the Augmentation // and you must also have enough rep in that faction in order to purchase it. - const availableAugs = findSleevePurchasableAugs(props.sleeve); + const availableAugs = props.sleeve.findPurchasableAugs(); return ( From c510e478855595c0b47d37999ae9b1a68fe408a1 Mon Sep 17 00:00:00 2001 From: Snarling <84951833+Snarling@users.noreply.github.com> Date: Tue, 20 Sep 2022 01:57:46 -0400 Subject: [PATCH 24/46] Player is now a Person Use correct class inheritance, use class as type and remove IPlayer --- src/Bladeburner/Action.tsx | 10 +- src/Bladeburner/Bladeburner.tsx | 18 +- src/Bladeburner/IAction.tsx | 10 +- src/Bladeburner/IBladeburner.ts | 18 +- src/CotMG/StaneksGift.ts | 2 +- src/Crime/Crime.ts | 4 +- src/Crime/formulas/crime.ts | 40 ---- src/Faction/formulas/donation.ts | 4 +- src/Hacking.ts | 14 +- src/Netscript/NetscriptHelpers.ts | 6 +- src/PersonObjects/IPerson.ts | 33 --- src/PersonObjects/Person.ts | 134 ++--------- src/PersonObjects/PersonMethods.ts | 199 ++++++++++++++++ src/PersonObjects/Player/PlayerObject.ts | 53 +---- .../Player/PlayerObjectGeneralMethods.ts | 220 ------------------ src/PersonObjects/Sleeve/Sleeve.ts | 5 +- src/PersonObjects/Sleeve/SleeveMethods.ts | 9 +- src/PersonObjects/formulas/reputation.ts | 8 +- src/PersonObjects/formulas/skill.ts | 4 + src/Server/formulas/grow.ts | 4 +- src/Work/WorkStats.ts | 6 +- src/Work/formulas/Class.ts | 4 +- src/Work/formulas/Company.ts | 4 +- src/Work/formulas/Faction.ts | 6 +- 24 files changed, 297 insertions(+), 518 deletions(-) delete mode 100644 src/Crime/formulas/crime.ts delete mode 100644 src/PersonObjects/IPerson.ts create mode 100644 src/PersonObjects/PersonMethods.ts diff --git a/src/Bladeburner/Action.tsx b/src/Bladeburner/Action.tsx index 90a735046..9ec88479a 100644 --- a/src/Bladeburner/Action.tsx +++ b/src/Bladeburner/Action.tsx @@ -5,7 +5,7 @@ import { Generic_fromJSON, Generic_toJSON, IReviverValue, Reviver } from "../uti import { BladeburnerConstants } from "./data/Constants"; import { IBladeburner } from "./IBladeburner"; import { IAction, ISuccessChanceParams } from "./IAction"; -import { IPerson } from "../PersonObjects/IPerson"; +import { Person } from "../PersonObjects/Person"; class StatsMultiplier { [key: string]: number; @@ -153,7 +153,7 @@ export class Action implements IAction { * Tests for success. Should be called when an action has completed * @param inst {Bladeburner} - Bladeburner instance */ - attempt(inst: IBladeburner, person: IPerson): boolean { + attempt(inst: IBladeburner, person: Person): boolean { return Math.random() < this.getSuccessChance(inst, person); } @@ -162,7 +162,7 @@ export class Action implements IAction { return 1; } - getActionTime(inst: IBladeburner, person: IPerson): number { + getActionTime(inst: IBladeburner, person: Person): number { const difficulty = this.getDifficulty(); let baseTime = difficulty / BladeburnerConstants.DifficultyToTimeFactor; const skillFac = inst.skillMultipliers.actionTime; // Always < 1 @@ -212,7 +212,7 @@ export class Action implements IAction { return 1; } - getEstSuccessChance(inst: IBladeburner, person: IPerson): [number, number] { + getEstSuccessChance(inst: IBladeburner, person: Person): [number, number] { function clamp(x: number): number { return Math.max(0, Math.min(x, 1)); } @@ -233,7 +233,7 @@ export class Action implements IAction { * @params - options: * est (bool): Get success chance estimate instead of real success chance */ - getSuccessChance(inst: IBladeburner, person: IPerson, params: ISuccessChanceParams = { est: false }): number { + getSuccessChance(inst: IBladeburner, person: Person, params: ISuccessChanceParams = { est: false }): number { if (inst == null) { throw new Error("Invalid Bladeburner instance passed into Action.getSuccessChance"); } diff --git a/src/Bladeburner/Bladeburner.tsx b/src/Bladeburner/Bladeburner.tsx index 66e4bda0f..c52b72431 100644 --- a/src/Bladeburner/Bladeburner.tsx +++ b/src/Bladeburner/Bladeburner.tsx @@ -16,7 +16,7 @@ import { City } from "./City"; import { IAction } from "./IAction"; import { Player } from "../Player"; import { createTaskTracker, ITaskTracker } from "../PersonObjects/ITaskTracker"; -import { IPerson } from "../PersonObjects/IPerson"; +import { Person } from "../PersonObjects/Person"; import { Router } from "../ui/GameRoot"; import { ConsoleHelpText } from "./data/Help"; import { exceptionAlert } from "../utils/helpers/exceptionAlert"; @@ -995,7 +995,7 @@ export class Bladeburner implements IBladeburner { * @param action(Action obj) - Derived action class * @param success(bool) - Whether action was successful */ - getActionStats(action: IAction, person: IPerson, success: boolean): ITaskTracker { + getActionStats(action: IAction, person: Person, success: boolean): ITaskTracker { const difficulty = action.getDifficulty(); /** @@ -1025,7 +1025,7 @@ export class Bladeburner implements IBladeburner { }; } - getDiplomacyEffectiveness(person: IPerson): number { + getDiplomacyEffectiveness(person: Person): number { // Returns a decimal by which the city's chaos level should be multiplied (e.g. 0.98) const CharismaLinearFactor = 1e3; const CharismaExponentialFactor = 0.045; @@ -1035,11 +1035,11 @@ export class Bladeburner implements IBladeburner { return (100 - charismaEff) / 100; } - getRecruitmentSuccessChance(person: IPerson): number { + getRecruitmentSuccessChance(person: Person): number { return Math.pow(person.skills.charisma, 0.45) / (this.teamSize - this.sleeveSize + 1); } - getRecruitmentTime(person: IPerson): number { + getRecruitmentTime(person: Person): number { const effCharisma = person.skills.charisma * this.skillMultipliers.effCha; const charismaFactor = Math.pow(effCharisma, 0.81) + effCharisma / 90; return Math.max(10, Math.round(BladeburnerConstants.BaseRecruitmentTimeNeeded - charismaFactor)); @@ -1257,7 +1257,7 @@ export class Bladeburner implements IBladeburner { } } - completeAction(person: IPerson, actionIdent: IActionIdentifier, isPlayer = true): ITaskTracker { + completeAction(person: Person, actionIdent: IActionIdentifier, isPlayer = true): ITaskTracker { let retValue = createTaskTracker(); switch (actionIdent.type) { case ActionTypes["Contract"]: @@ -1610,7 +1610,7 @@ export class Bladeburner implements IBladeburner { } } - changeRank(person: IPerson, change: number): void { + changeRank(person: Person, change: number): void { if (isNaN(change)) { throw new Error("NaN passed into Bladeburner.changeRank()"); } @@ -2146,7 +2146,7 @@ export class Bladeburner implements IBladeburner { } } - getActionTimeNetscriptFn(person: IPerson, type: string, name: string): number | string { + getActionTimeNetscriptFn(person: Person, type: string, name: string): number | string { const actionId = this.getActionIdFromTypeAndName(type, name); if (actionId == null) { return "bladeburner.getActionTime"; @@ -2177,7 +2177,7 @@ export class Bladeburner implements IBladeburner { } } - getActionEstimatedSuccessChanceNetscriptFn(person: IPerson, type: string, name: string): [number, number] | string { + getActionEstimatedSuccessChanceNetscriptFn(person: Person, type: string, name: string): [number, number] | string { const actionId = this.getActionIdFromTypeAndName(type, name); if (actionId == null) { return "bladeburner.getActionEstimatedSuccessChance"; diff --git a/src/Bladeburner/IAction.tsx b/src/Bladeburner/IAction.tsx index 55202d638..0f396fa32 100644 --- a/src/Bladeburner/IAction.tsx +++ b/src/Bladeburner/IAction.tsx @@ -1,5 +1,5 @@ import { IReviverValue } from "../utils/JSONReviver"; -import { IPerson } from "../PersonObjects/IPerson"; +import { Person } from "../PersonObjects/Person"; import { IBladeburner } from "./IBladeburner"; interface IStatsMultiplier { @@ -57,15 +57,15 @@ export interface IAction { teamCount: number; getDifficulty(): number; - attempt(inst: IBladeburner, person: IPerson): boolean; + attempt(inst: IBladeburner, person: Person): boolean; getActionTimePenalty(): number; - getActionTime(inst: IBladeburner, person: IPerson): number; + getActionTime(inst: IBladeburner, person: Person): number; getTeamSuccessBonus(inst: IBladeburner): number; getActionTypeSkillSuccessBonus(inst: IBladeburner): number; getChaosCompetencePenalty(inst: IBladeburner, params: ISuccessChanceParams): number; getChaosDifficultyBonus(inst: IBladeburner): number; - getEstSuccessChance(inst: IBladeburner, person: IPerson): [number, number]; - getSuccessChance(inst: IBladeburner, person: IPerson, params: ISuccessChanceParams): number; + getEstSuccessChance(inst: IBladeburner, person: Person): [number, number]; + getSuccessChance(inst: IBladeburner, person: Person, params: ISuccessChanceParams): number; getSuccessesNeededForNextLevel(baseSuccessesPerLevel: number): number; setMaxLevel(baseSuccessesPerLevel: number): void; toJSON(): IReviverValue; diff --git a/src/Bladeburner/IBladeburner.ts b/src/Bladeburner/IBladeburner.ts index 80062b3c2..0f3353ba1 100644 --- a/src/Bladeburner/IBladeburner.ts +++ b/src/Bladeburner/IBladeburner.ts @@ -2,7 +2,7 @@ import { IActionIdentifier } from "./IActionIdentifier"; import { City } from "./City"; import { Skill } from "./Skill"; import { IAction } from "./IAction"; -import { IPerson } from "../PersonObjects/IPerson"; +import { Person } from "../PersonObjects/Person"; import { ITaskTracker } from "../PersonObjects/ITaskTracker"; import { WorkerScript } from "../Netscript/WorkerScript"; import { Contract } from "./Contract"; @@ -82,8 +82,8 @@ export interface IBladeburner { getGeneralActionNamesNetscriptFn(): string[]; getSkillNamesNetscriptFn(): string[]; startActionNetscriptFn(type: string, name: string, workerScript: WorkerScript): boolean; - getActionTimeNetscriptFn(person: IPerson, type: string, name: string): number | string; - getActionEstimatedSuccessChanceNetscriptFn(person: IPerson, type: string, name: string): [number, number] | string; + getActionTimeNetscriptFn(person: Person, type: string, name: string): number | string; + getActionEstimatedSuccessChanceNetscriptFn(person: Person, type: string, name: string): [number, number] | string; getActionCountRemainingNetscriptFn(type: string, name: string, workerScript: WorkerScript): number; getSkillLevelNetscriptFn(skillName: string, workerScript: WorkerScript): number; getSkillUpgradeCostNetscriptFn(skillName: string, count: number, workerScript: WorkerScript): number; @@ -102,23 +102,23 @@ export interface IBladeburner { triggerMigration(sourceCityName: string): void; triggerPotentialMigration(sourceCityName: string, chance: number): void; randomEvent(): void; - getDiplomacyEffectiveness(person: IPerson): number; - getRecruitmentSuccessChance(person: IPerson): number; - getRecruitmentTime(person: IPerson): number; + getDiplomacyEffectiveness(person: Person): number; + getRecruitmentSuccessChance(person: Person): number; + getRecruitmentTime(person: Person): number; resetSkillMultipliers(): void; updateSkillMultipliers(): void; completeOperation(success: boolean): void; getActionObject(actionId: IActionIdentifier): IAction | null; completeContract(success: boolean, actionIdent: IActionIdentifier): void; - completeAction(person: IPerson, actionIdent: IActionIdentifier, isPlayer?: boolean): ITaskTracker; + completeAction(person: Person, actionIdent: IActionIdentifier, isPlayer?: boolean): ITaskTracker; infiltrateSynthoidCommunities(): void; - changeRank(person: IPerson, change: number): void; + changeRank(person: Person, change: number): void; processAction(seconds: number): void; calculateStaminaGainPerSecond(): number; calculateMaxStamina(): void; create(): void; process(): void; - getActionStats(action: IAction, person: IPerson, success: boolean): ITaskTracker; + getActionStats(action: IAction, person: Person, success: boolean): ITaskTracker; sleeveSupport(joining: boolean): void; toJSON(): IReviverValue; } diff --git a/src/CotMG/StaneksGift.ts b/src/CotMG/StaneksGift.ts index 2943eee4c..876f9e41d 100644 --- a/src/CotMG/StaneksGift.ts +++ b/src/CotMG/StaneksGift.ts @@ -225,7 +225,7 @@ export class StaneksGift implements IStaneksGift { if (!sleeve.hasAugmentation(AugmentationNames.ZOE)) continue; sleeve.resetMultipliers(); sleeve.mults = mergeMultipliers(sleeve.mults, sleeveMults); - sleeve.updateStatLevels(); + sleeve.updateSkillLevels(); } } diff --git a/src/Crime/Crime.ts b/src/Crime/Crime.ts index 8edf124f8..399518581 100644 --- a/src/Crime/Crime.ts +++ b/src/Crime/Crime.ts @@ -1,6 +1,6 @@ import { CONSTANTS } from "../Constants"; import { Player } from "../Player"; -import { IPerson } from "../PersonObjects/IPerson"; +import { Person } from "../PersonObjects/Person"; import { WorkerScript } from "../Netscript/WorkerScript"; import { CrimeType } from "../utils/WorkType"; import { CrimeWork } from "../Work/CrimeWork"; @@ -115,7 +115,7 @@ export class Crime { return this.time; } - successRate(p: IPerson): number { + successRate(p: Person): number { let chance: number = this.hacking_success_weight * p.skills.hacking + this.strength_success_weight * p.skills.strength + diff --git a/src/Crime/formulas/crime.ts b/src/Crime/formulas/crime.ts deleted file mode 100644 index 0a896028b..000000000 --- a/src/Crime/formulas/crime.ts +++ /dev/null @@ -1,40 +0,0 @@ -import { calculateIntelligenceBonus } from "../../PersonObjects/formulas/intelligence"; -import { CONSTANTS } from "../../Constants"; - -export interface ICrime { - hacking_success_weight: number; - strength_success_weight: number; - defense_success_weight: number; - dexterity_success_weight: number; - agility_success_weight: number; - charisma_success_weight: number; - difficulty: number; -} - -export interface IPerson { - hacking: number; - strength: number; - defense: number; - dexterity: number; - agility: number; - charisma: number; - intelligence: number; - crime_success_mult: number; -} - -export function calculateCrimeSuccessChance(crime: ICrime, person: IPerson): number { - let chance: number = - crime.hacking_success_weight * person.hacking + - crime.strength_success_weight * person.strength + - crime.defense_success_weight * person.defense + - crime.dexterity_success_weight * person.dexterity + - crime.agility_success_weight * person.agility + - crime.charisma_success_weight * person.charisma + - CONSTANTS.IntelligenceCrimeWeight * person.intelligence; - chance /= CONSTANTS.MaxSkillLevel; - chance /= crime.difficulty; - chance *= person.crime_success_mult; - chance *= calculateIntelligenceBonus(person.intelligence); - - return Math.min(chance, 1); -} diff --git a/src/Faction/formulas/donation.ts b/src/Faction/formulas/donation.ts index 0bcd8c645..14d14bfaf 100644 --- a/src/Faction/formulas/donation.ts +++ b/src/Faction/formulas/donation.ts @@ -1,6 +1,6 @@ import { CONSTANTS } from "../../Constants"; -import { IPerson } from "../../PersonObjects/IPerson"; +import { Person } from "../../PersonObjects/Person"; -export function repFromDonation(amt: number, person: IPerson): number { +export function repFromDonation(amt: number, person: Person): number { return (amt / CONSTANTS.DonateMoneyToRepDivisor) * person.mults.faction_rep; } diff --git a/src/Hacking.ts b/src/Hacking.ts index 91feb8883..d0febe357 100644 --- a/src/Hacking.ts +++ b/src/Hacking.ts @@ -1,12 +1,12 @@ import { BitNodeMultipliers } from "./BitNode/BitNodeMultipliers"; -import { IPerson } from "./PersonObjects/IPerson"; +import { Person } from "./PersonObjects/Person"; import { calculateIntelligenceBonus } from "./PersonObjects/formulas/intelligence"; import { Server } from "./Server/Server"; /** * Returns the chance the person has to successfully hack a server */ -export function calculateHackingChance(server: Server, person: IPerson): number { +export function calculateHackingChance(server: Server, person: Person): number { const hackFactor = 1.75; const difficultyMult = (100 - server.hackDifficulty) / 100; const skillMult = hackFactor * person.skills.hacking; @@ -30,7 +30,7 @@ export function calculateHackingChance(server: Server, person: IPerson): number * Returns the amount of hacking experience the person will gain upon * successfully hacking a server */ -export function calculateHackingExpGain(server: Server, person: IPerson): number { +export function calculateHackingExpGain(server: Server, person: Person): number { const baseExpGain = 3; const diffFactor = 0.3; if (server.baseDifficulty == null) { @@ -46,7 +46,7 @@ export function calculateHackingExpGain(server: Server, person: IPerson): number * Returns the percentage of money that will be stolen from a server if * it is successfully hacked (returns the decimal form, not the actual percent value) */ -export function calculatePercentMoneyHacked(server: Server, person: IPerson): number { +export function calculatePercentMoneyHacked(server: Server, person: Person): number { // Adjust if needed for balancing. This is the divisor for the final calculation const balanceFactor = 240; @@ -67,7 +67,7 @@ export function calculatePercentMoneyHacked(server: Server, person: IPerson): nu /** * Returns time it takes to complete a hack on a server, in seconds */ -export function calculateHackingTime(server: Server, person: IPerson): number { +export function calculateHackingTime(server: Server, person: Person): number { const difficultyMult = server.requiredHackingSkill * server.hackDifficulty; const baseDiff = 500; @@ -88,7 +88,7 @@ export function calculateHackingTime(server: Server, person: IPerson): number { /** * Returns time it takes to complete a grow operation on a server, in seconds */ -export function calculateGrowTime(server: Server, person: IPerson): number { +export function calculateGrowTime(server: Server, person: Person): number { const growTimeMultiplier = 3.2; // Relative to hacking time. 16/5 = 3.2 return growTimeMultiplier * calculateHackingTime(server, person); @@ -97,7 +97,7 @@ export function calculateGrowTime(server: Server, person: IPerson): number { /** * Returns time it takes to complete a weaken operation on a server, in seconds */ -export function calculateWeakenTime(server: Server, person: IPerson): number { +export function calculateWeakenTime(server: Server, person: Person): number { const weakenTimeMultiplier = 4; // Relative to hacking time return weakenTimeMultiplier * calculateHackingTime(server, person); diff --git a/src/Netscript/NetscriptHelpers.ts b/src/Netscript/NetscriptHelpers.ts index 79a2dc2bb..be1cae56c 100644 --- a/src/Netscript/NetscriptHelpers.ts +++ b/src/Netscript/NetscriptHelpers.ts @@ -21,7 +21,7 @@ import { CONSTANTS } from "../Constants"; import { influenceStockThroughServerHack } from "../StockMarket/PlayerInfluencing"; import { IPort, NetscriptPort } from "../NetscriptPort"; import { NetscriptPorts } from "../NetscriptWorker"; -import { IPerson } from "../PersonObjects/IPerson"; +import { Person } from "../PersonObjects/Person"; import { FormulaGang } from "../Gang/formulas/formulas"; import { GangMember } from "../Gang/GangMember"; import { GangMemberTask } from "../Gang/GangMemberTask"; @@ -498,7 +498,7 @@ function getValidPort(ctx: NetscriptContext, port: number): IPort { return iport; } -function player(ctx: NetscriptContext, p: unknown): IPerson { +function player(ctx: NetscriptContext, p: unknown): Person { const fakePlayer = { hp: undefined, mults: undefined, @@ -518,7 +518,7 @@ function player(ctx: NetscriptContext, p: unknown): IPerson { entropy: undefined, }; if (!roughlyIs(fakePlayer, p)) throw makeRuntimeErrorMsg(ctx, `player should be a Player.`, "TYPE"); - return p as IPerson; + return p as Person; } function server(ctx: NetscriptContext, s: unknown): Server { diff --git a/src/PersonObjects/IPerson.ts b/src/PersonObjects/IPerson.ts deleted file mode 100644 index f1611d483..000000000 --- a/src/PersonObjects/IPerson.ts +++ /dev/null @@ -1,33 +0,0 @@ -// Interface that represents either the player (PlayerObject) or -// a Sleeve. Used for functions that need to take in both. - -import { IPlayerOwnedAugmentation } from "../Augmentation/PlayerOwnedAugmentation"; -import { HP } from "./HP"; -import { ITaskTracker } from "./ITaskTracker"; -import { Multipliers } from "./Multipliers"; -import { Skills } from "./Skills"; - -export interface IPerson { - hp: HP; - skills: Skills; - exp: Skills; - - mults: Multipliers; - - augmentations: IPlayerOwnedAugmentation[]; - - getIntelligenceBonus(weight: number): number; - gainHackingExp(exp: number): void; - gainStrengthExp(exp: number): void; - gainDefenseExp(exp: number): void; - gainDexterityExp(exp: number): void; - gainAgilityExp(exp: number): void; - gainCharismaExp(exp: number): void; - gainIntelligenceExp(exp: number): void; - gainStats(retValue: ITaskTracker): void; - calculateSkill(exp: number, mult?: number): number; - takeDamage(amt: number): boolean; - regenerateHp: (amt: number) => void; - queryStatFromString: (str: string) => number; - whoAmI: () => string; -} diff --git a/src/PersonObjects/Person.ts b/src/PersonObjects/Person.ts index c08cc38dd..794f2ed62 100644 --- a/src/PersonObjects/Person.ts +++ b/src/PersonObjects/Person.ts @@ -1,18 +1,15 @@ -import * as generalMethods from "./Player/PlayerObjectGeneralMethods"; -import { Augmentation } from "../Augmentation/Augmentation"; +import * as personMethods from "./PersonMethods"; import { IPlayerOwnedAugmentation } from "../Augmentation/PlayerOwnedAugmentation"; -import { BitNodeMultipliers } from "../BitNode/BitNodeMultipliers"; import { CityName } from "../Locations/data/CityNames"; -import { CONSTANTS } from "../Constants"; import { calculateSkill } from "./formulas/skill"; import { calculateIntelligenceBonus } from "./formulas/intelligence"; -import { IPerson } from "./IPerson"; -import { defaultMultipliers, mergeAugmentation } from "./Multipliers"; +import { defaultMultipliers } from "./Multipliers"; import { Skills } from "./Skills"; import { HP } from "./HP"; +import { IReviverValue } from "../utils/JSONReviver"; // Base class representing a person-like object -export abstract class Person implements IPerson { +export abstract class Person { hp: HP = { current: 10, max: 10 }; skills: Skills = { hacking: 1, @@ -45,126 +42,31 @@ export abstract class Person implements IPerson { */ city: CityName = CityName.Sector12; - gainHackingExp = generalMethods.gainHackingExp; - gainStrengthExp = generalMethods.gainStrengthExp; - gainDefenseExp = generalMethods.gainDefenseExp; - gainDexterityExp = generalMethods.gainDexterityExp; - gainAgilityExp = generalMethods.gainAgilityExp; - gainCharismaExp = generalMethods.gainCharismaExp; - gainIntelligenceExp = generalMethods.gainIntelligenceExp; - gainStats = generalMethods.gainStats; - calculateSkill = generalMethods.calculateSkill; - regenerateHp = generalMethods.regenerateHp; - queryStatFromString = generalMethods.queryStatFromString; - - /** - * Updates this object's multipliers for the given augmentation - */ - applyAugmentation(aug: Augmentation): void { - this.mults = mergeAugmentation(this.mults, aug.mults); - } - - /** - * Given an experience amount and stat multiplier, calculates the - * stat level. Stat-agnostic (same formula for every stat) - */ - calculateStat(exp: number, mult = 1): number { - return calculateSkill(exp, mult); - } - - /** - * Calculate and return the amount of faction reputation earned per cycle - * when doing Field Work for a faction - */ - getFactionFieldWorkRepGain(): number { - const t = - (0.9 * - (this.skills.hacking / CONSTANTS.MaxSkillLevel + - this.skills.strength / CONSTANTS.MaxSkillLevel + - this.skills.defense / CONSTANTS.MaxSkillLevel + - this.skills.dexterity / CONSTANTS.MaxSkillLevel + - this.skills.agility / CONSTANTS.MaxSkillLevel + - this.skills.charisma / CONSTANTS.MaxSkillLevel)) / - 5.5; - return t * this.mults.faction_rep; - } - - /** - * Calculate and return the amount of faction reputation earned per cycle - * when doing Hacking Work for a faction - */ - getFactionHackingWorkRepGain(): number { - return (this.skills.hacking / CONSTANTS.MaxSkillLevel) * this.mults.faction_rep; - } - - /** - * Calculate and return the amount of faction reputation earned per cycle - * when doing Security Work for a faction - */ - getFactionSecurityWorkRepGain(): number { - const t = - (0.9 * - (this.skills.hacking / CONSTANTS.MaxSkillLevel + - this.skills.strength / CONSTANTS.MaxSkillLevel + - this.skills.defense / CONSTANTS.MaxSkillLevel + - this.skills.dexterity / CONSTANTS.MaxSkillLevel + - this.skills.agility / CONSTANTS.MaxSkillLevel)) / - 4.5; - return t * this.mults.faction_rep; - } + gainHackingExp = personMethods.gainHackingExp; + gainStrengthExp = personMethods.gainStrengthExp; + gainDefenseExp = personMethods.gainDefenseExp; + gainDexterityExp = personMethods.gainDexterityExp; + gainAgilityExp = personMethods.gainAgilityExp; + gainCharismaExp = personMethods.gainCharismaExp; + gainIntelligenceExp = personMethods.gainIntelligenceExp; + gainStats = personMethods.gainStats; + regenerateHp = personMethods.regenerateHp; + queryStatFromString = personMethods.queryStatFromString; + updateSkillLevels = personMethods.updateSkillLevels; + calculateSkill = calculateSkill; //Class version is equal to imported version /** * Reset all multipliers to 1 */ - resetMultipliers(): void { + resetMultipliers() { this.mults = defaultMultipliers(); } - /** - * Update all stat levels - */ - updateStatLevels(): void { - this.skills.hacking = Math.max( - 1, - Math.floor(this.calculateStat(this.exp.hacking, this.mults.hacking * BitNodeMultipliers.HackingLevelMultiplier)), - ); - this.skills.strength = Math.max( - 1, - Math.floor( - this.calculateStat(this.exp.strength, this.mults.strength * BitNodeMultipliers.StrengthLevelMultiplier), - ), - ); - this.skills.defense = Math.max( - 1, - Math.floor(this.calculateStat(this.exp.defense, this.mults.defense * BitNodeMultipliers.DefenseLevelMultiplier)), - ); - this.skills.dexterity = Math.max( - 1, - Math.floor( - this.calculateStat(this.exp.dexterity, this.mults.dexterity * BitNodeMultipliers.DexterityLevelMultiplier), - ), - ); - this.skills.agility = Math.max( - 1, - Math.floor(this.calculateStat(this.exp.agility, this.mults.agility * BitNodeMultipliers.AgilityLevelMultiplier)), - ); - this.skills.charisma = Math.max( - 1, - Math.floor( - this.calculateStat(this.exp.charisma, this.mults.charisma * BitNodeMultipliers.CharismaLevelMultiplier), - ), - ); - - const ratio: number = this.hp.current / this.hp.max; - this.hp.max = Math.floor(10 + this.skills.defense / 10); - this.hp.current = Math.round(this.hp.max * ratio); - } - getIntelligenceBonus(weight: number): number { return calculateIntelligenceBonus(this.skills.intelligence, weight); } abstract takeDamage(amt: number): boolean; - abstract whoAmI(): string; + abstract toJSON(): IReviverValue; } diff --git a/src/PersonObjects/PersonMethods.ts b/src/PersonObjects/PersonMethods.ts new file mode 100644 index 000000000..b3657c438 --- /dev/null +++ b/src/PersonObjects/PersonMethods.ts @@ -0,0 +1,199 @@ +import { Person } from "./Person"; +import { calculateSkill } from "./formulas/skill"; +import { BitNodeMultipliers } from "../BitNode/BitNodeMultipliers"; +import { Player } from "../Player"; +import { ITaskTracker } from "./ITaskTracker"; + +export function gainHackingExp(this: Person, exp: number): void { + if (isNaN(exp)) { + console.error("ERR: NaN passed into Player.gainHackingExp()"); + return; + } + this.exp.hacking += exp; + if (this.exp.hacking < 0) { + this.exp.hacking = 0; + } + + this.skills.hacking = calculateSkill( + this.exp.hacking, + this.mults.hacking * BitNodeMultipliers.HackingLevelMultiplier, + ); +} + +export function gainStrengthExp(this: Person, exp: number): void { + if (isNaN(exp)) { + console.error("ERR: NaN passed into Player.gainStrengthExp()"); + return; + } + this.exp.strength += exp; + if (this.exp.strength < 0) { + this.exp.strength = 0; + } + + this.skills.strength = calculateSkill( + this.exp.strength, + this.mults.strength * BitNodeMultipliers.StrengthLevelMultiplier, + ); +} + +export function gainDefenseExp(this: Person, exp: number): void { + if (isNaN(exp)) { + console.error("ERR: NaN passed into player.gainDefenseExp()"); + return; + } + this.exp.defense += exp; + if (this.exp.defense < 0) { + this.exp.defense = 0; + } + + this.skills.defense = calculateSkill( + this.exp.defense, + this.mults.defense * BitNodeMultipliers.DefenseLevelMultiplier, + ); + const ratio = this.hp.current / this.hp.max; + this.hp.max = Math.floor(10 + this.skills.defense / 10); + this.hp.current = Math.round(this.hp.max * ratio); +} + +export function gainDexterityExp(this: Person, exp: number): void { + if (isNaN(exp)) { + console.error("ERR: NaN passed into Player.gainDexterityExp()"); + return; + } + this.exp.dexterity += exp; + if (this.exp.dexterity < 0) { + this.exp.dexterity = 0; + } + + this.skills.dexterity = calculateSkill( + this.exp.dexterity, + this.mults.dexterity * BitNodeMultipliers.DexterityLevelMultiplier, + ); +} + +export function gainAgilityExp(this: Person, exp: number): void { + if (isNaN(exp)) { + console.error("ERR: NaN passed into Player.gainAgilityExp()"); + return; + } + this.exp.agility += exp; + if (this.exp.agility < 0) { + this.exp.agility = 0; + } + + this.skills.agility = calculateSkill( + this.exp.agility, + this.mults.agility * BitNodeMultipliers.AgilityLevelMultiplier, + ); +} + +export function gainCharismaExp(this: Person, exp: number): void { + if (isNaN(exp)) { + console.error("ERR: NaN passed into Player.gainCharismaExp()"); + return; + } + this.exp.charisma += exp; + if (this.exp.charisma < 0) { + this.exp.charisma = 0; + } + + this.skills.charisma = calculateSkill( + this.exp.charisma, + this.mults.charisma * BitNodeMultipliers.CharismaLevelMultiplier, + ); +} + +export function gainIntelligenceExp(this: Person, exp: number): void { + if (isNaN(exp)) { + console.error("ERROR: NaN passed into Player.gainIntelligenceExp()"); + return; + } + if (Player.sourceFileLvl(5) > 0 || this.skills.intelligence > 0 || Player.bitNodeN === 5) { + this.exp.intelligence += exp; + this.skills.intelligence = Math.floor(this.calculateSkill(this.exp.intelligence, 1)); + } +} +export function gainStats(this: Person, retValue: ITaskTracker): void { + this.gainHackingExp(retValue.hack * this.mults.hacking_exp); + this.gainStrengthExp(retValue.str * this.mults.strength_exp); + this.gainDefenseExp(retValue.def * this.mults.defense_exp); + this.gainDexterityExp(retValue.dex * this.mults.dexterity_exp); + this.gainAgilityExp(retValue.agi * this.mults.agility_exp); + this.gainCharismaExp(retValue.cha * this.mults.charisma_exp); + this.gainIntelligenceExp(retValue.int); +} + +//Given a string expression like "str" or "strength", returns the given stat +export function queryStatFromString(this: Person, str: string): number { + const tempStr = str.toLowerCase(); + if (tempStr.includes("hack")) { + return this.skills.hacking; + } + if (tempStr.includes("str")) { + return this.skills.strength; + } + if (tempStr.includes("def")) { + return this.skills.defense; + } + if (tempStr.includes("dex")) { + return this.skills.dexterity; + } + if (tempStr.includes("agi")) { + return this.skills.agility; + } + if (tempStr.includes("cha")) { + return this.skills.charisma; + } + if (tempStr.includes("int")) { + return this.skills.intelligence; + } + return 0; +} + +export function regenerateHp(this: Person, amt: number): void { + if (typeof amt !== "number") { + console.warn(`Player.regenerateHp() called without a numeric argument: ${amt}`); + return; + } + this.hp.current += amt; + if (this.hp.current > this.hp.max) { + this.hp.current = this.hp.max; + } +} + +export function updateSkillLevels(this: Person): void { + this.skills.hacking = Math.max( + 1, + Math.floor(this.calculateSkill(this.exp.hacking, this.mults.hacking * BitNodeMultipliers.HackingLevelMultiplier)), + ); + this.skills.strength = Math.max( + 1, + Math.floor( + this.calculateSkill(this.exp.strength, this.mults.strength * BitNodeMultipliers.StrengthLevelMultiplier), + ), + ); + this.skills.defense = Math.max( + 1, + Math.floor(this.calculateSkill(this.exp.defense, this.mults.defense * BitNodeMultipliers.DefenseLevelMultiplier)), + ); + this.skills.dexterity = Math.max( + 1, + Math.floor( + this.calculateSkill(this.exp.dexterity, this.mults.dexterity * BitNodeMultipliers.DexterityLevelMultiplier), + ), + ); + this.skills.agility = Math.max( + 1, + Math.floor(this.calculateSkill(this.exp.agility, this.mults.agility * BitNodeMultipliers.AgilityLevelMultiplier)), + ); + this.skills.charisma = Math.max( + 1, + Math.floor( + this.calculateSkill(this.exp.charisma, this.mults.charisma * BitNodeMultipliers.CharismaLevelMultiplier), + ), + ); + + const ratio: number = this.hp.current / this.hp.max; + this.hp.max = Math.floor(10 + this.skills.defense / 10); + this.hp.current = Math.round(this.hp.max * ratio); +} diff --git a/src/PersonObjects/Player/PlayerObject.ts b/src/PersonObjects/Player/PlayerObject.ts index af67f569a..e083fb46a 100644 --- a/src/PersonObjects/Player/PlayerObject.ts +++ b/src/PersonObjects/Player/PlayerObject.ts @@ -11,7 +11,6 @@ import { Sleeve } from "../Sleeve/Sleeve"; import { IPlayerOwnedSourceFile } from "../../SourceFile/PlayerOwnedSourceFile"; import { Exploit } from "../../Exploits/Exploit"; -import { IPerson } from "../IPerson"; import { LocationName } from "../../Locations/data/LocationNames"; import { IPlayerOwnedAugmentation } from "../../Augmentation/PlayerOwnedAugmentation"; import { ICorporation } from "../../Corporation/ICorporation"; @@ -20,7 +19,6 @@ import { IBladeburner } from "../../Bladeburner/IBladeburner"; import { HacknetNode } from "../../Hacknet/HacknetNode"; import { HashManager } from "../../Hacknet/HashManager"; -import { CityName } from "../../Locations/data/CityNames"; import { MoneySourceTracker } from "../../utils/MoneySourceTracker"; import { Reviver, Generic_toJSON, Generic_fromJSON, IReviverValue } from "../../utils/JSONReviver"; @@ -29,15 +27,11 @@ import { cyrb53 } from "../../utils/StringHelperFunctions"; import { getRandomInt } from "../../utils/helpers/getRandomInt"; import { CONSTANTS } from "../../Constants"; import { Work } from "src/Work/Work"; -import { defaultMultipliers } from "../Multipliers"; -import { HP } from "../HP"; -import { Skills } from "../Skills"; +import { Person } from "../Person"; -export class PlayerObject implements IPerson { - // Class members - augmentations: IPlayerOwnedAugmentation[] = []; +export class PlayerObject extends Person { + // Player-specific properties bitNodeN = 1; //current bitnode - city = CityName.Sector12; corporation: ICorporation | null = null; gang: IGang | null = null; bladeburner: IBladeburner | null = null; @@ -73,34 +67,12 @@ export class PlayerObject implements IPerson { lastSave = 0; totalPlaytime = 0; - hp: HP = { current: 10, max: 10 }; - skills: Skills = { - hacking: 1, - strength: 1, - defense: 1, - dexterity: 1, - agility: 1, - charisma: 1, - intelligence: 0, - }; - exp: Skills = { - hacking: 0, - strength: 0, - defense: 0, - dexterity: 0, - agility: 0, - charisma: 0, - intelligence: 0, - }; - - mults = defaultMultipliers(); - currentWork: Work | null = null; focus = false; entropy = 0; - // Methods + // Player-specific methods init = generalMethods.init; startWork = workMethods.startWork; processWork = workMethods.processWork; @@ -124,14 +96,6 @@ export class PlayerObject implements IPerson { canAccessGang = gangMethods.canAccessGang; canAccessGrafting = generalMethods.canAccessGrafting; canAfford = generalMethods.canAfford; - gainHackingExp = generalMethods.gainHackingExp; - gainStrengthExp = generalMethods.gainStrengthExp; - gainDefenseExp = generalMethods.gainDefenseExp; - gainDexterityExp = generalMethods.gainDexterityExp; - gainAgilityExp = generalMethods.gainAgilityExp; - gainCharismaExp = generalMethods.gainCharismaExp; - gainIntelligenceExp = generalMethods.gainIntelligenceExp; - gainStats = generalMethods.gainStats; gainMoney = generalMethods.gainMoney; getCurrentServer = serverMethods.getCurrentServer; getGangFaction = gangMethods.getGangFaction; @@ -153,7 +117,6 @@ export class PlayerObject implements IPerson { loseMoney = generalMethods.loseMoney; reapplyAllAugmentations = generalMethods.reapplyAllAugmentations; reapplyAllSourceFiles = generalMethods.reapplyAllSourceFiles; - regenerateHp = generalMethods.regenerateHp; recordMoneySource = generalMethods.recordMoneySource; setMoney = generalMethods.setMoney; startBladeburner = bladeburnerMethods.startBladeburner; @@ -164,21 +127,16 @@ export class PlayerObject implements IPerson { travel = generalMethods.travel; giveExploit = generalMethods.giveExploit; giveAchievement = generalMethods.giveAchievement; - queryStatFromString = generalMethods.queryStatFromString; - getIntelligenceBonus = generalMethods.getIntelligenceBonus; getCasinoWinnings = generalMethods.getCasinoWinnings; quitJob = generalMethods.quitJob; hasJob = generalMethods.hasJob; createHacknetServer = serverMethods.createHacknetServer; queueAugmentation = generalMethods.queueAugmentation; receiveInvite = generalMethods.receiveInvite; - updateSkillLevels = generalMethods.updateSkillLevels; gainCodingContractReward = generalMethods.gainCodingContractReward; stopFocusing = generalMethods.stopFocusing; - resetMultipliers = generalMethods.resetMultipliers; prestigeAugmentation = generalMethods.prestigeAugmentation; prestigeSourceFile = generalMethods.prestigeSourceFile; - calculateSkill = generalMethods.calculateSkill; calculateSkillProgress = generalMethods.calculateSkillProgress; hospitalize = generalMethods.hospitalize; checkForFactionInvitations = generalMethods.checkForFactionInvitations; @@ -189,6 +147,7 @@ export class PlayerObject implements IPerson { focusPenalty = generalMethods.focusPenalty; constructor() { + super(); // Let's get a hash of some semi-random stuff so we have something unique. this.identifier = cyrb53( "I-" + @@ -219,4 +178,4 @@ export class PlayerObject implements IPerson { } } -Reviver.constructors.PlayerObject = PlayerObject; +Reviver.constructors.PlayerObject = PlayerObject; \ No newline at end of file diff --git a/src/PersonObjects/Player/PlayerObjectGeneralMethods.ts b/src/PersonObjects/Player/PlayerObjectGeneralMethods.ts index e44277f8f..f27c3bd50 100644 --- a/src/PersonObjects/Player/PlayerObjectGeneralMethods.ts +++ b/src/PersonObjects/Player/PlayerObjectGeneralMethods.ts @@ -24,11 +24,9 @@ import { LocationName } from "../../Locations/data/LocationNames"; import { Sleeve } from "../Sleeve/Sleeve"; import { isSleeveCompanyWork } from "../Sleeve/Work/SleeveCompanyWork"; import { - calculateSkill as calculateSkillF, calculateSkillProgress as calculateSkillProgressF, ISkillProgress, } from "../formulas/skill"; -import { calculateIntelligenceBonus } from "../formulas/intelligence"; import { GetServer, AddToAllServers, createUniqueRandomIp } from "../../Server/AllServers"; import { Server } from "../../Server/Server"; import { safetlyCreateUniqueServer } from "../../Server/ServerHelpers"; @@ -47,12 +45,8 @@ import { dialogBoxCreate } from "../../ui/React/DialogBox"; import { SnackbarEvents, ToastVariant } from "../../ui/React/Snackbar"; import { achievements } from "../../Achievements/Achievements"; import { FactionNames } from "../../Faction/data/FactionNames"; -import { ITaskTracker } from "../ITaskTracker"; -import { IPerson } from "../IPerson"; -import { Player } from "../../Player"; import { isCompanyWork } from "../../Work/CompanyWork"; -import { defaultMultipliers } from "../Multipliers"; import { serverMetadata } from "../../Server/data/servers"; export function init(this: PlayerObject): void { @@ -186,63 +180,11 @@ export function receiveInvite(this: PlayerObject, factionName: string): void { this.factionInvitations.push(factionName); } -//Calculates skill level based on experience. The same formula will be used for every skill -export function calculateSkill(this: IPerson, exp: number, mult = 1): number { - return calculateSkillF(exp, mult); -} - //Calculates skill level progress based on experience. The same formula will be used for every skill export function calculateSkillProgress(this: PlayerObject, exp: number, mult = 1): ISkillProgress { return calculateSkillProgressF(exp, mult); } -export function updateSkillLevels(this: PlayerObject): void { - this.skills.hacking = Math.max( - 1, - Math.floor(this.calculateSkill(this.exp.hacking, this.mults.hacking * BitNodeMultipliers.HackingLevelMultiplier)), - ); - this.skills.strength = Math.max( - 1, - Math.floor( - this.calculateSkill(this.exp.strength, this.mults.strength * BitNodeMultipliers.StrengthLevelMultiplier), - ), - ); - this.skills.defense = Math.max( - 1, - Math.floor(this.calculateSkill(this.exp.defense, this.mults.defense * BitNodeMultipliers.DefenseLevelMultiplier)), - ); - this.skills.dexterity = Math.max( - 1, - Math.floor( - this.calculateSkill(this.exp.dexterity, this.mults.dexterity * BitNodeMultipliers.DexterityLevelMultiplier), - ), - ); - this.skills.agility = Math.max( - 1, - Math.floor(this.calculateSkill(this.exp.agility, this.mults.agility * BitNodeMultipliers.AgilityLevelMultiplier)), - ); - this.skills.charisma = Math.max( - 1, - Math.floor( - this.calculateSkill(this.exp.charisma, this.mults.charisma * BitNodeMultipliers.CharismaLevelMultiplier), - ), - ); - - if (this.skills.intelligence > 0) { - this.skills.intelligence = Math.floor(this.calculateSkill(this.exp.intelligence)); - } else { - this.skills.intelligence = 0; - } - - const ratio = this.hp.current / this.hp.max; - this.hp.max = Math.floor(10 + this.skills.defense / 10); - this.hp.current = Math.round(this.hp.max * ratio); -} - -export function resetMultipliers(this: PlayerObject): void { - this.mults = defaultMultipliers(); -} - export function hasProgram(this: PlayerObject, programName: string): boolean { const home = this.getHomeComputer(); if (home == null) { @@ -306,153 +248,6 @@ export function recordMoneySource(this: PlayerObject, amt: number, source: strin this.moneySourceB.record(amt, source); } -export function gainHackingExp(this: IPerson, exp: number): void { - if (isNaN(exp)) { - console.error("ERR: NaN passed into Player.gainHackingExp()"); - return; - } - this.exp.hacking += exp; - if (this.exp.hacking < 0) { - this.exp.hacking = 0; - } - - this.skills.hacking = calculateSkillF( - this.exp.hacking, - this.mults.hacking * BitNodeMultipliers.HackingLevelMultiplier, - ); -} - -export function gainStrengthExp(this: IPerson, exp: number): void { - if (isNaN(exp)) { - console.error("ERR: NaN passed into Player.gainStrengthExp()"); - return; - } - this.exp.strength += exp; - if (this.exp.strength < 0) { - this.exp.strength = 0; - } - - this.skills.strength = calculateSkillF( - this.exp.strength, - this.mults.strength * BitNodeMultipliers.StrengthLevelMultiplier, - ); -} - -export function gainDefenseExp(this: IPerson, exp: number): void { - if (isNaN(exp)) { - console.error("ERR: NaN passed into player.gainDefenseExp()"); - return; - } - this.exp.defense += exp; - if (this.exp.defense < 0) { - this.exp.defense = 0; - } - - this.skills.defense = calculateSkillF( - this.exp.defense, - this.mults.defense * BitNodeMultipliers.DefenseLevelMultiplier, - ); - const ratio = this.hp.current / this.hp.max; - this.hp.max = Math.floor(10 + this.skills.defense / 10); - this.hp.current = Math.round(this.hp.max * ratio); -} - -export function gainDexterityExp(this: IPerson, exp: number): void { - if (isNaN(exp)) { - console.error("ERR: NaN passed into Player.gainDexterityExp()"); - return; - } - this.exp.dexterity += exp; - if (this.exp.dexterity < 0) { - this.exp.dexterity = 0; - } - - this.skills.dexterity = calculateSkillF( - this.exp.dexterity, - this.mults.dexterity * BitNodeMultipliers.DexterityLevelMultiplier, - ); -} - -export function gainAgilityExp(this: IPerson, exp: number): void { - if (isNaN(exp)) { - console.error("ERR: NaN passed into Player.gainAgilityExp()"); - return; - } - this.exp.agility += exp; - if (this.exp.agility < 0) { - this.exp.agility = 0; - } - - this.skills.agility = calculateSkillF( - this.exp.agility, - this.mults.agility * BitNodeMultipliers.AgilityLevelMultiplier, - ); -} - -export function gainCharismaExp(this: IPerson, exp: number): void { - if (isNaN(exp)) { - console.error("ERR: NaN passed into Player.gainCharismaExp()"); - return; - } - this.exp.charisma += exp; - if (this.exp.charisma < 0) { - this.exp.charisma = 0; - } - - this.skills.charisma = calculateSkillF( - this.exp.charisma, - this.mults.charisma * BitNodeMultipliers.CharismaLevelMultiplier, - ); -} - -export function gainIntelligenceExp(this: IPerson, exp: number): void { - if (isNaN(exp)) { - console.error("ERROR: NaN passed into Player.gainIntelligenceExp()"); - return; - } - if (Player.sourceFileLvl(5) > 0 || this.skills.intelligence > 0 || Player.bitNodeN === 5) { - this.exp.intelligence += exp; - this.skills.intelligence = Math.floor(this.calculateSkill(this.exp.intelligence, 1)); - } -} - -export function gainStats(this: IPerson, retValue: ITaskTracker): void { - this.gainHackingExp(retValue.hack * this.mults.hacking_exp); - this.gainStrengthExp(retValue.str * this.mults.strength_exp); - this.gainDefenseExp(retValue.def * this.mults.defense_exp); - this.gainDexterityExp(retValue.dex * this.mults.dexterity_exp); - this.gainAgilityExp(retValue.agi * this.mults.agility_exp); - this.gainCharismaExp(retValue.cha * this.mults.charisma_exp); - this.gainIntelligenceExp(retValue.int); -} - -//Given a string expression like "str" or "strength", returns the given stat -export function queryStatFromString(this: PlayerObject, str: string): number { - const tempStr = str.toLowerCase(); - if (tempStr.includes("hack")) { - return this.skills.hacking; - } - if (tempStr.includes("str")) { - return this.skills.strength; - } - if (tempStr.includes("def")) { - return this.skills.defense; - } - if (tempStr.includes("dex")) { - return this.skills.dexterity; - } - if (tempStr.includes("agi")) { - return this.skills.agility; - } - if (tempStr.includes("cha")) { - return this.skills.charisma; - } - if (tempStr.includes("int")) { - return this.skills.intelligence; - } - return 0; -} - export function startFocusing(this: PlayerObject): void { this.focus = true; } @@ -477,17 +272,6 @@ export function takeDamage(this: PlayerObject, amt: number): boolean { } } -export function regenerateHp(this: IPerson, amt: number): void { - if (typeof amt !== "number") { - console.warn(`Player.regenerateHp() called without a numeric argument: ${amt}`); - return; - } - this.hp.current += amt; - if (this.hp.current > this.hp.max) { - this.hp.current = this.hp.max; - } -} - export function hospitalize(this: PlayerObject): number { const cost = getHospitalizationCost(); SnackbarEvents.emit(`You've been Hospitalized for ${numeralWrapper.formatMoney(cost)}`, ToastVariant.WARNING, 2000); @@ -1441,10 +1225,6 @@ export function giveAchievement(this: PlayerObject, achievementId: string): void } } -export function getIntelligenceBonus(this: PlayerObject, weight: number): number { - return calculateIntelligenceBonus(this.skills.intelligence, weight); -} - export function getCasinoWinnings(this: PlayerObject): number { return this.moneySourceA.casino; } diff --git a/src/PersonObjects/Sleeve/Sleeve.ts b/src/PersonObjects/Sleeve/Sleeve.ts index ff0f92f40..2b0d5c4a5 100644 --- a/src/PersonObjects/Sleeve/Sleeve.ts +++ b/src/PersonObjects/Sleeve/Sleeve.ts @@ -80,6 +80,7 @@ export class Sleeve extends Person { this.shockRecovery(); } + applyAugmentation = sleeveMethods.applyAugmentation; findPurchasableAugs = sleeveMethods.findPurchasableAugs; shockBonus(): number { @@ -147,7 +148,7 @@ export class Sleeve extends Person { this.exp.charisma = 0; this.applyAugmentation(aug); this.augmentations.push({ name: aug.name, level: 1 }); - this.updateStatLevels(); + this.updateSkillLevels(); } /** @@ -161,7 +162,7 @@ export class Sleeve extends Person { this.exp.dexterity = 0; this.exp.agility = 0; this.exp.charisma = 0; - this.updateStatLevels(); + this.updateSkillLevels(); this.hp.current = this.hp.max; // Reset task-related stuff diff --git a/src/PersonObjects/Sleeve/SleeveMethods.ts b/src/PersonObjects/Sleeve/SleeveMethods.ts index 08d762d29..0607ea85f 100644 --- a/src/PersonObjects/Sleeve/SleeveMethods.ts +++ b/src/PersonObjects/Sleeve/SleeveMethods.ts @@ -6,10 +6,17 @@ import { Player } from "../../Player"; import { Augmentation } from "../../Augmentation/Augmentation"; import { StaticAugmentations } from "../../Augmentation/StaticAugmentations"; import { Factions } from "../../Faction/Factions"; -import { Multipliers } from "../Multipliers"; +import { mergeMultipliers, Multipliers } from "../Multipliers"; import { AugmentationNames } from "../../Augmentation/data/AugmentationNames"; import { getFactionAugmentationsFiltered } from "../../Faction/FactionHelpers"; +/** + * Updates this object's multipliers for the given augmentation + */ +export function applyAugmentation(this: Sleeve, aug: Augmentation): void { + this.mults = mergeMultipliers(this.mults, aug.mults); +} + export function findPurchasableAugs(this: Sleeve): Augmentation[] { // You can only purchase Augmentations that are actually available from // your factions. I.e. you must be in a faction that has the Augmentation diff --git a/src/PersonObjects/formulas/reputation.ts b/src/PersonObjects/formulas/reputation.ts index 149d66733..f549493ff 100644 --- a/src/PersonObjects/formulas/reputation.ts +++ b/src/PersonObjects/formulas/reputation.ts @@ -1,7 +1,7 @@ import { CONSTANTS } from "../../Constants"; import { BitNodeMultipliers } from "../../BitNode/BitNodeMultipliers"; import { CalculateShareMult } from "../../NetworkShare/Share"; -import { IPerson } from "../IPerson"; +import { Person } from "../Person"; import { calculateIntelligenceBonus } from "./intelligence"; function mult(favor: number): number { @@ -12,7 +12,7 @@ function mult(favor: number): number { return favorMult * BitNodeMultipliers.FactionWorkRepGain; } -export function getHackingWorkRepGain(p: IPerson, favor: number): number { +export function getHackingWorkRepGain(p: Person, favor: number): number { return ( ((p.skills.hacking + p.skills.intelligence / 3) / CONSTANTS.MaxSkillLevel) * p.mults.faction_rep * @@ -22,7 +22,7 @@ export function getHackingWorkRepGain(p: IPerson, favor: number): number { ); } -export function getFactionSecurityWorkRepGain(p: IPerson, favor: number): number { +export function getFactionSecurityWorkRepGain(p: Person, favor: number): number { const t = (0.9 * (p.skills.strength + @@ -35,7 +35,7 @@ export function getFactionSecurityWorkRepGain(p: IPerson, favor: number): number return t * p.mults.faction_rep * mult(favor) * calculateIntelligenceBonus(p.skills.intelligence, 1); } -export function getFactionFieldWorkRepGain(p: IPerson, favor: number): number { +export function getFactionFieldWorkRepGain(p: Person, favor: number): number { const t = (0.9 * (p.skills.strength + diff --git a/src/PersonObjects/formulas/skill.ts b/src/PersonObjects/formulas/skill.ts index 7f22253ca..e8f0bc479 100644 --- a/src/PersonObjects/formulas/skill.ts +++ b/src/PersonObjects/formulas/skill.ts @@ -1,3 +1,7 @@ +/** + * Given an experience amount and stat multiplier, calculates the + * stat level. Stat-agnostic (same formula for every stat) + */ export function calculateSkill(exp: number, mult = 1): number { return Math.max(Math.floor(mult * (32 * Math.log(exp + 534.5) - 200)), 1); } diff --git a/src/Server/formulas/grow.ts b/src/Server/formulas/grow.ts index 4ab2fa761..a739adf7b 100644 --- a/src/Server/formulas/grow.ts +++ b/src/Server/formulas/grow.ts @@ -1,9 +1,9 @@ import { CONSTANTS } from "../../Constants"; import { Server } from "../Server"; import { BitNodeMultipliers } from "../../BitNode/BitNodeMultipliers"; -import { IPerson } from "../../PersonObjects/IPerson"; +import { Person } from "../../PersonObjects/Person"; -export function calculateServerGrowth(server: Server, threads: number, p: IPerson, cores = 1): number { +export function calculateServerGrowth(server: Server, threads: number, p: Person, cores = 1): number { const numServerGrowthCycles = Math.max(Math.floor(threads), 0); //Get adjusted growth rate, which accounts for server security diff --git a/src/Work/WorkStats.ts b/src/Work/WorkStats.ts index 442fbfd1b..fb98b66cb 100644 --- a/src/Work/WorkStats.ts +++ b/src/Work/WorkStats.ts @@ -1,4 +1,4 @@ -import { IPerson } from "src/PersonObjects/IPerson"; +import { Person } from "src/PersonObjects/Person"; import { Player } from "../Player"; export interface WorkStats { @@ -68,7 +68,7 @@ export const scaleWorkStats = (w: WorkStats, n: number, scaleMoney = true): Work }; }; -export const applyWorkStats = (target: IPerson, workStats: WorkStats, cycles: number, source: string): WorkStats => { +export const applyWorkStats = (target: Person, workStats: WorkStats, cycles: number, source: string): WorkStats => { const expStats = applyWorkStatsExp(target, workStats, cycles); const gains = { money: workStats.money * cycles, @@ -86,7 +86,7 @@ export const applyWorkStats = (target: IPerson, workStats: WorkStats, cycles: nu return gains; }; -export const applyWorkStatsExp = (target: IPerson, workStats: WorkStats, cycles: number): WorkStats => { +export const applyWorkStatsExp = (target: Person, workStats: WorkStats, cycles: number): WorkStats => { const gains = { money: 0, reputation: 0, diff --git a/src/Work/formulas/Class.ts b/src/Work/formulas/Class.ts index 54ede73fb..d685e497b 100644 --- a/src/Work/formulas/Class.ts +++ b/src/Work/formulas/Class.ts @@ -8,7 +8,7 @@ import { WorkStats } from "../WorkStats"; import { Server } from "../../Server/Server"; import { GetServer } from "../../Server/AllServers"; import { serverMetadata } from "../../Server/data/servers"; -import { IPerson } from "../../PersonObjects/IPerson"; +import { Person } from "../../PersonObjects/Person"; import { LocationName } from "../../Locations/data/LocationNames"; const gameCPS = 1000 / CONSTANTS._idleSpeed; // 5 cycles per second @@ -20,7 +20,7 @@ export function calculateCost(classs: Class, location: Location): number { return classs.earnings.money * location.costMult * discount; } -export function calculateClassEarnings(person: IPerson, type: ClassType, locationName: LocationName): WorkStats { +export function calculateClassEarnings(person: Person, type: ClassType, locationName: LocationName): WorkStats { //Find cost and exp gain per game cycle const hashManager = Player.hashManager; const classs = Classes[type]; diff --git a/src/Work/formulas/Company.ts b/src/Work/formulas/Company.ts index 801b8813b..710cd89e6 100644 --- a/src/Work/formulas/Company.ts +++ b/src/Work/formulas/Company.ts @@ -4,9 +4,9 @@ import { Player } from "../../Player"; import { WorkStats } from "../WorkStats"; import { BitNodeMultipliers } from "../../BitNode/BitNodeMultipliers"; import { CONSTANTS } from "../../Constants"; -import { IPerson } from "src/PersonObjects/IPerson"; +import { Person } from "../../PersonObjects/Person"; -export const calculateCompanyWorkStats = (worker: IPerson, company: Company): WorkStats => { +export const calculateCompanyWorkStats = (worker: Person, company: Company): WorkStats => { const companyPositionName = Player.jobs[company.name]; const companyPosition = CompanyPositions[companyPositionName]; diff --git a/src/Work/formulas/Faction.ts b/src/Work/formulas/Faction.ts index 0a2913f38..1dd704c3a 100644 --- a/src/Work/formulas/Faction.ts +++ b/src/Work/formulas/Faction.ts @@ -1,4 +1,4 @@ -import { IPerson } from "../../PersonObjects/IPerson"; +import { Person } from "../../PersonObjects/Person"; import { BitNodeMultipliers } from "../../BitNode/BitNodeMultipliers"; import { CONSTANTS } from "../../Constants"; import { FactionWorkType } from "../data/FactionWorkType"; @@ -30,7 +30,7 @@ export const FactionWorkStats: Record = { }), }; -export const calculateFactionRep = (person: IPerson, tpe: FactionWorkType, favor: number): number => { +export const calculateFactionRep = (person: Person, tpe: FactionWorkType, favor: number): number => { const repFormulas = { [FactionWorkType.HACKING]: getHackingWorkRepGain, [FactionWorkType.FIELD]: getFactionFieldWorkRepGain, @@ -39,7 +39,7 @@ export const calculateFactionRep = (person: IPerson, tpe: FactionWorkType, favor return repFormulas[tpe](person, favor); }; -export function calculateFactionExp(person: IPerson, tpe: FactionWorkType): WorkStats { +export function calculateFactionExp(person: Person, tpe: FactionWorkType): WorkStats { const baseStats = FactionWorkStats[tpe]; return { money: 0, From 2213d06159189f66702ec02c321263f7423741e1 Mon Sep 17 00:00:00 2001 From: Snarling <84951833+Snarling@users.noreply.github.com> Date: Tue, 20 Sep 2022 02:15:58 -0400 Subject: [PATCH 25/46] Using bladeburner and action classes as types --- src/Bladeburner/Action.tsx | 25 +++-- src/Bladeburner/BlackOperation.ts | 4 +- src/Bladeburner/Bladeburner.tsx | 9 +- src/Bladeburner/Contract.ts | 4 +- src/Bladeburner/IAction.tsx | 72 ------------- src/Bladeburner/IBladeburner.ts | 124 ----------------------- src/Bladeburner/Operation.ts | 8 +- src/Bladeburner/ui/ActionLevel.tsx | 8 +- src/Bladeburner/ui/AllPages.tsx | 4 +- src/Bladeburner/ui/Autolevel.tsx | 4 +- src/Bladeburner/ui/BlackOpElem.tsx | 4 +- src/Bladeburner/ui/BlackOpList.tsx | 4 +- src/Bladeburner/ui/BlackOpPage.tsx | 4 +- src/Bladeburner/ui/Console.tsx | 4 +- src/Bladeburner/ui/ContractElem.tsx | 8 +- src/Bladeburner/ui/ContractList.tsx | 4 +- src/Bladeburner/ui/ContractPage.tsx | 4 +- src/Bladeburner/ui/GeneralActionElem.tsx | 8 +- src/Bladeburner/ui/GeneralActionList.tsx | 4 +- src/Bladeburner/ui/GeneralActionPage.tsx | 4 +- src/Bladeburner/ui/OperationElem.tsx | 4 +- src/Bladeburner/ui/OperationList.tsx | 4 +- src/Bladeburner/ui/OperationPage.tsx | 4 +- src/Bladeburner/ui/SkillElem.tsx | 4 +- src/Bladeburner/ui/SkillList.tsx | 4 +- src/Bladeburner/ui/SkillPage.tsx | 4 +- src/Bladeburner/ui/StartButton.tsx | 4 +- src/Bladeburner/ui/Stats.tsx | 4 +- src/Bladeburner/ui/SuccessChance.tsx | 8 +- src/Bladeburner/ui/TeamSizeButton.tsx | 4 +- src/Bladeburner/ui/TeamSizeModal.tsx | 4 +- src/Bladeburner/ui/TravelModal.tsx | 4 +- src/NetscriptFunctions/Bladeburner.ts | 4 +- src/PersonObjects/Player/PlayerObject.ts | 4 +- 34 files changed, 88 insertions(+), 282 deletions(-) delete mode 100644 src/Bladeburner/IAction.tsx delete mode 100644 src/Bladeburner/IBladeburner.ts diff --git a/src/Bladeburner/Action.tsx b/src/Bladeburner/Action.tsx index 9ec88479a..9874f1b2f 100644 --- a/src/Bladeburner/Action.tsx +++ b/src/Bladeburner/Action.tsx @@ -3,10 +3,13 @@ import { getRandomInt } from "../utils/helpers/getRandomInt"; import { addOffset } from "../utils/helpers/addOffset"; import { Generic_fromJSON, Generic_toJSON, IReviverValue, Reviver } from "../utils/JSONReviver"; import { BladeburnerConstants } from "./data/Constants"; -import { IBladeburner } from "./IBladeburner"; -import { IAction, ISuccessChanceParams } from "./IAction"; +import { Bladeburner } from "./Bladeburner"; import { Person } from "../PersonObjects/Person"; +interface ISuccessChanceParams { + est: boolean; +} + class StatsMultiplier { [key: string]: number; @@ -41,7 +44,7 @@ export interface IActionParams { teamCount?: number; } -export class Action implements IAction { +export class Action { name = ""; // Difficulty scales with level. See getDifficulty() method @@ -153,7 +156,7 @@ export class Action implements IAction { * Tests for success. Should be called when an action has completed * @param inst {Bladeburner} - Bladeburner instance */ - attempt(inst: IBladeburner, person: Person): boolean { + attempt(inst: Bladeburner, person: Person): boolean { return Math.random() < this.getSuccessChance(inst, person); } @@ -162,7 +165,7 @@ export class Action implements IAction { return 1; } - getActionTime(inst: IBladeburner, person: Person): number { + getActionTime(inst: Bladeburner, person: Person): number { const difficulty = this.getDifficulty(); let baseTime = difficulty / BladeburnerConstants.DifficultyToTimeFactor; const skillFac = inst.skillMultipliers.actionTime; // Always < 1 @@ -183,16 +186,16 @@ export class Action implements IAction { // For actions that have teams. To be implemented by subtypes. // eslint-disable-next-line @typescript-eslint/no-unused-vars - getTeamSuccessBonus(inst: IBladeburner): number { + getTeamSuccessBonus(inst: Bladeburner): number { return 1; } // eslint-disable-next-line @typescript-eslint/no-unused-vars - getActionTypeSkillSuccessBonus(inst: IBladeburner): number { + getActionTypeSkillSuccessBonus(inst: Bladeburner): number { return 1; } - getChaosCompetencePenalty(inst: IBladeburner, params: ISuccessChanceParams): number { + getChaosCompetencePenalty(inst: Bladeburner, params: ISuccessChanceParams): number { const city = inst.getCurrentCity(); if (params.est) { return Math.pow(city.popEst / BladeburnerConstants.PopulationThreshold, BladeburnerConstants.PopulationExponent); @@ -201,7 +204,7 @@ export class Action implements IAction { } } - getChaosDifficultyBonus(inst: IBladeburner /*, params: ISuccessChanceParams*/): number { + getChaosDifficultyBonus(inst: Bladeburner /*, params: ISuccessChanceParams*/): number { const city = inst.getCurrentCity(); if (city.chaos > BladeburnerConstants.ChaosThreshold) { const diff = 1 + (city.chaos - BladeburnerConstants.ChaosThreshold); @@ -212,7 +215,7 @@ export class Action implements IAction { return 1; } - getEstSuccessChance(inst: IBladeburner, person: Person): [number, number] { + getEstSuccessChance(inst: Bladeburner, person: Person): [number, number] { function clamp(x: number): number { return Math.max(0, Math.min(x, 1)); } @@ -233,7 +236,7 @@ export class Action implements IAction { * @params - options: * est (bool): Get success chance estimate instead of real success chance */ - getSuccessChance(inst: IBladeburner, person: Person, params: ISuccessChanceParams = { est: false }): number { + getSuccessChance(inst: Bladeburner, person: Person, params: ISuccessChanceParams = { est: false }): number { if (inst == null) { throw new Error("Invalid Bladeburner instance passed into Action.getSuccessChance"); } diff --git a/src/Bladeburner/BlackOperation.ts b/src/Bladeburner/BlackOperation.ts index 9691ba5c6..717c5859f 100644 --- a/src/Bladeburner/BlackOperation.ts +++ b/src/Bladeburner/BlackOperation.ts @@ -12,11 +12,11 @@ export class BlackOperation extends Operation { return 1.5; } - getChaosCompetencePenalty(/*inst: IBladeburner, params: ISuccessChanceParams*/): number { + getChaosCompetencePenalty(/*inst: Bladeburner, params: ISuccessChanceParams*/): number { return 1; } - getChaosDifficultyBonus(/*inst: IBladeburner, params: ISuccessChanceParams*/): number { + getChaosDifficultyBonus(/*inst: Bladeburner, params: ISuccessChanceParams*/): number { return 1; } diff --git a/src/Bladeburner/Bladeburner.tsx b/src/Bladeburner/Bladeburner.tsx index c52b72431..a7dff6eb2 100644 --- a/src/Bladeburner/Bladeburner.tsx +++ b/src/Bladeburner/Bladeburner.tsx @@ -1,5 +1,4 @@ import { Reviver, Generic_toJSON, Generic_fromJSON, IReviverValue } from "../utils/JSONReviver"; -import { IBladeburner } from "./IBladeburner"; import { IActionIdentifier } from "./IActionIdentifier"; import { ActionIdentifier } from "./ActionIdentifier"; import { ActionTypes } from "./data/ActionTypes"; @@ -13,7 +12,7 @@ import { formatNumber } from "../utils/StringHelperFunctions"; import { Skills } from "./Skills"; import { Skill } from "./Skill"; import { City } from "./City"; -import { IAction } from "./IAction"; +import { Action } from "./Action"; import { Player } from "../Player"; import { createTaskTracker, ITaskTracker } from "../PersonObjects/ITaskTracker"; import { Person } from "../PersonObjects/Person"; @@ -45,7 +44,7 @@ export interface BlackOpsAttempt { action?: BlackOperation; } -export class Bladeburner implements IBladeburner { +export class Bladeburner { numHosp = 0; moneyLost = 0; rank = 0; @@ -995,7 +994,7 @@ export class Bladeburner implements IBladeburner { * @param action(Action obj) - Derived action class * @param success(bool) - Whether action was successful */ - getActionStats(action: IAction, person: Person, success: boolean): ITaskTracker { + getActionStats(action: Action, person: Person, success: boolean): ITaskTracker { const difficulty = action.getDifficulty(); /** @@ -1202,7 +1201,7 @@ export class Bladeburner implements IBladeburner { } } - getActionObject(actionId: IActionIdentifier): IAction | null { + getActionObject(actionId: IActionIdentifier): Action | null { /** * Given an ActionIdentifier object, returns the corresponding * GeneralAction, Contract, Operation, or BlackOperation object diff --git a/src/Bladeburner/Contract.ts b/src/Bladeburner/Contract.ts index a74d1b029..61a6a7d6f 100644 --- a/src/Bladeburner/Contract.ts +++ b/src/Bladeburner/Contract.ts @@ -1,4 +1,4 @@ -import { IBladeburner } from "./IBladeburner"; +import { Bladeburner } from "./Bladeburner"; import { Action, IActionParams } from "./Action"; import { Generic_fromJSON, Generic_toJSON, IReviverValue, Reviver } from "../utils/JSONReviver"; @@ -7,7 +7,7 @@ export class Contract extends Action { super(params); } - getActionTypeSkillSuccessBonus(inst: IBladeburner): number { + getActionTypeSkillSuccessBonus(inst: Bladeburner): number { return inst.skillMultipliers.successChanceContract; } diff --git a/src/Bladeburner/IAction.tsx b/src/Bladeburner/IAction.tsx deleted file mode 100644 index 0f396fa32..000000000 --- a/src/Bladeburner/IAction.tsx +++ /dev/null @@ -1,72 +0,0 @@ -import { IReviverValue } from "../utils/JSONReviver"; -import { Person } from "../PersonObjects/Person"; -import { IBladeburner } from "./IBladeburner"; - -interface IStatsMultiplier { - [key: string]: number; - - hack: number; - str: number; - def: number; - dex: number; - agi: number; - cha: number; - int: number; -} - -export interface ISuccessChanceParams { - est: boolean; -} - -export interface IAction { - name: string; - - // Difficulty scales with level. See getDifficulty() method - level: number; - maxLevel: number; - autoLevel: boolean; - baseDifficulty: number; - difficultyFac: number; - - // Rank increase/decrease is affected by this exponent - rewardFac: number; - - successes: number; - failures: number; - - // All of these scale with level/difficulty - rankGain: number; - rankLoss: number; - hpLoss: number; - hpLost: number; - - // Action Category. Current categories are stealth and kill - isStealth: boolean; - isKill: boolean; - - /** - * Number of this contract remaining, and its growth rate - * Growth rate is an integer and the count will increase by that integer every "cycle" - */ - count: number; - - // Weighting of each stat in determining action success rate - weights: IStatsMultiplier; - // Diminishing returns of stats (stat ^ decay where 0 <= decay <= 1) - decays: IStatsMultiplier; - teamCount: number; - - getDifficulty(): number; - attempt(inst: IBladeburner, person: Person): boolean; - getActionTimePenalty(): number; - getActionTime(inst: IBladeburner, person: Person): number; - getTeamSuccessBonus(inst: IBladeburner): number; - getActionTypeSkillSuccessBonus(inst: IBladeburner): number; - getChaosCompetencePenalty(inst: IBladeburner, params: ISuccessChanceParams): number; - getChaosDifficultyBonus(inst: IBladeburner): number; - getEstSuccessChance(inst: IBladeburner, person: Person): [number, number]; - getSuccessChance(inst: IBladeburner, person: Person, params: ISuccessChanceParams): number; - getSuccessesNeededForNextLevel(baseSuccessesPerLevel: number): number; - setMaxLevel(baseSuccessesPerLevel: number): void; - toJSON(): IReviverValue; -} diff --git a/src/Bladeburner/IBladeburner.ts b/src/Bladeburner/IBladeburner.ts deleted file mode 100644 index 0f3353ba1..000000000 --- a/src/Bladeburner/IBladeburner.ts +++ /dev/null @@ -1,124 +0,0 @@ -import { IActionIdentifier } from "./IActionIdentifier"; -import { City } from "./City"; -import { Skill } from "./Skill"; -import { IAction } from "./IAction"; -import { Person } from "../PersonObjects/Person"; -import { ITaskTracker } from "../PersonObjects/ITaskTracker"; -import { WorkerScript } from "../Netscript/WorkerScript"; -import { Contract } from "./Contract"; -import { Operation } from "./Operation"; -import { IReviverValue } from "../utils/JSONReviver"; -import { BlackOpsAttempt } from "./Bladeburner"; - -export interface IBladeburner { - numHosp: number; - moneyLost: number; - rank: number; - maxRank: number; - - skillPoints: number; - totalSkillPoints: number; - - teamSize: number; - sleeveSize: number; - teamLost: number; - hpLost: number; - - storedCycles: number; - - randomEventCounter: number; - - actionTimeToComplete: number; - actionTimeCurrent: number; - actionTimeOverflow: number; - - action: IActionIdentifier; - - cities: Record; - city: string; - skills: Record; - skillMultipliers: Record; - staminaBonus: number; - maxStamina: number; - stamina: number; - contracts: Record; - operations: Record; - blackops: Record; - logging: { - general: boolean; - contracts: boolean; - ops: boolean; - blackops: boolean; - events: boolean; - }; - automateEnabled: boolean; - automateActionHigh: IActionIdentifier; - automateThreshHigh: number; - automateActionLow: IActionIdentifier; - automateThreshLow: number; - consoleHistory: string[]; - consoleLogs: string[]; - - getCurrentCity(): City; - calculateStaminaPenalty(): number; - canAttemptBlackOp(actionId: IActionIdentifier): BlackOpsAttempt; - startAction(action: IActionIdentifier): void; - upgradeSkill(skill: Skill): void; - executeConsoleCommands(command: string): void; - postToConsole(input: string, saveToLogs?: boolean): void; - log(input: string): void; - resetAction(): void; - clearConsole(): void; - - prestige(): void; - storeCycles(numCycles?: number): void; - getTypeAndNameFromActionId(actionId: IActionIdentifier): { - type: string; - name: string; - }; - getContractNamesNetscriptFn(): string[]; - getOperationNamesNetscriptFn(): string[]; - getBlackOpNamesNetscriptFn(): string[]; - getGeneralActionNamesNetscriptFn(): string[]; - getSkillNamesNetscriptFn(): string[]; - startActionNetscriptFn(type: string, name: string, workerScript: WorkerScript): boolean; - getActionTimeNetscriptFn(person: Person, type: string, name: string): number | string; - getActionEstimatedSuccessChanceNetscriptFn(person: Person, type: string, name: string): [number, number] | string; - getActionCountRemainingNetscriptFn(type: string, name: string, workerScript: WorkerScript): number; - getSkillLevelNetscriptFn(skillName: string, workerScript: WorkerScript): number; - getSkillUpgradeCostNetscriptFn(skillName: string, count: number, workerScript: WorkerScript): number; - upgradeSkillNetscriptFn(skillName: string, count: number, workerScript: WorkerScript): boolean; - getTeamSizeNetscriptFn(type: string, name: string, workerScript: WorkerScript): number; - setTeamSizeNetscriptFn(type: string, name: string, size: number, workerScript: WorkerScript): number; - joinBladeburnerFactionNetscriptFn(workerScript: WorkerScript): boolean; - getActionIdFromTypeAndName(type: string, name: string): IActionIdentifier | null; - executeStartConsoleCommand(args: string[]): void; - executeSkillConsoleCommand(args: string[]): void; - executeLogConsoleCommand(args: string[]): void; - executeHelpConsoleCommand(args: string[]): void; - executeAutomateConsoleCommand(args: string[]): void; - parseCommandArguments(command: string): string[]; - executeConsoleCommand(command: string): void; - triggerMigration(sourceCityName: string): void; - triggerPotentialMigration(sourceCityName: string, chance: number): void; - randomEvent(): void; - getDiplomacyEffectiveness(person: Person): number; - getRecruitmentSuccessChance(person: Person): number; - getRecruitmentTime(person: Person): number; - resetSkillMultipliers(): void; - updateSkillMultipliers(): void; - completeOperation(success: boolean): void; - getActionObject(actionId: IActionIdentifier): IAction | null; - completeContract(success: boolean, actionIdent: IActionIdentifier): void; - completeAction(person: Person, actionIdent: IActionIdentifier, isPlayer?: boolean): ITaskTracker; - infiltrateSynthoidCommunities(): void; - changeRank(person: Person, change: number): void; - processAction(seconds: number): void; - calculateStaminaGainPerSecond(): number; - calculateMaxStamina(): void; - create(): void; - process(): void; - getActionStats(action: IAction, person: Person, success: boolean): ITaskTracker; - sleeveSupport(joining: boolean): void; - toJSON(): IReviverValue; -} diff --git a/src/Bladeburner/Operation.ts b/src/Bladeburner/Operation.ts index 04304988e..4eef008c1 100644 --- a/src/Bladeburner/Operation.ts +++ b/src/Bladeburner/Operation.ts @@ -1,4 +1,4 @@ -import { IBladeburner } from "./IBladeburner"; +import { Bladeburner } from "./Bladeburner"; import { BladeburnerConstants } from "./data/Constants"; import { Action, IActionParams } from "./Action"; import { Generic_fromJSON, Generic_toJSON, IReviverValue, Reviver } from "../utils/JSONReviver"; @@ -19,7 +19,7 @@ export class Operation extends Action { } // For actions that have teams. To be implemented by subtypes. - getTeamSuccessBonus(inst: IBladeburner): number { + getTeamSuccessBonus(inst: Bladeburner): number { if (this.teamCount && this.teamCount > 0) { this.teamCount = Math.min(this.teamCount, inst.teamSize); const teamMultiplier = Math.pow(this.teamCount, 0.05); @@ -29,11 +29,11 @@ export class Operation extends Action { return 1; } - getActionTypeSkillSuccessBonus(inst: IBladeburner): number { + getActionTypeSkillSuccessBonus(inst: Bladeburner): number { return inst.skillMultipliers.successChanceOperation; } - getChaosDifficultyBonus(inst: IBladeburner /*, params: ISuccessChanceParams*/): number { + getChaosDifficultyBonus(inst: Bladeburner /*, params: ISuccessChanceParams*/): number { const city = inst.getCurrentCity(); if (city.chaos > BladeburnerConstants.ChaosThreshold) { const diff = 1 + (city.chaos - BladeburnerConstants.ChaosThreshold); diff --git a/src/Bladeburner/ui/ActionLevel.tsx b/src/Bladeburner/ui/ActionLevel.tsx index e87a466fe..b74625729 100644 --- a/src/Bladeburner/ui/ActionLevel.tsx +++ b/src/Bladeburner/ui/ActionLevel.tsx @@ -1,6 +1,6 @@ import React from "react"; -import { IAction } from "../IAction"; -import { IBladeburner } from "../IBladeburner"; +import { Action } from "../Action"; +import { Bladeburner } from "../Bladeburner"; import { BladeburnerConstants } from "../data/Constants"; import Typography from "@mui/material/Typography"; @@ -11,9 +11,9 @@ import ArrowDropUpIcon from "@mui/icons-material/ArrowDropUp"; import ArrowDropDownIcon from "@mui/icons-material/ArrowDropDown"; interface IProps { - action: IAction; + action: Action; isActive: boolean; - bladeburner: IBladeburner; + bladeburner: Bladeburner; rerender: () => void; } diff --git a/src/Bladeburner/ui/AllPages.tsx b/src/Bladeburner/ui/AllPages.tsx index 7c77ae79f..e6fa94cd6 100644 --- a/src/Bladeburner/ui/AllPages.tsx +++ b/src/Bladeburner/ui/AllPages.tsx @@ -4,14 +4,14 @@ import { ContractPage } from "./ContractPage"; import { OperationPage } from "./OperationPage"; import { BlackOpPage } from "./BlackOpPage"; import { SkillPage } from "./SkillPage"; -import { IBladeburner } from "../IBladeburner"; +import { Bladeburner } from "../Bladeburner"; import Tabs from "@mui/material/Tabs"; import Tab from "@mui/material/Tab"; import Box from "@mui/material/Box"; interface IProps { - bladeburner: IBladeburner; + bladeburner: Bladeburner; } export function AllPages(props: IProps): React.ReactElement { diff --git a/src/Bladeburner/ui/Autolevel.tsx b/src/Bladeburner/ui/Autolevel.tsx index dad8188fd..6e18e64ee 100644 --- a/src/Bladeburner/ui/Autolevel.tsx +++ b/src/Bladeburner/ui/Autolevel.tsx @@ -1,12 +1,12 @@ import React from "react"; -import { IAction } from "../IAction"; +import { Action } from "../Action"; import Typography from "@mui/material/Typography"; import Tooltip from "@mui/material/Tooltip"; import Box from "@mui/material/Box"; import Switch from "@mui/material/Switch"; interface IProps { - action: IAction; + action: Action; rerender: () => void; } diff --git a/src/Bladeburner/ui/BlackOpElem.tsx b/src/Bladeburner/ui/BlackOpElem.tsx index e5e586d84..6e81c36ec 100644 --- a/src/Bladeburner/ui/BlackOpElem.tsx +++ b/src/Bladeburner/ui/BlackOpElem.tsx @@ -3,7 +3,7 @@ import { formatNumber, convertTimeMsToTimeElapsedString } from "../../utils/Stri import { ActionTypes } from "../data/ActionTypes"; import { createProgressBarText } from "../../utils/helpers/createProgressBarText"; import { TeamSizeButton } from "./TeamSizeButton"; -import { IBladeburner } from "../IBladeburner"; +import { Bladeburner } from "../Bladeburner"; import { BlackOperation } from "../BlackOperation"; import { BlackOperations } from "../data/BlackOperations"; import { Player } from "../../Player"; @@ -15,7 +15,7 @@ import Typography from "@mui/material/Typography"; import Paper from "@mui/material/Paper"; interface IProps { - bladeburner: IBladeburner; + bladeburner: Bladeburner; action: BlackOperation; } diff --git a/src/Bladeburner/ui/BlackOpList.tsx b/src/Bladeburner/ui/BlackOpList.tsx index 17706bf6f..a5fa39302 100644 --- a/src/Bladeburner/ui/BlackOpList.tsx +++ b/src/Bladeburner/ui/BlackOpList.tsx @@ -2,10 +2,10 @@ import React from "react"; import { BlackOperations } from "../BlackOperations"; import { BlackOperation } from "../BlackOperation"; import { BlackOpElem } from "./BlackOpElem"; -import { IBladeburner } from "../IBladeburner"; +import { Bladeburner } from "../Bladeburner"; interface IProps { - bladeburner: IBladeburner; + bladeburner: Bladeburner; } export function BlackOpList(props: IProps): React.ReactElement { diff --git a/src/Bladeburner/ui/BlackOpPage.tsx b/src/Bladeburner/ui/BlackOpPage.tsx index ecfede4c9..715ad3941 100644 --- a/src/Bladeburner/ui/BlackOpPage.tsx +++ b/src/Bladeburner/ui/BlackOpPage.tsx @@ -1,6 +1,6 @@ import * as React from "react"; import { BlackOpList } from "./BlackOpList"; -import { IBladeburner } from "../IBladeburner"; +import { Bladeburner } from "../Bladeburner"; import Typography from "@mui/material/Typography"; import { FactionNames } from "../../Faction/data/FactionNames"; import { Router } from "../../ui/GameRoot"; @@ -9,7 +9,7 @@ import { Button } from "@mui/material"; import { CorruptableText } from "../../ui/React/CorruptableText"; interface IProps { - bladeburner: IBladeburner; + bladeburner: Bladeburner; } export function BlackOpPage(props: IProps): React.ReactElement { diff --git a/src/Bladeburner/ui/Console.tsx b/src/Bladeburner/ui/Console.tsx index bcc07b447..5c5565e08 100644 --- a/src/Bladeburner/ui/Console.tsx +++ b/src/Bladeburner/ui/Console.tsx @@ -1,5 +1,5 @@ import React, { useState, useRef, useEffect } from "react"; -import { IBladeburner } from "../IBladeburner"; +import { Bladeburner } from "../Bladeburner"; import { KEY } from "../../utils/helpers/keyCodes"; import Paper from "@mui/material/Paper"; @@ -48,7 +48,7 @@ function Line(props: ILineProps): React.ReactElement { } interface IProps { - bladeburner: IBladeburner; + bladeburner: Bladeburner; } export function Console(props: IProps): React.ReactElement { diff --git a/src/Bladeburner/ui/ContractElem.tsx b/src/Bladeburner/ui/ContractElem.tsx index 376236ca7..49dfc5add 100644 --- a/src/Bladeburner/ui/ContractElem.tsx +++ b/src/Bladeburner/ui/ContractElem.tsx @@ -3,8 +3,8 @@ import { ActionTypes } from "../data/ActionTypes"; import { createProgressBarText } from "../../utils/helpers/createProgressBarText"; import { formatNumber, convertTimeMsToTimeElapsedString } from "../../utils/StringHelperFunctions"; import { Contracts } from "../data/Contracts"; -import { IBladeburner } from "../IBladeburner"; -import { IAction } from "../IAction"; +import { Bladeburner } from "../Bladeburner"; +import { Action } from "../Action"; import { Player } from "../../Player"; import { SuccessChance } from "./SuccessChance"; import { CopyableText } from "../../ui/React/CopyableText"; @@ -16,8 +16,8 @@ import Typography from "@mui/material/Typography"; import Paper from "@mui/material/Paper"; interface IProps { - bladeburner: IBladeburner; - action: IAction; + bladeburner: Bladeburner; + action: Action; } export function ContractElem(props: IProps): React.ReactElement { diff --git a/src/Bladeburner/ui/ContractList.tsx b/src/Bladeburner/ui/ContractList.tsx index 499a437fe..689238495 100644 --- a/src/Bladeburner/ui/ContractList.tsx +++ b/src/Bladeburner/ui/ContractList.tsx @@ -1,9 +1,9 @@ import React from "react"; import { ContractElem } from "./ContractElem"; -import { IBladeburner } from "../IBladeburner"; +import { Bladeburner } from "../Bladeburner"; interface IProps { - bladeburner: IBladeburner; + bladeburner: Bladeburner; } export function ContractList(props: IProps): React.ReactElement { diff --git a/src/Bladeburner/ui/ContractPage.tsx b/src/Bladeburner/ui/ContractPage.tsx index 0af07e41c..d8a54bc2f 100644 --- a/src/Bladeburner/ui/ContractPage.tsx +++ b/src/Bladeburner/ui/ContractPage.tsx @@ -1,10 +1,10 @@ import * as React from "react"; import { ContractList } from "./ContractList"; -import { IBladeburner } from "../IBladeburner"; +import { Bladeburner } from "../Bladeburner"; import Typography from "@mui/material/Typography"; interface IProps { - bladeburner: IBladeburner; + bladeburner: Bladeburner; } export function ContractPage(props: IProps): React.ReactElement { diff --git a/src/Bladeburner/ui/GeneralActionElem.tsx b/src/Bladeburner/ui/GeneralActionElem.tsx index 09b1de249..b88b98dd9 100644 --- a/src/Bladeburner/ui/GeneralActionElem.tsx +++ b/src/Bladeburner/ui/GeneralActionElem.tsx @@ -2,8 +2,8 @@ import React, { useState } from "react"; import { ActionTypes } from "../data/ActionTypes"; import { createProgressBarText } from "../../utils/helpers/createProgressBarText"; import { formatNumber, convertTimeMsToTimeElapsedString } from "../../utils/StringHelperFunctions"; -import { IBladeburner } from "../IBladeburner"; -import { IAction } from "../IAction"; +import { Bladeburner } from "../Bladeburner"; +import { Action } from "../Action"; import { GeneralActions } from "../data/GeneralActions"; import { Player } from "../../Player"; import { CopyableText } from "../../ui/React/CopyableText"; @@ -15,8 +15,8 @@ import Box from "@mui/material/Box"; import Paper from "@mui/material/Paper"; interface IProps { - bladeburner: IBladeburner; - action: IAction; + bladeburner: Bladeburner; + action: Action; } export function GeneralActionElem(props: IProps): React.ReactElement { diff --git a/src/Bladeburner/ui/GeneralActionList.tsx b/src/Bladeburner/ui/GeneralActionList.tsx index 27e52fbc9..58a64d944 100644 --- a/src/Bladeburner/ui/GeneralActionList.tsx +++ b/src/Bladeburner/ui/GeneralActionList.tsx @@ -2,10 +2,10 @@ import React from "react"; import { GeneralActionElem } from "./GeneralActionElem"; import { Action } from "../Action"; import { GeneralActions } from "../GeneralActions"; -import { IBladeburner } from "../IBladeburner"; +import { Bladeburner } from "../Bladeburner"; interface IProps { - bladeburner: IBladeburner; + bladeburner: Bladeburner; } export function GeneralActionList(props: IProps): React.ReactElement { diff --git a/src/Bladeburner/ui/GeneralActionPage.tsx b/src/Bladeburner/ui/GeneralActionPage.tsx index 10d27a86d..3dcf808c2 100644 --- a/src/Bladeburner/ui/GeneralActionPage.tsx +++ b/src/Bladeburner/ui/GeneralActionPage.tsx @@ -1,10 +1,10 @@ import * as React from "react"; import { GeneralActionList } from "./GeneralActionList"; -import { IBladeburner } from "../IBladeburner"; +import { Bladeburner } from "../Bladeburner"; import Typography from "@mui/material/Typography"; interface IProps { - bladeburner: IBladeburner; + bladeburner: Bladeburner; } export function GeneralActionPage(props: IProps): React.ReactElement { diff --git a/src/Bladeburner/ui/OperationElem.tsx b/src/Bladeburner/ui/OperationElem.tsx index ea39d68d6..161003d60 100644 --- a/src/Bladeburner/ui/OperationElem.tsx +++ b/src/Bladeburner/ui/OperationElem.tsx @@ -7,7 +7,7 @@ import { ActionLevel } from "./ActionLevel"; import { Autolevel } from "./Autolevel"; import { StartButton } from "./StartButton"; import { TeamSizeButton } from "./TeamSizeButton"; -import { IBladeburner } from "../IBladeburner"; +import { Bladeburner } from "../Bladeburner"; import { Operation } from "../Operation"; import { Operations } from "../data/Operations"; import { Player } from "../../Player"; @@ -17,7 +17,7 @@ import Typography from "@mui/material/Typography"; import Paper from "@mui/material/Paper"; interface IProps { - bladeburner: IBladeburner; + bladeburner: Bladeburner; action: Operation; } diff --git a/src/Bladeburner/ui/OperationList.tsx b/src/Bladeburner/ui/OperationList.tsx index eacb779bc..610896b6c 100644 --- a/src/Bladeburner/ui/OperationList.tsx +++ b/src/Bladeburner/ui/OperationList.tsx @@ -1,9 +1,9 @@ import React from "react"; import { OperationElem } from "./OperationElem"; -import { IBladeburner } from "../IBladeburner"; +import { Bladeburner } from "../Bladeburner"; interface IProps { - bladeburner: IBladeburner; + bladeburner: Bladeburner; } export function OperationList(props: IProps): React.ReactElement { diff --git a/src/Bladeburner/ui/OperationPage.tsx b/src/Bladeburner/ui/OperationPage.tsx index 3557a8867..c2b212da7 100644 --- a/src/Bladeburner/ui/OperationPage.tsx +++ b/src/Bladeburner/ui/OperationPage.tsx @@ -1,10 +1,10 @@ import * as React from "react"; import { OperationList } from "./OperationList"; -import { IBladeburner } from "../IBladeburner"; +import { Bladeburner } from "../Bladeburner"; import Typography from "@mui/material/Typography"; interface IProps { - bladeburner: IBladeburner; + bladeburner: Bladeburner; } export function OperationPage(props: IProps): React.ReactElement { diff --git a/src/Bladeburner/ui/SkillElem.tsx b/src/Bladeburner/ui/SkillElem.tsx index c51217bd0..e878f4339 100644 --- a/src/Bladeburner/ui/SkillElem.tsx +++ b/src/Bladeburner/ui/SkillElem.tsx @@ -1,7 +1,7 @@ import React from "react"; import { CopyableText } from "../../ui/React/CopyableText"; import { formatNumber } from "../../utils/StringHelperFunctions"; -import { IBladeburner } from "../IBladeburner"; +import { Bladeburner } from "../Bladeburner"; import Typography from "@mui/material/Typography"; import IconButton from "@mui/material/IconButton"; @@ -13,7 +13,7 @@ import { Skill } from "../Skill"; interface IProps { skill: Skill; - bladeburner: IBladeburner; + bladeburner: Bladeburner; onUpgrade: () => void; } diff --git a/src/Bladeburner/ui/SkillList.tsx b/src/Bladeburner/ui/SkillList.tsx index c6e801c58..f28b56fc2 100644 --- a/src/Bladeburner/ui/SkillList.tsx +++ b/src/Bladeburner/ui/SkillList.tsx @@ -1,10 +1,10 @@ import * as React from "react"; import { SkillElem } from "./SkillElem"; import { Skills } from "../Skills"; -import { IBladeburner } from "../IBladeburner"; +import { Bladeburner } from "../Bladeburner"; interface IProps { - bladeburner: IBladeburner; + bladeburner: Bladeburner; onUpgrade: () => void; } diff --git a/src/Bladeburner/ui/SkillPage.tsx b/src/Bladeburner/ui/SkillPage.tsx index 376efc748..44795d62c 100644 --- a/src/Bladeburner/ui/SkillPage.tsx +++ b/src/Bladeburner/ui/SkillPage.tsx @@ -2,10 +2,10 @@ import React, { useState } from "react"; import { SkillList } from "./SkillList"; import { BladeburnerConstants } from "../data/Constants"; import { formatNumber } from "../../utils/StringHelperFunctions"; -import { IBladeburner } from "../IBladeburner"; +import { Bladeburner } from "../Bladeburner"; import Typography from "@mui/material/Typography"; interface IProps { - bladeburner: IBladeburner; + bladeburner: Bladeburner; } export function SkillPage(props: IProps): React.ReactElement { diff --git a/src/Bladeburner/ui/StartButton.tsx b/src/Bladeburner/ui/StartButton.tsx index ce03674f3..b92f2b592 100644 --- a/src/Bladeburner/ui/StartButton.tsx +++ b/src/Bladeburner/ui/StartButton.tsx @@ -1,13 +1,13 @@ import React from "react"; -import { IBladeburner } from "../IBladeburner"; +import { Bladeburner } from "../Bladeburner"; import { BlackOperation } from "../BlackOperation"; import { Player } from "../../Player"; import Button from "@mui/material/Button"; import { AugmentationNames } from "../../Augmentation/data/AugmentationNames"; interface IProps { - bladeburner: IBladeburner; + bladeburner: Bladeburner; type: number; name: string; rerender: () => void; diff --git a/src/Bladeburner/ui/Stats.tsx b/src/Bladeburner/ui/Stats.tsx index a9d1d0930..a0e6c2417 100644 --- a/src/Bladeburner/ui/Stats.tsx +++ b/src/Bladeburner/ui/Stats.tsx @@ -7,7 +7,7 @@ import { numeralWrapper } from "../../ui/numeralFormat"; import { Factions } from "../../Faction/Factions"; import { Router } from "../../ui/GameRoot"; import { joinFaction } from "../../Faction/FactionHelpers"; -import { IBladeburner } from "../IBladeburner"; +import { Bladeburner } from "../Bladeburner"; import { TravelModal } from "./TravelModal"; import Typography from "@mui/material/Typography"; @@ -18,7 +18,7 @@ import Paper from "@mui/material/Paper"; import { FactionNames } from "../../Faction/data/FactionNames"; interface IProps { - bladeburner: IBladeburner; + bladeburner: Bladeburner; } export function Stats(props: IProps): React.ReactElement { diff --git a/src/Bladeburner/ui/SuccessChance.tsx b/src/Bladeburner/ui/SuccessChance.tsx index 285a730d6..fe39358a5 100644 --- a/src/Bladeburner/ui/SuccessChance.tsx +++ b/src/Bladeburner/ui/SuccessChance.tsx @@ -2,13 +2,13 @@ import React from "react"; import { formatNumber } from "../../utils/StringHelperFunctions"; import { StealthIcon } from "./StealthIcon"; import { KillIcon } from "./KillIcon"; -import { IAction } from "../IAction"; -import { IBladeburner } from "../IBladeburner"; +import { Action } from "../Action"; +import { Bladeburner } from "../Bladeburner"; import { Player } from "../../Player"; interface IProps { - bladeburner: IBladeburner; - action: IAction; + bladeburner: Bladeburner; + action: Action; } export function SuccessChance(props: IProps): React.ReactElement { diff --git a/src/Bladeburner/ui/TeamSizeButton.tsx b/src/Bladeburner/ui/TeamSizeButton.tsx index 81093a23a..9972afb35 100644 --- a/src/Bladeburner/ui/TeamSizeButton.tsx +++ b/src/Bladeburner/ui/TeamSizeButton.tsx @@ -1,12 +1,12 @@ import React, { useState } from "react"; import { Operation } from "../Operation"; -import { IBladeburner } from "../IBladeburner"; +import { Bladeburner } from "../Bladeburner"; import { TeamSizeModal } from "./TeamSizeModal"; import { formatNumber } from "../../utils/StringHelperFunctions"; import Button from "@mui/material/Button"; interface IProps { action: Operation; - bladeburner: IBladeburner; + bladeburner: Bladeburner; } export function TeamSizeButton(props: IProps): React.ReactElement { const [open, setOpen] = useState(false); diff --git a/src/Bladeburner/ui/TeamSizeModal.tsx b/src/Bladeburner/ui/TeamSizeModal.tsx index 743f864aa..52a74f621 100644 --- a/src/Bladeburner/ui/TeamSizeModal.tsx +++ b/src/Bladeburner/ui/TeamSizeModal.tsx @@ -2,13 +2,13 @@ import React, { useState } from "react"; import { dialogBoxCreate } from "../../ui/React/DialogBox"; import { Modal } from "../../ui/React/Modal"; import { Action } from "../Action"; -import { IBladeburner } from "../IBladeburner"; +import { Bladeburner } from "../Bladeburner"; import Typography from "@mui/material/Typography"; import Button from "@mui/material/Button"; import TextField from "@mui/material/TextField"; interface IProps { - bladeburner: IBladeburner; + bladeburner: Bladeburner; action: Action; open: boolean; onClose: () => void; diff --git a/src/Bladeburner/ui/TravelModal.tsx b/src/Bladeburner/ui/TravelModal.tsx index c4e5351db..fb7bcaef5 100644 --- a/src/Bladeburner/ui/TravelModal.tsx +++ b/src/Bladeburner/ui/TravelModal.tsx @@ -1,5 +1,5 @@ import React from "react"; -import { IBladeburner } from "../IBladeburner"; +import { Bladeburner } from "../Bladeburner"; import { WorldMap } from "../../ui/React/WorldMap"; import { Modal } from "../../ui/React/Modal"; import { CityName } from "../../Locations/data/CityNames"; @@ -8,7 +8,7 @@ import Typography from "@mui/material/Typography"; import Button from "@mui/material/Button"; interface IProps { - bladeburner: IBladeburner; + bladeburner: Bladeburner; open: boolean; onClose: () => void; } diff --git a/src/NetscriptFunctions/Bladeburner.ts b/src/NetscriptFunctions/Bladeburner.ts index 54e379700..0b0c3e8ea 100644 --- a/src/NetscriptFunctions/Bladeburner.ts +++ b/src/NetscriptFunctions/Bladeburner.ts @@ -2,7 +2,7 @@ import { Player } from "../Player"; import { Bladeburner } from "../Bladeburner/Bladeburner"; import { BitNodeMultipliers } from "../BitNode/BitNodeMultipliers"; import { Bladeburner as INetscriptBladeburner, BladeburnerCurAction } from "../ScriptEditor/NetscriptDefinitions"; -import { IAction } from "src/Bladeburner/IAction"; +import { Action } from "src/Bladeburner/Action"; import { InternalAPI, NetscriptContext } from "src/Netscript/APIWrapper"; import { BlackOperation } from "../Bladeburner/BlackOperation"; import { helpers } from "../Netscript/NetscriptHelpers"; @@ -31,7 +31,7 @@ export function NetscriptBladeburner(): InternalAPI { } }; - const getBladeburnerActionObject = function (ctx: NetscriptContext, type: string, name: string): IAction { + const getBladeburnerActionObject = function (ctx: NetscriptContext, type: string, name: string): Action { const bladeburner = Player.bladeburner; if (bladeburner === null) throw new Error("Must have joined bladeburner"); const actionId = bladeburner.getActionIdFromTypeAndName(type, name); diff --git a/src/PersonObjects/Player/PlayerObject.ts b/src/PersonObjects/Player/PlayerObject.ts index e083fb46a..73b8b0a50 100644 --- a/src/PersonObjects/Player/PlayerObject.ts +++ b/src/PersonObjects/Player/PlayerObject.ts @@ -15,7 +15,7 @@ import { LocationName } from "../../Locations/data/LocationNames"; import { IPlayerOwnedAugmentation } from "../../Augmentation/PlayerOwnedAugmentation"; import { ICorporation } from "../../Corporation/ICorporation"; import { IGang } from "../../Gang/IGang"; -import { IBladeburner } from "../../Bladeburner/IBladeburner"; +import { Bladeburner } from "../../Bladeburner/Bladeburner"; import { HacknetNode } from "../../Hacknet/HacknetNode"; import { HashManager } from "../../Hacknet/HashManager"; @@ -34,7 +34,7 @@ export class PlayerObject extends Person { bitNodeN = 1; //current bitnode corporation: ICorporation | null = null; gang: IGang | null = null; - bladeburner: IBladeburner | null = null; + bladeburner: Bladeburner | null = null; currentServer = ""; factions: string[] = []; factionInvitations: string[] = []; From 557bc1256233376961be8cb671ec0156b17b0897 Mon Sep 17 00:00:00 2001 From: Snarling <84951833+Snarling@users.noreply.github.com> Date: Tue, 20 Sep 2022 03:15:00 -0400 Subject: [PATCH 26/46] More classes as types --- src/Bladeburner/ActionIdentifier.ts | 3 +- src/Bladeburner/Bladeburner.tsx | 21 +++--- src/Bladeburner/IActionIdentifier.ts | 4 -- src/Bladeburner/ui/StartButton.tsx | 3 +- src/CotMG/BaseGift.ts | 29 ++++++++ src/CotMG/DummyGift.ts | 67 ------------------- src/CotMG/Helper.tsx | 6 +- src/CotMG/IStaneksGift.ts | 22 ------ src/CotMG/StaneksGift.ts | 18 ++--- src/CotMG/ui/ActiveFragmentSummary.tsx | 4 +- src/CotMG/ui/DummyGrid.tsx | 4 +- src/CotMG/ui/FragmentInspector.tsx | 4 +- src/CotMG/ui/FragmentSelector.tsx | 6 +- src/CotMG/ui/Grid.tsx | 4 +- src/CotMG/ui/MainBoard.tsx | 4 +- src/CotMG/ui/StaneksGiftRoot.tsx | 4 +- src/PersonObjects/Player/PlayerObject.ts | 2 +- .../Player/PlayerObjectGeneralMethods.ts | 5 +- 18 files changed, 67 insertions(+), 143 deletions(-) delete mode 100644 src/Bladeburner/IActionIdentifier.ts create mode 100644 src/CotMG/BaseGift.ts delete mode 100644 src/CotMG/DummyGift.ts delete mode 100644 src/CotMG/IStaneksGift.ts diff --git a/src/Bladeburner/ActionIdentifier.ts b/src/Bladeburner/ActionIdentifier.ts index 9368bb874..cab31083f 100644 --- a/src/Bladeburner/ActionIdentifier.ts +++ b/src/Bladeburner/ActionIdentifier.ts @@ -1,4 +1,3 @@ -import { IActionIdentifier } from "./IActionIdentifier"; import { Generic_fromJSON, Generic_toJSON, IReviverValue, Reviver } from "../utils/JSONReviver"; interface IParams { @@ -6,7 +5,7 @@ interface IParams { type?: number; } -export class ActionIdentifier implements IActionIdentifier { +export class ActionIdentifier { name = ""; type = -1; diff --git a/src/Bladeburner/Bladeburner.tsx b/src/Bladeburner/Bladeburner.tsx index a7dff6eb2..1c88a4678 100644 --- a/src/Bladeburner/Bladeburner.tsx +++ b/src/Bladeburner/Bladeburner.tsx @@ -1,5 +1,4 @@ import { Reviver, Generic_toJSON, Generic_fromJSON, IReviverValue } from "../utils/JSONReviver"; -import { IActionIdentifier } from "./IActionIdentifier"; import { ActionIdentifier } from "./ActionIdentifier"; import { ActionTypes } from "./data/ActionTypes"; import { Growths } from "./data/Growths"; @@ -66,7 +65,7 @@ export class Bladeburner { actionTimeCurrent = 0; actionTimeOverflow = 0; - action: IActionIdentifier = new ActionIdentifier({ + action: ActionIdentifier = new ActionIdentifier({ type: ActionTypes["Idle"], }); @@ -88,11 +87,11 @@ export class Bladeburner { events: true, }; automateEnabled = false; - automateActionHigh: IActionIdentifier = new ActionIdentifier({ + automateActionHigh: ActionIdentifier = new ActionIdentifier({ type: ActionTypes["Idle"], }); automateThreshHigh = 0; - automateActionLow: IActionIdentifier = new ActionIdentifier({ + automateActionLow: ActionIdentifier = new ActionIdentifier({ type: ActionTypes["Idle"], }); automateThreshLow = 0; @@ -124,7 +123,7 @@ export class Bladeburner { return Math.min(1, this.stamina / (0.5 * this.maxStamina)); } - canAttemptBlackOp(actionId: IActionIdentifier): BlackOpsAttempt { + canAttemptBlackOp(actionId: ActionIdentifier): BlackOpsAttempt { // Safety measure - don't repeat BlackOps that are already done if (this.blackops[actionId.name] != null) { return { error: "Tried to start a Black Operation that had already been completed" }; @@ -162,7 +161,7 @@ export class Bladeburner { } /** This function is only for the player. Sleeves use their own functions to perform blade work. */ - startAction(actionId: IActionIdentifier): void { + startAction(actionId: ActionIdentifier): void { if (actionId == null) return; this.action = actionId; this.actionTimeCurrent = 0; @@ -309,7 +308,7 @@ export class Bladeburner { } // working on - getActionIdFromTypeAndName(type = "", name = ""): IActionIdentifier | null { + getActionIdFromTypeAndName(type = "", name = ""): ActionIdentifier | null { if (type === "" || name === "") { return null; } @@ -1201,7 +1200,7 @@ export class Bladeburner { } } - getActionObject(actionId: IActionIdentifier): Action | null { + getActionObject(actionId: ActionIdentifier): Action | null { /** * Given an ActionIdentifier object, returns the corresponding * GeneralAction, Contract, Operation, or BlackOperation object @@ -1231,7 +1230,7 @@ export class Bladeburner { } } - completeContract(success: boolean, actionIdent: IActionIdentifier): void { + completeContract(success: boolean, actionIdent: ActionIdentifier): void { if (actionIdent.type !== ActionTypes.Contract) { throw new Error("completeContract() called even though current action is not a Contract"); } @@ -1256,7 +1255,7 @@ export class Bladeburner { } } - completeAction(person: Person, actionIdent: IActionIdentifier, isPlayer = true): ITaskTracker { + completeAction(person: Person, actionIdent: ActionIdentifier, isPlayer = true): ITaskTracker { let retValue = createTaskTracker(); switch (actionIdent.type) { case ActionTypes["Contract"]: @@ -2060,7 +2059,7 @@ export class Bladeburner { } } - getTypeAndNameFromActionId(actionId: IActionIdentifier): { + getTypeAndNameFromActionId(actionId: ActionIdentifier): { type: string; name: string; } { diff --git a/src/Bladeburner/IActionIdentifier.ts b/src/Bladeburner/IActionIdentifier.ts deleted file mode 100644 index 3d2414e36..000000000 --- a/src/Bladeburner/IActionIdentifier.ts +++ /dev/null @@ -1,4 +0,0 @@ -export interface IActionIdentifier { - name: string; - type: number; -} diff --git a/src/Bladeburner/ui/StartButton.tsx b/src/Bladeburner/ui/StartButton.tsx index b92f2b592..b7ff5489c 100644 --- a/src/Bladeburner/ui/StartButton.tsx +++ b/src/Bladeburner/ui/StartButton.tsx @@ -5,6 +5,7 @@ import { BlackOperation } from "../BlackOperation"; import { Player } from "../../Player"; import Button from "@mui/material/Button"; import { AugmentationNames } from "../../Augmentation/data/AugmentationNames"; +import { ActionIdentifier } from "../ActionIdentifier"; interface IProps { bladeburner: Bladeburner; @@ -13,7 +14,7 @@ interface IProps { rerender: () => void; } export function StartButton(props: IProps): React.ReactElement { - const action = props.bladeburner.getActionObject({ name: props.name, type: props.type }); + const action = props.bladeburner.getActionObject(new ActionIdentifier({ name: props.name, type: props.type })); if (action == null) { throw new Error("Failed to get Operation Object for: " + props.name); } diff --git a/src/CotMG/BaseGift.ts b/src/CotMG/BaseGift.ts new file mode 100644 index 000000000..9c6460679 --- /dev/null +++ b/src/CotMG/BaseGift.ts @@ -0,0 +1,29 @@ +import { ActiveFragment } from "./ActiveFragment"; + +export class BaseGift { + fragments: ActiveFragment[]; + _width?: number; + _height?: number; + + constructor(width?: number, height?: number, fragments: ActiveFragment[] = []) { + this.fragments = fragments; + this._width = width; + this._height = height; + } + + width(): number { + return this._width || 4; + } + height(): number { + return this._height || 4; + } + fragmentAt(worldX: number, worldY: number): ActiveFragment | undefined { + for (const aFrag of this.fragments) { + if (aFrag.fullAt(worldX, worldY)) { + return aFrag; + } + } + + return undefined; + } +} diff --git a/src/CotMG/DummyGift.ts b/src/CotMG/DummyGift.ts deleted file mode 100644 index 22de183a3..000000000 --- a/src/CotMG/DummyGift.ts +++ /dev/null @@ -1,67 +0,0 @@ -import { ActiveFragment } from "./ActiveFragment"; -import { IStaneksGift } from "./IStaneksGift"; - -export class DummyGift implements IStaneksGift { - storedCycles = 0; - fragments: ActiveFragment[] = []; - _width: number; - _height: number; - - constructor(width: number, height: number, fragments: ActiveFragment[]) { - this.fragments = fragments; - this._width = width; - this._height = height; - } - - width(): number { - return this._width; - } - height(): number { - return this._height; - } - charge(): void { - throw new Error("unimplemented for dummy gift"); - } - process(): void { - throw new Error("unimplemented for dummy gift"); - } - effect(): number { - throw new Error("unimplemented for dummy gift"); - } - canPlace(): boolean { - throw new Error("unimplemented for dummy gift"); - } - place(): boolean { - throw new Error("unimplemented for dummy gift"); - } - findFragment(): ActiveFragment | undefined { - throw new Error("unimplemented for dummy gift"); - } - fragmentAt(worldX: number, worldY: number): ActiveFragment | undefined { - for (const aFrag of this.fragments) { - if (aFrag.fullAt(worldX, worldY)) { - return aFrag; - } - } - - return undefined; - } - delete(): boolean { - throw new Error("unimplemented for dummy gift"); - } - clear(): void { - throw new Error("unimplemented for dummy gift"); - } - count(): number { - throw new Error("unimplemented for dummy gift"); - } - inBonus(): boolean { - throw new Error("unimplemented for dummy gift"); - } - prestigeAugmentation(): void { - throw new Error("unimplemented for dummy gift"); - } - prestigeSourceFile(): void { - throw new Error("unimplemented for dummy gift"); - } -} diff --git a/src/CotMG/Helper.tsx b/src/CotMG/Helper.tsx index 854f6e0be..661c1948b 100644 --- a/src/CotMG/Helper.tsx +++ b/src/CotMG/Helper.tsx @@ -1,9 +1,9 @@ import { Reviver } from "../utils/JSONReviver"; +import { BaseGift } from "./BaseGift"; -import { IStaneksGift } from "./IStaneksGift"; import { StaneksGift } from "./StaneksGift"; -export let staneksGift: IStaneksGift = new StaneksGift(); +export let staneksGift = new StaneksGift(); export function loadStaneksGift(saveString: string): void { if (saveString) { @@ -23,7 +23,7 @@ export function zeros(width: number, height: number): number[][] { return array; } -export function calculateGrid(gift: IStaneksGift): number[][] { +export function calculateGrid(gift: BaseGift): number[][] { const newgrid = zeros(gift.width(), gift.height()) as unknown as number[][]; for (let i = 0; i < gift.width(); i++) { for (let j = 0; j < gift.height(); j++) { diff --git a/src/CotMG/IStaneksGift.ts b/src/CotMG/IStaneksGift.ts deleted file mode 100644 index 9dbc2c329..000000000 --- a/src/CotMG/IStaneksGift.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { ActiveFragment } from "./ActiveFragment"; -import { Fragment } from "./Fragment"; - -export interface IStaneksGift { - storedCycles: number; - fragments: ActiveFragment[]; - width(): number; - height(): number; - charge(fragment: ActiveFragment, threads: number): void; - process(n: number): void; - effect(fragment: ActiveFragment): number; - canPlace(x: number, y: number, rotation: number, fragment: Fragment): boolean; - place(x: number, y: number, rotation: number, fragment: Fragment): boolean; - findFragment(rootX: number, rootY: number): ActiveFragment | undefined; - fragmentAt(rootX: number, rootY: number): ActiveFragment | undefined; - delete(rootX: number, rootY: number): boolean; - clear(): void; - count(fragment: Fragment): number; - inBonus(): boolean; - prestigeAugmentation(): void; - prestigeSourceFile(): void; -} diff --git a/src/CotMG/StaneksGift.ts b/src/CotMG/StaneksGift.ts index 876f9e41d..a914c4b6e 100644 --- a/src/CotMG/StaneksGift.ts +++ b/src/CotMG/StaneksGift.ts @@ -2,7 +2,7 @@ import { FactionNames } from "../Faction/data/FactionNames"; import { Fragment } from "./Fragment"; import { ActiveFragment } from "./ActiveFragment"; import { FragmentType } from "./FragmentType"; -import { IStaneksGift } from "./IStaneksGift"; +import { BaseGift } from "./BaseGift"; import { Factions } from "../Faction/Factions"; import { CalculateEffect } from "./formulas/effect"; import { StaneksGiftEvents } from "./StaneksGiftEvents"; @@ -14,9 +14,11 @@ import { Player } from "../Player"; import { AugmentationNames } from "../Augmentation/data/AugmentationNames"; import { defaultMultipliers, mergeMultipliers, Multipliers, scaleMultipliers } from "../PersonObjects/Multipliers"; -export class StaneksGift implements IStaneksGift { +export class StaneksGift extends BaseGift { storedCycles = 0; - fragments: ActiveFragment[] = []; + constructor() { + super(); + } baseSize(): number { return StanekConstants.BaseSize + BitNodeMultipliers.StaneksGiftExtraSize + Player.sourceFileLvl(13); @@ -95,16 +97,6 @@ export class StaneksGift implements IStaneksGift { return this.fragments.find((f) => f.x === rootX && f.y === rootY); } - fragmentAt(worldX: number, worldY: number): ActiveFragment | undefined { - for (const aFrag of this.fragments) { - if (aFrag.fullAt(worldX, worldY)) { - return aFrag; - } - } - - return undefined; - } - count(fragment: Fragment): number { let amt = 0; for (const aFrag of this.fragments) { diff --git a/src/CotMG/ui/ActiveFragmentSummary.tsx b/src/CotMG/ui/ActiveFragmentSummary.tsx index 5eb8c4c03..75495a5be 100644 --- a/src/CotMG/ui/ActiveFragmentSummary.tsx +++ b/src/CotMG/ui/ActiveFragmentSummary.tsx @@ -1,6 +1,6 @@ import React from "react"; import { ActiveFragment } from "../ActiveFragment"; -import { IStaneksGift } from "../IStaneksGift"; +import { StaneksGift } from "../StaneksGift"; import { FragmentType, Effect } from "../FragmentType"; import { numeralWrapper } from "../../ui/numeralFormat"; @@ -10,7 +10,7 @@ import Table from "@mui/material/Table"; import { TableBody, TableCell, TableRow } from "@mui/material"; type IProps = { - gift: IStaneksGift; + gift: StaneksGift; }; function formatEffect(effect: number, type: FragmentType): string { diff --git a/src/CotMG/ui/DummyGrid.tsx b/src/CotMG/ui/DummyGrid.tsx index 94dbbda89..ad2b675e8 100644 --- a/src/CotMG/ui/DummyGrid.tsx +++ b/src/CotMG/ui/DummyGrid.tsx @@ -1,7 +1,7 @@ import { Box, Table } from "@mui/material"; import * as React from "react"; import { ActiveFragment } from "../ActiveFragment"; -import { DummyGift } from "../DummyGift"; +import { BaseGift } from "../BaseGift"; import { Grid } from "./Grid"; import { zeros } from "../Helper"; @@ -12,7 +12,7 @@ interface IProps { } export function DummyGrid(props: IProps): React.ReactElement { - const gift = new DummyGift(props.width, props.height, props.fragments); + const gift = new BaseGift(props.width, props.height, props.fragments); const ghostGrid = zeros(props.width, props.height); return ( diff --git a/src/CotMG/ui/FragmentInspector.tsx b/src/CotMG/ui/FragmentInspector.tsx index 3582c3b55..0c089a4d3 100644 --- a/src/CotMG/ui/FragmentInspector.tsx +++ b/src/CotMG/ui/FragmentInspector.tsx @@ -1,6 +1,6 @@ import React, { useState, useEffect } from "react"; import { ActiveFragment } from "../ActiveFragment"; -import { IStaneksGift } from "../IStaneksGift"; +import { StaneksGift } from "../StaneksGift"; import { FragmentType, Effect } from "../FragmentType"; import { numeralWrapper } from "../../ui/numeralFormat"; @@ -8,7 +8,7 @@ import Paper from "@mui/material/Paper"; import Typography from "@mui/material/Typography"; type IProps = { - gift: IStaneksGift; + gift: StaneksGift; fragment: ActiveFragment | undefined; x: number; y: number; diff --git a/src/CotMG/ui/FragmentSelector.tsx b/src/CotMG/ui/FragmentSelector.tsx index 4a0af8967..3940e3599 100644 --- a/src/CotMG/ui/FragmentSelector.tsx +++ b/src/CotMG/ui/FragmentSelector.tsx @@ -1,7 +1,7 @@ import React, { useState } from "react"; import { Fragments, Fragment, NoneFragment, DeleteFragment } from "../Fragment"; import { FragmentType, Effect } from "../FragmentType"; -import { IStaneksGift } from "../IStaneksGift"; +import { StaneksGift } from "../StaneksGift"; import { FragmentPreview } from "./FragmentPreview"; import { numeralWrapper } from "../../ui/numeralFormat"; @@ -11,7 +11,7 @@ import Typography from "@mui/material/Typography"; import Box from "@mui/material/Box"; type IOptionProps = { - gift: IStaneksGift; + gift: StaneksGift; fragment: Fragment; selectFragment: (fragment: Fragment) => void; }; @@ -46,7 +46,7 @@ function FragmentOption(props: IOptionProps): React.ReactElement { } type IProps = { - gift: IStaneksGift; + gift: StaneksGift; selectFragment: (fragment: Fragment) => void; }; diff --git a/src/CotMG/ui/Grid.tsx b/src/CotMG/ui/Grid.tsx index 78dd13b98..82efcdf09 100644 --- a/src/CotMG/ui/Grid.tsx +++ b/src/CotMG/ui/Grid.tsx @@ -2,14 +2,14 @@ import { TableBody, TableRow } from "@mui/material"; import * as React from "react"; import { ActiveFragment } from "../ActiveFragment"; import { calculateGrid } from "../Helper"; -import { IStaneksGift } from "../IStaneksGift"; +import { BaseGift } from "../BaseGift"; import { Cell } from "./Cell"; interface IProps { width: number; height: number; ghostGrid: number[][]; - gift: IStaneksGift; + gift: BaseGift; enter(i: number, j: number): void; click(i: number, j: number): void; } diff --git a/src/CotMG/ui/MainBoard.tsx b/src/CotMG/ui/MainBoard.tsx index 21ddecbc6..a320dee53 100644 --- a/src/CotMG/ui/MainBoard.tsx +++ b/src/CotMG/ui/MainBoard.tsx @@ -1,7 +1,7 @@ import * as React from "react"; import { Fragment, NoneFragment } from "../Fragment"; import { FragmentType } from "../FragmentType"; -import { IStaneksGift } from "../IStaneksGift"; +import { StaneksGift } from "../StaneksGift"; import { FragmentInspector } from "./FragmentInspector"; import { FragmentSelector } from "./FragmentSelector"; import Box from "@mui/material/Box"; @@ -14,7 +14,7 @@ import Tooltip from "@mui/material/Tooltip"; import Typography from "@mui/material/Typography"; interface IProps { - gift: IStaneksGift; + gift: StaneksGift; } export function MainBoard(props: IProps): React.ReactElement { diff --git a/src/CotMG/ui/StaneksGiftRoot.tsx b/src/CotMG/ui/StaneksGiftRoot.tsx index eaacc58ad..d4c091ff8 100644 --- a/src/CotMG/ui/StaneksGiftRoot.tsx +++ b/src/CotMG/ui/StaneksGiftRoot.tsx @@ -3,7 +3,7 @@ import { convertTimeMsToTimeElapsedString } from "../../utils/StringHelperFuncti import { CONSTANTS } from "../../Constants"; import { StaneksGiftEvents } from "../StaneksGiftEvents"; import { MainBoard } from "./MainBoard"; -import { IStaneksGift } from "../IStaneksGift"; +import { StaneksGift } from "../StaneksGift"; import { Info } from "@mui/icons-material"; import { dialogBoxCreate } from "../../ui/React/DialogBox"; import Typography from "@mui/material/Typography"; @@ -13,7 +13,7 @@ import { DummyGrid } from "./DummyGrid"; import Container from "@mui/material/Container"; type IProps = { - staneksGift: IStaneksGift; + staneksGift: StaneksGift; }; export function StaneksGiftRoot({ staneksGift }: IProps): React.ReactElement { diff --git a/src/PersonObjects/Player/PlayerObject.ts b/src/PersonObjects/Player/PlayerObject.ts index 73b8b0a50..d42cc2e39 100644 --- a/src/PersonObjects/Player/PlayerObject.ts +++ b/src/PersonObjects/Player/PlayerObject.ts @@ -178,4 +178,4 @@ export class PlayerObject extends Person { } } -Reviver.constructors.PlayerObject = PlayerObject; \ No newline at end of file +Reviver.constructors.PlayerObject = PlayerObject; diff --git a/src/PersonObjects/Player/PlayerObjectGeneralMethods.ts b/src/PersonObjects/Player/PlayerObjectGeneralMethods.ts index f27c3bd50..490d92739 100644 --- a/src/PersonObjects/Player/PlayerObjectGeneralMethods.ts +++ b/src/PersonObjects/Player/PlayerObjectGeneralMethods.ts @@ -23,10 +23,7 @@ import { CityName } from "../../Locations/data/CityNames"; import { LocationName } from "../../Locations/data/LocationNames"; import { Sleeve } from "../Sleeve/Sleeve"; import { isSleeveCompanyWork } from "../Sleeve/Work/SleeveCompanyWork"; -import { - calculateSkillProgress as calculateSkillProgressF, - ISkillProgress, -} from "../formulas/skill"; +import { calculateSkillProgress as calculateSkillProgressF, ISkillProgress } from "../formulas/skill"; import { GetServer, AddToAllServers, createUniqueRandomIp } from "../../Server/AllServers"; import { Server } from "../../Server/Server"; import { safetlyCreateUniqueServer } from "../../Server/ServerHelpers"; From bc7c15ad77f3d7ac98fa153027f64dccdc122077 Mon Sep 17 00:00:00 2001 From: Snarling <84951833+Snarling@users.noreply.github.com> Date: Tue, 20 Sep 2022 06:47:54 -0400 Subject: [PATCH 27/46] corp: classes are types --- src/Corporation/Actions.ts | 36 ++++----- src/Corporation/Employee.ts | 6 +- src/Corporation/ICorporation.ts | 62 --------------- src/Corporation/IIndustry.ts | 78 ------------------- src/Corporation/Industry.ts | 17 ++-- src/Corporation/IndustryData.tsx | 32 ++++---- src/Corporation/OfficeSpace.ts | 8 +- src/Corporation/Product.ts | 6 +- src/Corporation/Warehouse.ts | 10 +-- src/Corporation/ui/Context.ts | 16 ++-- src/Corporation/ui/CorporationRoot.tsx | 4 +- src/Corporation/ui/ExpandIndustryTab.tsx | 4 +- src/Corporation/ui/Helpers.tsx | 4 +- .../ui/IndustryProductEquation.tsx | 4 +- src/Corporation/ui/IndustryWarehouse.tsx | 8 +- src/Corporation/ui/MainPanel.tsx | 4 +- src/Corporation/ui/MoneyCost.tsx | 4 +- src/Corporation/ui/modals/ExportModal.tsx | 10 +-- src/Corporation/ui/modals/ResearchModal.tsx | 6 +- src/Corporation/ui/modals/SellSharesModal.tsx | 4 +- .../ui/modals/UpgradeOfficeSizeModal.tsx | 4 +- src/NetscriptFunctions/Corporation.ts | 13 ++-- src/PersonObjects/Player/PlayerObject.ts | 4 +- 23 files changed, 100 insertions(+), 244 deletions(-) delete mode 100644 src/Corporation/ICorporation.ts delete mode 100644 src/Corporation/IIndustry.ts diff --git a/src/Corporation/Actions.ts b/src/Corporation/Actions.ts index 07e475b6f..820017692 100644 --- a/src/Corporation/Actions.ts +++ b/src/Corporation/Actions.ts @@ -1,8 +1,6 @@ import { Player } from "../Player"; import { MaterialSizes } from "./MaterialSizes"; -import { ICorporation } from "./ICorporation"; import { Corporation } from "./Corporation"; -import { IIndustry } from "./IIndustry"; import { IndustryStartingCosts, IndustryResearchTrees } from "./IndustryData"; import { Industry } from "./Industry"; import { CorporationConstants } from "./data/Constants"; @@ -17,7 +15,7 @@ import { EmployeePositions } from "./EmployeePositions"; import { ResearchMap } from "./ResearchMap"; import { isRelevantMaterial } from "./ui/Helpers"; -export function NewIndustry(corporation: ICorporation, industry: string, name: string): void { +export function NewIndustry(corporation: Corporation, industry: string, name: string): void { if (corporation.divisions.find(({ type }) => industry == type)) throw new Error(`You have already expanded into the ${industry} industry!`); @@ -47,7 +45,7 @@ export function NewIndustry(corporation: ICorporation, industry: string, name: s } } -export function NewCity(corporation: ICorporation, division: IIndustry, city: string): void { +export function NewCity(corporation: Corporation, division: Industry, city: string): void { if (corporation.funds < CorporationConstants.OfficeInitialCost) { throw new Error("You don't have enough company funds to open a new office!"); } @@ -61,7 +59,7 @@ export function NewCity(corporation: ICorporation, division: IIndustry, city: st }); } -export function UnlockUpgrade(corporation: ICorporation, upgrade: CorporationUnlockUpgrade): void { +export function UnlockUpgrade(corporation: Corporation, upgrade: CorporationUnlockUpgrade): void { if (corporation.funds < upgrade.price) { throw new Error("Insufficient funds"); } @@ -71,7 +69,7 @@ export function UnlockUpgrade(corporation: ICorporation, upgrade: CorporationUnl corporation.unlock(upgrade); } -export function LevelUpgrade(corporation: ICorporation, upgrade: CorporationUpgrade): void { +export function LevelUpgrade(corporation: Corporation, upgrade: CorporationUpgrade): void { const baseCost = upgrade.basePrice; const priceMult = upgrade.priceMult; const level = corporation.upgrades[upgrade.index]; @@ -83,7 +81,7 @@ export function LevelUpgrade(corporation: ICorporation, upgrade: CorporationUpgr } } -export function IssueDividends(corporation: ICorporation, rate: number): void { +export function IssueDividends(corporation: Corporation, rate: number): void { if (isNaN(rate) || rate < 0 || rate > CorporationConstants.DividendMaxRate) { throw new Error(`Invalid value. Must be an number between 0 and ${CorporationConstants.DividendMaxRate}`); } @@ -252,7 +250,7 @@ export function BuyMaterial(material: Material, amt: number): void { material.buy = amt; } -export function BulkPurchase(corp: ICorporation, warehouse: Warehouse, material: Material, amt: number): void { +export function BulkPurchase(corp: Corporation, warehouse: Warehouse, material: Material, amt: number): void { const matSize = MaterialSizes[material.name]; const maxAmount = (warehouse.size - warehouse.sizeUsed) / matSize; if (isNaN(amt) || amt < 0) { @@ -270,7 +268,7 @@ export function BulkPurchase(corp: ICorporation, warehouse: Warehouse, material: } } -export function SellShares(corporation: ICorporation, numShares: number): number { +export function SellShares(corporation: Corporation, numShares: number): number { if (isNaN(numShares)) throw new Error("Invalid value for number of shares"); if (numShares < 0) throw new Error("Invalid value for number of shares"); if (numShares > corporation.numShares) throw new Error("You don't have that many shares to sell!"); @@ -290,7 +288,7 @@ export function SellShares(corporation: ICorporation, numShares: number): number return profit; } -export function BuyBackShares(corporation: ICorporation, numShares: number): boolean { +export function BuyBackShares(corporation: Corporation, numShares: number): boolean { if (isNaN(numShares)) throw new Error("Invalid value for number of shares"); if (numShares < 0) throw new Error("Invalid value for number of shares"); if (numShares > corporation.issuedShares) throw new Error("You don't have that many shares to buy!"); @@ -318,7 +316,7 @@ export function AutoAssignJob(office: OfficeSpace, job: string, count: number): return office.autoAssignJob(job, count); } -export function UpgradeOfficeSize(corp: ICorporation, office: OfficeSpace, size: number): void { +export function UpgradeOfficeSize(corp: Corporation, office: OfficeSpace, size: number): void { const initialPriceMult = Math.round(office.size / CorporationConstants.OfficeInitialSize); const costMultiplier = 1.09; // Calculate cost to upgrade size by 15 employees @@ -332,7 +330,7 @@ export function UpgradeOfficeSize(corp: ICorporation, office: OfficeSpace, size: corp.funds = corp.funds - cost; } -export function BuyCoffee(corp: ICorporation, office: OfficeSpace): boolean { +export function BuyCoffee(corp: Corporation, office: OfficeSpace): boolean { const cost = office.getCoffeeCost(); if (corp.funds < cost) { return false; @@ -346,7 +344,7 @@ export function BuyCoffee(corp: ICorporation, office: OfficeSpace): boolean { return true; } -export function ThrowParty(corp: ICorporation, office: OfficeSpace, costPerEmployee: number): number { +export function ThrowParty(corp: Corporation, office: OfficeSpace, costPerEmployee: number): number { const mult = 1 + costPerEmployee / 10e6; const cost = costPerEmployee * office.employees.length; if (corp.funds < cost) { @@ -361,7 +359,7 @@ export function ThrowParty(corp: ICorporation, office: OfficeSpace, costPerEmplo return mult; } -export function PurchaseWarehouse(corp: ICorporation, division: IIndustry, city: string): void { +export function PurchaseWarehouse(corp: Corporation, division: Industry, city: string): void { if (corp.funds < CorporationConstants.WarehouseInitialCost) return; if (division.warehouses[city] instanceof Warehouse) return; division.warehouses[city] = new Warehouse({ @@ -380,7 +378,7 @@ export function UpgradeWarehouseCost(warehouse: Warehouse, amt: number): number ); } -export function UpgradeWarehouse(corp: ICorporation, division: IIndustry, warehouse: Warehouse, amt = 1): void { +export function UpgradeWarehouse(corp: Corporation, division: Industry, warehouse: Warehouse, amt = 1): void { const sizeUpgradeCost = UpgradeWarehouseCost(warehouse, amt); if (corp.funds < sizeUpgradeCost) return; warehouse.level += amt; @@ -388,7 +386,7 @@ export function UpgradeWarehouse(corp: ICorporation, division: IIndustry, wareho corp.funds = corp.funds - sizeUpgradeCost; } -export function HireAdVert(corp: ICorporation, division: IIndustry): void { +export function HireAdVert(corp: Corporation, division: Industry): void { const cost = division.getAdVertCost(); if (corp.funds < cost) return; corp.funds = corp.funds - cost; @@ -396,8 +394,8 @@ export function HireAdVert(corp: ICorporation, division: IIndustry): void { } export function MakeProduct( - corp: ICorporation, - division: IIndustry, + corp: Corporation, + division: Industry, city: string, productName: string, designInvest: number, @@ -449,7 +447,7 @@ export function MakeProduct( products[product.name] = product; } -export function Research(division: IIndustry, researchName: string): void { +export function Research(division: Industry, researchName: string): void { const researchTree = IndustryResearchTrees[division.type]; if (researchTree === undefined) throw new Error(`No research tree for industry '${division.type}'`); const allResearch = researchTree.getAllNodes(); diff --git a/src/Corporation/Employee.ts b/src/Corporation/Employee.ts index a8c71e636..8cbd5e9cb 100644 --- a/src/Corporation/Employee.ts +++ b/src/Corporation/Employee.ts @@ -2,8 +2,8 @@ import { CorporationConstants } from "./data/Constants"; import { getRandomInt } from "../utils/helpers/getRandomInt"; import { Generic_fromJSON, Generic_toJSON, IReviverValue, Reviver } from "../utils/JSONReviver"; import { EmployeePositions } from "./EmployeePositions"; -import { ICorporation } from "./ICorporation"; -import { IIndustry } from "./IIndustry"; +import { Corporation } from "./Corporation"; +import { Industry } from "./Industry"; interface IParams { name?: string; @@ -77,7 +77,7 @@ export class Employee { return salary; } - calculateProductivity(corporation: ICorporation, industry: IIndustry): number { + calculateProductivity(corporation: Corporation, industry: Industry): number { const effCre = this.cre * corporation.getEmployeeCreMultiplier() * industry.getEmployeeCreMultiplier(), effCha = this.cha * corporation.getEmployeeChaMultiplier() * industry.getEmployeeChaMultiplier(), effInt = this.int * corporation.getEmployeeIntMultiplier() * industry.getEmployeeIntMultiplier(), diff --git a/src/Corporation/ICorporation.ts b/src/Corporation/ICorporation.ts deleted file mode 100644 index ea71c6cf5..000000000 --- a/src/Corporation/ICorporation.ts +++ /dev/null @@ -1,62 +0,0 @@ -import { Industry } from "./Industry"; -import { CorporationUnlockUpgrade } from "./data/CorporationUnlockUpgrades"; -import { CorporationUpgrade } from "./data/CorporationUpgrades"; -import { CorporationState } from "./CorporationState"; -import { IReviverValue } from "../utils/JSONReviver"; - -export interface ICorporation { - name: string; - - divisions: Industry[]; - - funds: number; - revenue: number; - expenses: number; - fundingRound: number; - public: boolean; - totalShares: number; - numShares: number; - shareSalesUntilPriceUpdate: number; - shareSaleCooldown: number; - issueNewSharesCooldown: number; - dividendRate: number; - dividendTax: number; - issuedShares: number; - sharePrice: number; - storedCycles: number; - valuation: number; - - unlockUpgrades: number[]; - upgrades: number[]; - upgradeMultipliers: number[]; - - state: CorporationState; - - addFunds(amt: number): void; - getState(): string; - storeCycles(numCycles: number): void; - process(): void; - determineValuation(): void; - determineCycleValuation(): number; - getTargetSharePrice(): number; - updateSharePrice(): void; - immediatelyUpdateSharePrice(): void; - calculateShareSale(numShares: number): [number, number, number]; - convertCooldownToString(cd: number): string; - unlock(upgrade: CorporationUnlockUpgrade): void; - upgrade(upgrade: CorporationUpgrade): void; - getProductionMultiplier(): number; - getStorageMultiplier(): number; - getDreamSenseGain(): number; - getAdvertisingMultiplier(): number; - getEmployeeCreMultiplier(): number; - getEmployeeChaMultiplier(): number; - getEmployeeIntMultiplier(): number; - getEmployeeEffMultiplier(): number; - getSalesMultiplier(): number; - getScientificResearchMultiplier(): number; - getStarterGuide(): void; - updateDividendTax(): void; - getCycleDividends(): number; - toJSON(): IReviverValue; -} diff --git a/src/Corporation/IIndustry.ts b/src/Corporation/IIndustry.ts deleted file mode 100644 index 0ea8646a1..000000000 --- a/src/Corporation/IIndustry.ts +++ /dev/null @@ -1,78 +0,0 @@ -import { Material } from "./Material"; -import { Warehouse } from "./Warehouse"; -import { ICorporation } from "./ICorporation"; -import { OfficeSpace } from "./OfficeSpace"; -import { Product } from "./Product"; -import { IReviverValue } from "../utils/JSONReviver"; - -export interface IIndustry { - name: string; - type: string; - sciResearch: Material; - researched: { [key: string]: boolean | undefined }; - reqMats: { [key: string]: number | undefined }; - - prodMats: string[]; - - products: { [key: string]: Product | undefined }; - makesProducts: boolean; - - awareness: number; - popularity: number; - startingCost: number; - - reFac: number; - sciFac: number; - hwFac: number; - robFac: number; - aiFac: number; - advFac: number; - - prodMult: number; - - // Decimal - lastCycleRevenue: number; - lastCycleExpenses: number; - thisCycleRevenue: number; - thisCycleExpenses: number; - - state: string; - newInd: boolean; - warehouses: { [key: string]: Warehouse | 0 }; - offices: { [key: string]: OfficeSpace | 0 }; - numAdVerts: number; - - init(): void; - getProductDescriptionText(): string; - getMaximumNumberProducts(): number; - hasMaximumNumberProducts(): boolean; - calculateProductionFactors(): void; - updateWarehouseSizeUsed(warehouse: Warehouse): void; - process(marketCycles: number, state: string, corporation: ICorporation): void; - processMaterialMarket(): void; - processProductMarket(marketCycles: number): void; - processMaterials(marketCycles: number, corporation: ICorporation): [number, number]; - processProducts(marketCycles: number, corporation: ICorporation): [number, number]; - processProduct(marketCycles: number, product: Product, corporation: ICorporation): number; - resetImports(state: string): void; - discontinueProduct(product: Product): void; - getAdVertCost(): number; - applyAdVert(corporation: ICorporation): void; - getOfficeProductivity(office: OfficeSpace, params?: { forProduct?: boolean }): number; - getBusinessFactor(office: OfficeSpace): number; - getAdvertisingFactors(): [number, number, number, number]; - getMarketFactor(mat: { dmd: number; cmp: number }): number; - hasResearch(name: string): boolean; - updateResearchTree(): void; - getAdvertisingMultiplier(): number; - getEmployeeChaMultiplier(): number; - getEmployeeCreMultiplier(): number; - getEmployeeEffMultiplier(): number; - getEmployeeIntMultiplier(): number; - getProductionMultiplier(): number; - getProductProductionMultiplier(): number; - getSalesMultiplier(): number; - getScientificResearchMultiplier(): number; - getStorageMultiplier(): number; - toJSON(): IReviverValue; -} diff --git a/src/Corporation/Industry.ts b/src/Corporation/Industry.ts index affcf04e2..74426c857 100644 --- a/src/Corporation/Industry.ts +++ b/src/Corporation/Industry.ts @@ -12,16 +12,15 @@ import { dialogBoxCreate } from "../ui/React/DialogBox"; import { isString } from "../utils/helpers/isString"; import { MaterialSizes } from "./MaterialSizes"; import { Warehouse } from "./Warehouse"; -import { ICorporation } from "./ICorporation"; -import { IIndustry } from "./IIndustry"; +import { Corporation } from "./Corporation"; interface IParams { name?: string; - corp?: ICorporation; + corp?: Corporation; type?: string; } -export class Industry implements IIndustry { +export class Industry { name = ""; type = Industries.Agriculture; sciResearch = new Material({ name: "Scientific Research" }); @@ -385,7 +384,7 @@ export class Industry implements IIndustry { } } - process(marketCycles = 1, state: string, corporation: ICorporation): void { + process(marketCycles = 1, state: string, corporation: Corporation): void { this.state = state; //At the start of a cycle, store and reset revenue/expenses @@ -518,7 +517,7 @@ export class Industry implements IIndustry { } //Process production, purchase, and import/export of materials - processMaterials(marketCycles = 1, corporation: ICorporation): [number, number] { + processMaterials(marketCycles = 1, corporation: Corporation): [number, number] { let revenue = 0, expenses = 0; this.calculateProductionFactors(); @@ -949,7 +948,7 @@ export class Industry implements IIndustry { } //Process production & sale of this industry's FINISHED products (including all of their stats) - processProducts(marketCycles = 1, corporation: ICorporation): [number, number] { + processProducts(marketCycles = 1, corporation: Corporation): [number, number] { let revenue = 0; const expenses = 0; @@ -985,7 +984,7 @@ export class Industry implements IIndustry { } //Processes FINISHED products - processProduct(marketCycles = 1, product: Product, corporation: ICorporation): number { + processProduct(marketCycles = 1, product: Product, corporation: Corporation): number { let totalProfit = 0; for (let i = 0; i < CorporationConstants.Cities.length; ++i) { const city = CorporationConstants.Cities[i]; @@ -1225,7 +1224,7 @@ export class Industry implements IIndustry { return 1e9 * Math.pow(1.06, this.numAdVerts); } - applyAdVert(corporation: ICorporation): void { + applyAdVert(corporation: Corporation): void { const advMult = corporation.getAdvertisingMultiplier() * this.getAdvertisingMultiplier(); const awareness = (this.awareness + 3 * advMult) * (1.01 * advMult); this.awareness = Math.min(awareness, Number.MAX_VALUE); diff --git a/src/Corporation/IndustryData.tsx b/src/Corporation/IndustryData.tsx index d2ae99dd3..0608129ef 100644 --- a/src/Corporation/IndustryData.tsx +++ b/src/Corporation/IndustryData.tsx @@ -1,6 +1,6 @@ import React from "react"; import { ResearchTree } from "./ResearchTree"; -import { ICorporation } from "./ICorporation"; +import { Corporation } from "./Corporation"; import { getBaseResearchTreeCopy, getProductIndustryResearchTreeCopy } from "./data/BaseResearchTree"; import { MoneyCost } from "./ui/MoneyCost"; @@ -59,8 +59,8 @@ export const IndustryStartingCosts: IIndustryMap = { }; // Map of description for each industry -export const IndustryDescriptions: IIndustryMap<(corp: ICorporation) => React.ReactElement> = { - Energy: (corp: ICorporation) => ( +export const IndustryDescriptions: IIndustryMap<(corp: Corporation) => React.ReactElement> = { + Energy: (corp: Corporation) => ( <> Engage in the production and distribution of energy.
    @@ -70,7 +70,7 @@ export const IndustryDescriptions: IIndustryMap<(corp: ICorporation) => React.Re Recommended starting Industry: NO ), - Utilities: (corp: ICorporation) => ( + Utilities: (corp: Corporation) => ( <> Distribute water and provide wastewater services.
    @@ -80,7 +80,7 @@ export const IndustryDescriptions: IIndustryMap<(corp: ICorporation) => React.Re Recommended starting Industry: NO ), - Agriculture: (corp: ICorporation) => ( + Agriculture: (corp: Corporation) => ( <> Cultivate crops and breed livestock to produce food.
    @@ -90,7 +90,7 @@ export const IndustryDescriptions: IIndustryMap<(corp: ICorporation) => React.Re Recommended starting Industry: YES ), - Fishing: (corp: ICorporation) => ( + Fishing: (corp: Corporation) => ( <> Produce food through the breeding and processing of fish and fish products.
    @@ -100,7 +100,7 @@ export const IndustryDescriptions: IIndustryMap<(corp: ICorporation) => React.Re Recommended starting Industry: NO ), - Mining: (corp: ICorporation) => ( + Mining: (corp: Corporation) => ( <> Extract and process metals from the earth.
    @@ -110,7 +110,7 @@ export const IndustryDescriptions: IIndustryMap<(corp: ICorporation) => React.Re Recommended starting Industry: NO ), - Food: (corp: ICorporation) => ( + Food: (corp: Corporation) => ( <> Create your own restaurants all around the world.
    @@ -120,7 +120,7 @@ export const IndustryDescriptions: IIndustryMap<(corp: ICorporation) => React.Re Recommended starting Industry: YES ), - Tobacco: (corp: ICorporation) => ( + Tobacco: (corp: Corporation) => ( <> Create and distribute tobacco and tobacco-related products.
    @@ -130,7 +130,7 @@ export const IndustryDescriptions: IIndustryMap<(corp: ICorporation) => React.Re Recommended starting Industry: YES ), - Chemical: (corp: ICorporation) => ( + Chemical: (corp: Corporation) => ( <> Produce industrial chemicals.
    @@ -140,7 +140,7 @@ export const IndustryDescriptions: IIndustryMap<(corp: ICorporation) => React.Re Recommended starting Industry: NO ), - Pharmaceutical: (corp: ICorporation) => ( + Pharmaceutical: (corp: Corporation) => ( <> Discover, develop, and create new pharmaceutical drugs.
    @@ -150,7 +150,7 @@ export const IndustryDescriptions: IIndustryMap<(corp: ICorporation) => React.Re Recommended starting Industry: NO ), - Computer: (corp: ICorporation) => ( + Computer: (corp: Corporation) => ( <> Develop and manufacture new computer hardware and networking infrastructures.
    @@ -160,7 +160,7 @@ export const IndustryDescriptions: IIndustryMap<(corp: ICorporation) => React.Re Recommended starting Industry: NO ), - Robotics: (corp: ICorporation) => ( + Robotics: (corp: Corporation) => ( <> Develop and create robots.
    @@ -170,7 +170,7 @@ export const IndustryDescriptions: IIndustryMap<(corp: ICorporation) => React.Re Recommended starting Industry: NO ), - Software: (corp: ICorporation) => ( + Software: (corp: Corporation) => ( <> Develop computer software and create AI Cores.
    @@ -180,7 +180,7 @@ export const IndustryDescriptions: IIndustryMap<(corp: ICorporation) => React.Re Recommended starting Industry: YES ), - Healthcare: (corp: ICorporation) => ( + Healthcare: (corp: Corporation) => ( <> Create and manage hospitals.
    @@ -190,7 +190,7 @@ export const IndustryDescriptions: IIndustryMap<(corp: ICorporation) => React.Re Recommended starting Industry: NO ), - RealEstate: (corp: ICorporation) => ( + RealEstate: (corp: Corporation) => ( <> Develop and manage real estate properties.
    diff --git a/src/Corporation/OfficeSpace.ts b/src/Corporation/OfficeSpace.ts index 766e1b670..eba259395 100644 --- a/src/Corporation/OfficeSpace.ts +++ b/src/Corporation/OfficeSpace.ts @@ -4,8 +4,8 @@ import { getRandomInt } from "../utils/helpers/getRandomInt"; import { generateRandomString } from "../utils/StringHelperFunctions"; import { Generic_fromJSON, Generic_toJSON, IReviverValue, Reviver } from "../utils/JSONReviver"; import { Employee } from "./Employee"; -import { IIndustry } from "./IIndustry"; -import { ICorporation } from "./ICorporation"; +import { Industry } from "./Industry"; +import { Corporation } from "./Corporation"; interface IParams { loc?: string; @@ -68,7 +68,7 @@ export class OfficeSpace { return this.employees.length >= this.size; } - process(marketCycles = 1, corporation: ICorporation, industry: IIndustry): number { + process(marketCycles = 1, corporation: Corporation, industry: Industry): number { // HRBuddy AutoRecruitment and training if (industry.hasResearch("HRBuddy-Recruitment") && !this.atCapacity()) { const emp = this.hireRandomEmployee(); @@ -177,7 +177,7 @@ export class OfficeSpace { } } - calculateEmployeeProductivity(corporation: ICorporation, industry: IIndustry): void { + calculateEmployeeProductivity(corporation: Corporation, industry: Industry): void { //Reset for (const name of Object.keys(this.employeeProd)) { this.employeeProd[name] = 0; diff --git a/src/Corporation/Product.ts b/src/Corporation/Product.ts index 815c284c3..e85380372 100644 --- a/src/Corporation/Product.ts +++ b/src/Corporation/Product.ts @@ -1,6 +1,6 @@ import { EmployeePositions } from "./EmployeePositions"; import { MaterialSizes } from "./MaterialSizes"; -import { IIndustry } from "./IIndustry"; +import { Industry } from "./Industry"; import { ProductRatingWeights, IProductRatingWeight } from "./ProductRatingWeights"; import { createCityMap } from "../Locations/createCityMap"; @@ -157,7 +157,7 @@ export class Product { } // @param industry - Industry object. Reference to industry that makes this Product - finishProduct(industry: IIndustry): void { + finishProduct(industry: Industry): void { this.fin = true; // Calculate properties @@ -248,7 +248,7 @@ export class Product { } } - calculateRating(industry: IIndustry): void { + calculateRating(industry: Industry): void { const weights: IProductRatingWeight = ProductRatingWeights[industry.type]; if (weights == null) { console.error(`Could not find product rating weights for: ${industry}`); diff --git a/src/Corporation/Warehouse.ts b/src/Corporation/Warehouse.ts index 03cf81615..874651399 100644 --- a/src/Corporation/Warehouse.ts +++ b/src/Corporation/Warehouse.ts @@ -1,14 +1,14 @@ import { Material } from "./Material"; -import { ICorporation } from "./ICorporation"; -import { IIndustry } from "./IIndustry"; +import { Corporation } from "./Corporation"; +import { Industry } from "./Industry"; import { MaterialSizes } from "./MaterialSizes"; import { IMap } from "../types"; import { Generic_fromJSON, Generic_toJSON, IReviverValue, Reviver } from "../utils/JSONReviver"; import { exceptionAlert } from "../utils/helpers/exceptionAlert"; interface IConstructorParams { - corp?: ICorporation; - industry?: IIndustry; + corp?: Corporation; + industry?: Industry; loc?: string; size?: number; } @@ -96,7 +96,7 @@ export class Warehouse { } } - updateSize(corporation: ICorporation, industry: IIndustry): void { + updateSize(corporation: Corporation, industry: Industry): void { try { this.size = this.level * 100 * corporation.getStorageMultiplier() * industry.getStorageMultiplier(); } catch (e: unknown) { diff --git a/src/Corporation/ui/Context.ts b/src/Corporation/ui/Context.ts index 62e7f50a0..42bcfcf72 100644 --- a/src/Corporation/ui/Context.ts +++ b/src/Corporation/ui/Context.ts @@ -1,14 +1,14 @@ import React, { useContext } from "react"; -import { ICorporation } from "../ICorporation"; -import { IIndustry } from "../IIndustry"; +import { Corporation } from "../Corporation"; +import { Industry } from "../Industry"; export const Context: { - Corporation: React.Context; - Division: React.Context; + Corporation: React.Context; + Division: React.Context; } = { - Corporation: React.createContext({} as ICorporation), - Division: React.createContext({} as IIndustry), + Corporation: React.createContext({} as Corporation), + Division: React.createContext({} as Industry), }; -export const useCorporation = (): ICorporation => useContext(Context.Corporation); -export const useDivision = (): IIndustry => useContext(Context.Division); +export const useCorporation = (): Corporation => useContext(Context.Corporation); +export const useDivision = (): Industry => useContext(Context.Division); diff --git a/src/Corporation/ui/CorporationRoot.tsx b/src/Corporation/ui/CorporationRoot.tsx index ba24dbae8..3ca775af3 100644 --- a/src/Corporation/ui/CorporationRoot.tsx +++ b/src/Corporation/ui/CorporationRoot.tsx @@ -2,7 +2,7 @@ // These are the tabs at the top of the UI that let you switch to different // divisions, see an overview of your corporation, or create a new industry import React, { useState, useEffect } from "react"; -import { IIndustry } from "../IIndustry"; +import { Industry } from "../Industry"; import { MainPanel } from "./MainPanel"; import { Industries } from "../IndustryData"; import { ExpandIndustryTab } from "./ExpandIndustryTab"; @@ -32,7 +32,7 @@ export function CorporationRoot(): React.ReactElement { const canExpand = Object.keys(Industries).filter( (industryType: string) => - corporation.divisions.find((division: IIndustry) => division.type === industryType) === undefined, + corporation.divisions.find((division: Industry) => division.type === industryType) === undefined, ).length > 0; return ( diff --git a/src/Corporation/ui/ExpandIndustryTab.tsx b/src/Corporation/ui/ExpandIndustryTab.tsx index 74faabadf..8c4a36df5 100644 --- a/src/Corporation/ui/ExpandIndustryTab.tsx +++ b/src/Corporation/ui/ExpandIndustryTab.tsx @@ -2,7 +2,7 @@ import React, { useState } from "react"; import { dialogBoxCreate } from "../../ui/React/DialogBox"; import { IndustryStartingCosts, Industries, IndustryDescriptions } from "../IndustryData"; import { useCorporation } from "./Context"; -import { IIndustry } from "../IIndustry"; +import { Industry } from "../Industry"; import { NewIndustry } from "../Actions"; import Typography from "@mui/material/Typography"; @@ -23,7 +23,7 @@ export function ExpandIndustryTab(props: IProps): React.ReactElement { const possibleIndustries = allIndustries .filter( (industryType: string) => - corp.divisions.find((division: IIndustry) => division.type === industryType) === undefined, + corp.divisions.find((division: Industry) => division.type === industryType) === undefined, ) .sort(); const [industry, setIndustry] = useState(possibleIndustries.length > 0 ? possibleIndustries[0] : ""); diff --git a/src/Corporation/ui/Helpers.tsx b/src/Corporation/ui/Helpers.tsx index 30d116105..9f7b505d5 100644 --- a/src/Corporation/ui/Helpers.tsx +++ b/src/Corporation/ui/Helpers.tsx @@ -1,8 +1,8 @@ -import { IIndustry } from "../IIndustry"; +import { Industry } from "../Industry"; // Returns a boolean indicating whether the given material is relevant for the // current industry. -export function isRelevantMaterial(matName: string, division: IIndustry): boolean { +export function isRelevantMaterial(matName: string, division: Industry): boolean { // Materials that affect Production multiplier const prodMultiplierMats = ["Hardware", "Robots", "AICores", "RealEstate", "AI Cores", "Real Estate"]; diff --git a/src/Corporation/ui/IndustryProductEquation.tsx b/src/Corporation/ui/IndustryProductEquation.tsx index ce43b555e..c245b06b0 100644 --- a/src/Corporation/ui/IndustryProductEquation.tsx +++ b/src/Corporation/ui/IndustryProductEquation.tsx @@ -1,9 +1,9 @@ import React from "react"; -import { IIndustry } from "../IIndustry"; +import { Industry } from "../Industry"; import { MathJaxWrapper } from "../../MathJaxWrapper"; interface IProps { - division: IIndustry; + division: Industry; } export function IndustryProductEquation(props: IProps): React.ReactElement { diff --git a/src/Corporation/ui/IndustryWarehouse.tsx b/src/Corporation/ui/IndustryWarehouse.tsx index 0284e27ad..c60998cec 100644 --- a/src/Corporation/ui/IndustryWarehouse.tsx +++ b/src/Corporation/ui/IndustryWarehouse.tsx @@ -13,8 +13,8 @@ import { MaterialSizes } from "../MaterialSizes"; import { numeralWrapper } from "../../ui/numeralFormat"; -import { ICorporation } from "../ICorporation"; -import { IIndustry } from "../IIndustry"; +import { Corporation } from "../Corporation"; +import { Industry } from "../Industry"; import { MoneyCost } from "./MoneyCost"; import { isRelevantMaterial } from "./Helpers"; import { IndustryProductEquation } from "./IndustryProductEquation"; @@ -30,8 +30,8 @@ import makeStyles from "@mui/styles/makeStyles"; import createStyles from "@mui/styles/createStyles"; interface IProps { - corp: ICorporation; - division: IIndustry; + corp: Corporation; + division: Industry; warehouse: Warehouse | 0; currentCity: string; rerender: () => void; diff --git a/src/Corporation/ui/MainPanel.tsx b/src/Corporation/ui/MainPanel.tsx index 35a2833fd..ac865870d 100644 --- a/src/Corporation/ui/MainPanel.tsx +++ b/src/Corporation/ui/MainPanel.tsx @@ -4,7 +4,7 @@ import React from "react"; import { CityTabs } from "./CityTabs"; -import { IIndustry } from "../IIndustry"; +import { Industry } from "../Industry"; import { Context, useCorporation } from "./Context"; import { CityName } from "../../Locations/data/CityNames"; @@ -18,7 +18,7 @@ export function MainPanel(props: IProps): React.ReactElement { const corp = useCorporation(); const division = props.divisionName !== "Overview" - ? corp.divisions.find((division: IIndustry) => division.name === props.divisionName) + ? corp.divisions.find((division: Industry) => division.name === props.divisionName) : undefined; // use undefined because find returns undefined if (division === undefined) throw new Error("Cannot find division"); diff --git a/src/Corporation/ui/MoneyCost.tsx b/src/Corporation/ui/MoneyCost.tsx index 536ee2b95..8a2f17b6a 100644 --- a/src/Corporation/ui/MoneyCost.tsx +++ b/src/Corporation/ui/MoneyCost.tsx @@ -1,6 +1,6 @@ import * as React from "react"; import { numeralWrapper } from "../../ui/numeralFormat"; -import { ICorporation } from "../ICorporation"; +import { Corporation } from "../Corporation"; import { Theme } from "@mui/material/styles"; import makeStyles from "@mui/styles/makeStyles"; import createStyles from "@mui/styles/createStyles"; @@ -18,7 +18,7 @@ const useStyles = makeStyles((theme: Theme) => interface IProps { money: number; - corp: ICorporation; + corp: Corporation; } export function MoneyCost(props: IProps): React.ReactElement { diff --git a/src/Corporation/ui/modals/ExportModal.tsx b/src/Corporation/ui/modals/ExportModal.tsx index 947e932de..8161261ec 100644 --- a/src/Corporation/ui/modals/ExportModal.tsx +++ b/src/Corporation/ui/modals/ExportModal.tsx @@ -2,7 +2,7 @@ import React, { useState } from "react"; import { dialogBoxCreate } from "../../../ui/React/DialogBox"; import { Material } from "../../Material"; import { Export } from "../../Export"; -import { IIndustry } from "../../IIndustry"; +import { Industry } from "../../Industry"; import { ExportMaterial } from "../../Actions"; import { Modal } from "../../../ui/React/Modal"; import { useCorporation } from "../Context"; @@ -23,7 +23,7 @@ interface IProps { // Create a popup that lets the player manage exports export function ExportModal(props: IProps): React.ReactElement { const corp = useCorporation(); - const possibleDivisions = corp.divisions.filter((division: IIndustry) => + const possibleDivisions = corp.divisions.filter((division: Industry) => isRelevantMaterial(props.mat.name, division), ); if (possibleDivisions.length === 0) throw new Error("Export popup created with no divisions."); @@ -72,7 +72,7 @@ export function ExportModal(props: IProps): React.ReactElement { rerender(); } - const currentDivision = corp.divisions.find((division: IIndustry) => division.name === industry); + const currentDivision = corp.divisions.find((division: Industry) => division.name === industry); if (currentDivision === undefined) throw new Error(`Export popup somehow ended up with undefined division '${currentDivision}'`); const possibleCities = Object.keys(currentDivision.warehouses).filter( @@ -90,8 +90,8 @@ export function ExportModal(props: IProps): React.ReactElement {