mirror of
https://github.com/bitburner-official/bitburner-src.git
synced 2024-12-23 22:52:29 +01:00
Merge branch 'dev' into corp-remove-async
This commit is contained in:
commit
75a9151e74
64
dist/bitburner.d.ts
vendored
64
dist/bitburner.d.ts
vendored
@ -313,7 +313,7 @@ export declare interface Bladeburner {
|
||||
* @remarks
|
||||
* RAM cost: 4 GB
|
||||
*
|
||||
* Returns the number of seconds it takes to complete the specified action
|
||||
* Returns the number of milliseconds it takes to complete the specified action
|
||||
*
|
||||
* @param type - Type of action.
|
||||
* @param name - Name of action. Must be an exact match.
|
||||
@ -321,6 +321,17 @@ export declare interface Bladeburner {
|
||||
*/
|
||||
getActionTime(type: string, name: string): number;
|
||||
|
||||
/**
|
||||
* Get the time elapsed on current action.
|
||||
* @remarks
|
||||
* RAM cost: 4 GB
|
||||
*
|
||||
* Returns the number of milliseconds already spent on the current action.
|
||||
*
|
||||
* @returns Number of milliseconds already spent on the current action.
|
||||
*/
|
||||
getActionCurrentTime(): number;
|
||||
|
||||
/**
|
||||
* Get estimate success chance of an action.
|
||||
* @remarks
|
||||
@ -496,28 +507,30 @@ export declare interface Bladeburner {
|
||||
* @remarks
|
||||
* RAM cost: 4 GB
|
||||
*
|
||||
* This function returns the number of skill points needed to upgrade the specified skill.
|
||||
* This function returns the number of skill points needed to upgrade the specified skill the specified number of times.
|
||||
*
|
||||
* The function returns -1 if an invalid skill name is passed in.
|
||||
*
|
||||
* @param skillName - Name of skill. Case-sensitive and must be an exact match
|
||||
* @param count - Number of times to upgrade the skill. Defaults to 1 if not specified.
|
||||
* @returns Number of skill points needed to upgrade the specified skill.
|
||||
*/
|
||||
getSkillUpgradeCost(name: string): number;
|
||||
getSkillUpgradeCost(name: string, count?: number): number;
|
||||
|
||||
/**
|
||||
* Upgrade skill.
|
||||
* @remarks
|
||||
* RAM cost: 4 GB
|
||||
*
|
||||
* Attempts to upgrade the specified Bladeburner skill.
|
||||
* Attempts to upgrade the specified Bladeburner skill the specified number of times.
|
||||
*
|
||||
* Returns true if the skill is successfully upgraded, and false otherwise.
|
||||
*
|
||||
* @param skillName - Name of skill to be upgraded. Case-sensitive and must be an exact match
|
||||
* @param count - Number of times to upgrade the skill. Defaults to 1 if not specified.
|
||||
* @returns true if the skill is successfully upgraded, and false otherwise.
|
||||
*/
|
||||
upgradeSkill(name: string): boolean;
|
||||
upgradeSkill(name: string, count?: number): boolean;
|
||||
|
||||
/**
|
||||
* Get team size.
|
||||
@ -673,7 +686,7 @@ export declare interface Bladeburner {
|
||||
* @remarks
|
||||
* RAM cost: 0 GB
|
||||
*
|
||||
* Returns the amount of accumulated “bonus time” (seconds) for the Bladeburner mechanic.
|
||||
* Returns the amount of accumulated “bonus time” (milliseconds) for the Bladeburner mechanic.
|
||||
*
|
||||
* “Bonus time” is accumulated when the game is offline or if the game is inactive in the browser.
|
||||
*
|
||||
@ -1483,7 +1496,7 @@ export declare interface Gang {
|
||||
* @remarks
|
||||
* RAM cost: 0 GB
|
||||
*
|
||||
* Returns the amount of accumulated “bonus time” (seconds) for the Gang mechanic.
|
||||
* Returns the amount of accumulated “bonus time” (milliseconds) for the Gang mechanic.
|
||||
*
|
||||
* “Bonus time” is accumulated when the game is offline or if the game is inactive in the browser.
|
||||
*
|
||||
@ -3059,6 +3072,7 @@ export declare interface NS {
|
||||
* @remarks
|
||||
* RAM cost: 0 GB
|
||||
*
|
||||
* see: https://github.com/alexei/sprintf.js
|
||||
* @param format - format of the message
|
||||
* @param msg - Value to be printed.
|
||||
*/
|
||||
@ -3150,7 +3164,7 @@ export declare interface NS {
|
||||
* @param args - Arguments to identify which scripts to get logs for.
|
||||
* @returns Returns an string array, where each line is an element in the array. The most recently logged line is at the end of the array.
|
||||
*/
|
||||
getScriptLogs(fn?: string, host?: string, ...args: any[]): string[];
|
||||
getScriptLogs(fn?: string, host?: string, ...args: (string | number | boolean)[]): string[];
|
||||
|
||||
/**
|
||||
* Get an array of recently killed scripts across all servers.
|
||||
@ -3213,7 +3227,7 @@ export declare interface NS {
|
||||
* @param host - Optional. Hostname of the script being tailed. Defaults to the server this script is running on. If args are specified, this is not optional.
|
||||
* @param args - Arguments for the script being tailed.
|
||||
*/
|
||||
tail(fn?: FilenameOrPID, host?: string, ...args: any[]): void;
|
||||
tail(fn?: FilenameOrPID, host?: string, ...args: (string | number | boolean)[]): void;
|
||||
|
||||
/**
|
||||
* Close the tail window of a script.
|
||||
@ -3418,7 +3432,7 @@ export declare interface NS {
|
||||
* @param args - Additional arguments to pass into the new script that is being run. Note that if any arguments are being passed into the new script, then the second argument numThreads must be filled in with a value.
|
||||
* @returns Returns the PID of a successfully started script, and 0 otherwise.
|
||||
*/
|
||||
run(script: string, numThreads?: number, ...args: Array<string | number | boolean>): number;
|
||||
run(script: string, numThreads?: number, ...args: (string | number | boolean)[]): number;
|
||||
|
||||
/**
|
||||
* Start another script on any server.
|
||||
@ -3466,7 +3480,7 @@ export declare interface NS {
|
||||
* @param args - Additional arguments to pass into the new script that is being run. Note that if any arguments are being passed into the new script, then the third argument numThreads must be filled in with a value.
|
||||
* @returns Returns the PID of a successfully started script, and 0 otherwise.
|
||||
*/
|
||||
exec(script: string, host: string, numThreads?: number, ...args: Array<string | number | boolean>): number;
|
||||
exec(script: string, host: string, numThreads?: number, ...args: (string | number | boolean)[]): number;
|
||||
|
||||
/**
|
||||
* Terminate current script and start another in 10s.
|
||||
@ -3496,7 +3510,7 @@ export declare interface NS {
|
||||
* @param numThreads - Number of threads to spawn new script with. Will be rounded to nearest integer.
|
||||
* @param args - Additional arguments to pass into the new script that is being run.
|
||||
*/
|
||||
spawn(script: string, numThreads?: number, ...args: string[]): void;
|
||||
spawn(script: string, numThreads?: number, ...args: (string | number | boolean)[]): void;
|
||||
|
||||
/**
|
||||
* Terminate another script.
|
||||
@ -3566,7 +3580,7 @@ export declare interface NS {
|
||||
* ns.kill("foo.script", getHostname(), 1, "foodnstuff");
|
||||
* ```
|
||||
*/
|
||||
kill(script: string, host: string, ...args: string[]): boolean;
|
||||
kill(script: string, host: string, ...args: (string | number | boolean)[]): boolean;
|
||||
|
||||
/**
|
||||
* Terminate all scripts on a server.
|
||||
@ -4063,7 +4077,7 @@ export declare interface NS {
|
||||
* @param args - Arguments to specify/identify which scripts to search for.
|
||||
* @returns True if specified script is running on the target server, and false otherwise.
|
||||
*/
|
||||
isRunning(script: FilenameOrPID, host: string, ...args: string[]): boolean;
|
||||
isRunning(script: FilenameOrPID, host?: string, ...args: (string | number | boolean)[]): boolean;
|
||||
|
||||
/**
|
||||
* Get general info about a running script.
|
||||
@ -4078,7 +4092,11 @@ export declare interface NS {
|
||||
* @param args - Arguments to identify the script
|
||||
* @returns The info about the running script if found, and null otherwise.
|
||||
*/
|
||||
getRunningScript(filename?: FilenameOrPID, hostname?: string, ...args: (string | number)[]): RunningScript | null;
|
||||
getRunningScript(
|
||||
filename?: FilenameOrPID,
|
||||
hostname?: string,
|
||||
...args: (string | number | boolean)[]
|
||||
): RunningScript | null;
|
||||
|
||||
/**
|
||||
* Get cost of purchasing a server.
|
||||
@ -4404,13 +4422,13 @@ export declare interface NS {
|
||||
* Get the execution time of a hack() call.
|
||||
* @remarks
|
||||
* RAM cost: 0.05 GB
|
||||
*
|
||||
* When `hack` completes an amount of money is stolen depending on the player's skills.
|
||||
* Returns the amount of time in milliseconds it takes to execute the hack Netscript function on the target server.
|
||||
* The function takes in an optional hackLvl parameter that can be specified to see what the hack time would be at different hacking levels.
|
||||
* The required time is increased by the security level of the target server and decreased by the player's hacking level.
|
||||
*
|
||||
* @param host - Host of target server.
|
||||
* @returns Returns the amount of time in milliseconds it takes to execute the hack Netscript function. Returns Infinity if called on a Hacknet Server.
|
||||
* @returns Returns the amount of time in milliseconds it takes to execute the hack Netscript function.
|
||||
*/
|
||||
getHackTime(host: string): number;
|
||||
|
||||
@ -4420,11 +4438,10 @@ export declare interface NS {
|
||||
* RAM cost: 0.05 GB
|
||||
*
|
||||
* Returns the amount of time in milliseconds it takes to execute the grow Netscript function on the target server.
|
||||
* The function takes in an optional hackLvl parameter that can be specified to see what the grow time would be at different hacking levels.
|
||||
* The required time is increased by the security level of the target server and decreased by the player's hacking level.
|
||||
*
|
||||
* @param host - Host of target server.
|
||||
* @returns Returns the amount of time in milliseconds it takes to execute the grow Netscript function. Returns Infinity if called on a Hacknet Server.
|
||||
* @returns Returns the amount of time in milliseconds it takes to execute the grow Netscript function.
|
||||
*/
|
||||
getGrowTime(host: string): number;
|
||||
|
||||
@ -4434,11 +4451,10 @@ export declare interface NS {
|
||||
* RAM cost: 0.05 GB
|
||||
*
|
||||
* Returns the amount of time in milliseconds it takes to execute the weaken Netscript function on the target server.
|
||||
* The function takes in an optional hackLvl parameter that can be specified to see what the weaken time would be at different hacking levels.
|
||||
* The required time is increased by the security level of the target server and decreased by the player's hacking level.
|
||||
*
|
||||
* @param host - Host of target server.
|
||||
* @returns Returns the amount of time in milliseconds it takes to execute the weaken Netscript function. Returns Infinity if called on a Hacknet Server.
|
||||
* @returns Returns the amount of time in milliseconds it takes to execute the weaken Netscript function.
|
||||
*/
|
||||
getWeakenTime(host: string): number;
|
||||
|
||||
@ -4471,7 +4487,7 @@ export declare interface NS {
|
||||
/**
|
||||
* {@inheritDoc NS.(getScriptIncome:1)}
|
||||
*/
|
||||
getScriptIncome(script: string, host: string, ...args: string[]): number;
|
||||
getScriptIncome(script: string, host: string, ...args: (string | number | boolean)[]): number;
|
||||
|
||||
/**
|
||||
* Get the exp gain of a script.
|
||||
@ -4495,7 +4511,7 @@ export declare interface NS {
|
||||
/**
|
||||
* {@inheritDoc NS.(getScriptExpGain:1)}
|
||||
*/
|
||||
getScriptExpGain(script: string, host: string, ...args: string[]): number;
|
||||
getScriptExpGain(script: string, host: string, ...args: (string | number | boolean)[]): number;
|
||||
|
||||
/**
|
||||
* Returns the amount of time in milliseconds that have passed since you last installed Augmentations.
|
||||
@ -6439,6 +6455,8 @@ export declare interface SleeveTask {
|
||||
gymStatType: string;
|
||||
/** Faction work type being performed, if any */
|
||||
factionWorkType: string;
|
||||
/** Class being taken at university, if any */
|
||||
className: string;
|
||||
}
|
||||
|
||||
/**
|
||||
|
4
dist/main.bundle.js
vendored
4
dist/main.bundle.js
vendored
File diff suppressed because one or more lines are too long
2
dist/main.bundle.js.map
vendored
2
dist/main.bundle.js.map
vendored
File diff suppressed because one or more lines are too long
42
dist/vendor.bundle.js
vendored
42
dist/vendor.bundle.js
vendored
File diff suppressed because one or more lines are too long
2
dist/vendor.bundle.js.map
vendored
2
dist/vendor.bundle.js.map
vendored
File diff suppressed because one or more lines are too long
@ -35,6 +35,8 @@ Furthermore, some BitNodes introduce new content and mechanics. For example ther
|
||||
BitNode that grants access to the `Singularity API <https://github.com/danielyxie/bitburner/blob/dev/markdown/bitburner.singularity.md>`_.
|
||||
There is another BitNode in which you can manage a gang to earn money and reputation.
|
||||
|
||||
.. _gameplay_bitnodes_howtodestroy:
|
||||
|
||||
How to destroy a BitNode
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
Initially, the only way to destroy a BitNode is to join the Daedalus :ref:`Daedalus <gameplay_factions>`.
|
||||
|
@ -39,7 +39,7 @@ There are two methods of obtaining Duplicate Sleeves:
|
||||
|
||||
1. Destroy BitNode-10. Each completion give you one additional Duplicate Sleeve
|
||||
2. Purchase Duplicate Sleeves from :ref:`the faction The Covenant <gameplay_factions>`.
|
||||
This is only available in BitNodes-10. Sleeves purchased this way are **permanent** (they persist
|
||||
This is only available in BitNode-10. Sleeves purchased this way are **permanent** (they persist
|
||||
through BitNodes). You can purchase up to 5 Duplicate Sleeves from The Covenant.
|
||||
|
||||
Synchronization
|
||||
@ -86,8 +86,7 @@ switching BitNodes. For example, if a sleeve has a memory of 10, then when you
|
||||
switch BitNodes its synchronization will initially be set to 10, rather than 1.
|
||||
|
||||
Memory can only be increased by purchasing upgrades from The Covenant. Just like
|
||||
the ability to purchase additional sleeves, this is only available in BitNodes-10
|
||||
and above, and is only available after defeating BitNode-10 at least once.
|
||||
the ability to purchase additional sleeves, this is only available in BitNode-10.
|
||||
|
||||
Memory is a persistent stat, meaning it never gets reset back to 1.
|
||||
The maximum possible value for a sleeve's memory is 100.
|
||||
|
@ -5,7 +5,7 @@
|
||||
Source-Files
|
||||
============
|
||||
Source-Files are a type of persistent upgrade that is more powerful than Augmentations.
|
||||
Source-Files are received by destroying a BitNode. There are many different BitNodes
|
||||
Source-Files are received by :ref:`destroying a BitNode <gameplay_bitnodes_howtodestroy>`. There are many different BitNodes
|
||||
in the game and each BitNode will grant a different Source-File when it is destroyed.
|
||||
|
||||
A Source-File can be upgraded by destroying its corresponding BitNode a second or
|
||||
@ -64,3 +64,7 @@ List of all Source-Files
|
||||
|| || * Let the player start with Neuroflux Governor equal to the level of this |
|
||||
|| || Source-File. |
|
||||
+-------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
|| BitNode-13: They're lunatics || * This Source-File lets the Church of the Machine God appear in other BitNodes. |
|
||||
|| || * Each level of this Source-File increases the size of Stanek's Gift. |
|
||||
|| || |
|
||||
+-------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
|
@ -56,7 +56,7 @@ Here is everything you will KEEP when you install an Augmentation:
|
||||
|
||||
* Every Augmentation you have installed
|
||||
* Scripts on your home computer
|
||||
* RAM Upgrades on your home computer
|
||||
* RAM/Core Upgrades on your home computer
|
||||
* World Stock Exchange account and TIX API Access
|
||||
|
||||
.. _gameplay_augmentations_purchasingmultiple:
|
||||
|
@ -26,4 +26,16 @@ Harder crimes are typically more profitable, and also give more EXP.
|
||||
|
||||
Crime details
|
||||
^^^^^^^^^^^^^
|
||||
TODO
|
||||
Available crimes, and their descriptions, which all begin with "attempt to..."
|
||||
Shoplift …shoplift from a low-end retailer
|
||||
Rob store …commit armed robbery on a high-end store
|
||||
Mug someone …mug a random person on the street
|
||||
Larceny …rob property from someone's house
|
||||
Deal Drugs …deal drugs
|
||||
Bond Forgery …forge corporate bonds
|
||||
Traffick illegal Arms …smuggle illegal arms into the city
|
||||
Homicide …murder a random person on the street
|
||||
Grand theft Auto …commit grand theft auto
|
||||
Kidnap and Ransom …kidnap and ransom a high-profile-target
|
||||
Assassinate …assassinate a high-profile target
|
||||
Heist …pull off the ultimate heist
|
||||
|
@ -2,6 +2,9 @@
|
||||
|
||||
Factions
|
||||
========
|
||||
|
||||
.. warning:: This page contains spoilers regarding the game's story/plot-line.
|
||||
|
||||
Throughout the game you may receive invitations from factions. There are
|
||||
many different factions, and each faction has different criteria for
|
||||
determining its potential members. Joining a faction and furthering
|
||||
|
@ -8,15 +8,6 @@ on the navigation menu on the left-hand side of the game (you may need to expand
|
||||
the 'Hacking' header in order to see the 'Terminal' tab). Alternatively, the :ref:`keyboard
|
||||
shortcut <shortcuts>` Alt + t can be used to open the Terminal.
|
||||
|
||||
Configuration
|
||||
-------------
|
||||
|
||||
The terminal has a configuration file called .fconf. To edit this file, go to
|
||||
the terminal and enter::
|
||||
|
||||
nano .fconf
|
||||
|
||||
|
||||
.. _terminal_filesystem:
|
||||
|
||||
Filesystem (Directories)
|
||||
|
@ -62,7 +62,7 @@ To briefly summarize the information from the links above: Each server has a
|
||||
security level that affects how difficult it is to hack. Each server also has a
|
||||
certain amount of money, as well as a maximum amount of money it can hold. Hacking a
|
||||
server steals a percentage of that server's money. The :js:func:`hack` Netscript function
|
||||
is used to hack server. The :js:func:`grow` Netscript function is used to increase
|
||||
is used to hack a server. The :js:func:`grow` Netscript function is used to increase
|
||||
the amount of money available on a server. The :js:func:`weaken` Netscript function is
|
||||
used to decrease a server's security level.
|
||||
|
||||
|
@ -21,7 +21,7 @@ To automatically enter commands in the terminal (only works if looking at the te
|
||||
terminalInput[handler].onChange({target:terminalInput});
|
||||
|
||||
// Simulate an enter press
|
||||
terminalInput[handler].onKeyDown({keyCode:13,preventDefault:()=>null});
|
||||
terminalInput[handler].onKeyDown({key:'Enter',preventDefault:()=>null});
|
||||
|
||||
|
||||
To add lines to the terminal (only works if looking at the terminal):
|
||||
|
@ -15,4 +15,4 @@ scriptKill() Netscript Function
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
scriptKill("demo.script"); // returns: true
|
||||
scriptKill("demo.script", "home"); // returns: true
|
||||
|
@ -23,4 +23,4 @@ spawn() Netscript Function
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
spawn('foo.script', 10, 'foodnstuff', 90); // "run foo.script 10 foodnstuff 90" in 10 seconds.
|
||||
spawn('foo.script', 10, 'foodnstuff', 90); // "run foo.script foodnstuff 90 -t 10" in 10 seconds.
|
||||
|
@ -23,3 +23,14 @@ into a script using::
|
||||
args.length
|
||||
|
||||
**WARNING: Do not try to modify the args array. This will break the game.**
|
||||
|
||||
|
||||
example for accessing arguments in ns2 from terminal execution:
|
||||
terminal command:
|
||||
run name_of_script.js -t 10 --tail argument1 argument2
|
||||
|
||||
ns2 script:
|
||||
|
||||
const args_obj = arguments[0]
|
||||
const argument1 = (args_obj.server.args[0])
|
||||
const argument2 = (args_obj.server.args[1])
|
||||
|
25
markdown/bitburner.bladeburner.getactioncurrenttime.md
Normal file
25
markdown/bitburner.bladeburner.getactioncurrenttime.md
Normal file
@ -0,0 +1,25 @@
|
||||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [bitburner](./bitburner.md) > [Bladeburner](./bitburner.bladeburner.md) > [getActionCurrentTime](./bitburner.bladeburner.getactioncurrenttime.md)
|
||||
|
||||
## Bladeburner.getActionCurrentTime() method
|
||||
|
||||
Get the time elapsed on current action.
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
getActionCurrentTime(): number;
|
||||
```
|
||||
<b>Returns:</b>
|
||||
|
||||
number
|
||||
|
||||
Number of milliseconds already spent on the current action.
|
||||
|
||||
## Remarks
|
||||
|
||||
RAM cost: 4 GB
|
||||
|
||||
Returns the number of milliseconds already spent on the current action.
|
||||
|
@ -29,5 +29,5 @@ Number of milliseconds it takes to complete the specified action.
|
||||
|
||||
RAM cost: 4 GB
|
||||
|
||||
Returns the number of seconds it takes to complete the specified action
|
||||
Returns the number of milliseconds it takes to complete the specified action
|
||||
|
||||
|
@ -21,7 +21,7 @@ Amount of accumulated “bonus time” (milliseconds) for the Bladeburner mechan
|
||||
|
||||
RAM cost: 0 GB
|
||||
|
||||
Returns the amount of accumulated “bonus time” (seconds) for the Bladeburner mechanic.
|
||||
Returns the amount of accumulated “bonus time” (milliseconds) for the Bladeburner mechanic.
|
||||
|
||||
“Bonus time” is accumulated when the game is offline or if the game is inactive in the browser.
|
||||
|
||||
|
@ -9,7 +9,7 @@ Get cost to upgrade skill.
|
||||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
getSkillUpgradeCost(name: string): number;
|
||||
getSkillUpgradeCost(name: string, count?: number): number;
|
||||
```
|
||||
|
||||
## Parameters
|
||||
@ -17,6 +17,7 @@ getSkillUpgradeCost(name: string): number;
|
||||
| Parameter | Type | Description |
|
||||
| --- | --- | --- |
|
||||
| name | string | |
|
||||
| count | number | Number of times to upgrade the skill. Defaults to 1 if not specified. |
|
||||
|
||||
<b>Returns:</b>
|
||||
|
||||
@ -28,7 +29,7 @@ Number of skill points needed to upgrade the specified skill.
|
||||
|
||||
RAM cost: 4 GB
|
||||
|
||||
This function returns the number of skill points needed to upgrade the specified skill.
|
||||
This function returns the number of skill points needed to upgrade the specified skill the specified number of times.
|
||||
|
||||
The function returns -1 if an invalid skill name is passed in.
|
||||
|
||||
|
@ -23,6 +23,7 @@ You have to be employed in the Bladeburner division and be in BitNode-7 or have
|
||||
| [getActionAutolevel(type, name)](./bitburner.bladeburner.getactionautolevel.md) | Get whether an action is set to autolevel. |
|
||||
| [getActionCountRemaining(type, name)](./bitburner.bladeburner.getactioncountremaining.md) | Get action count remaining. |
|
||||
| [getActionCurrentLevel(type, name)](./bitburner.bladeburner.getactioncurrentlevel.md) | Get the current level of an action. |
|
||||
| [getActionCurrentTime()](./bitburner.bladeburner.getactioncurrenttime.md) | Get the time elapsed on current action. |
|
||||
| [getActionEstimatedSuccessChance(type, name)](./bitburner.bladeburner.getactionestimatedsuccesschance.md) | Get estimate success chance of an action. |
|
||||
| [getActionMaxLevel(type, name)](./bitburner.bladeburner.getactionmaxlevel.md) | Get the maximum level of an action. |
|
||||
| [getActionRepGain(type, name, level)](./bitburner.bladeburner.getactionrepgain.md) | Get the reputation gain of an action. |
|
||||
@ -42,7 +43,7 @@ You have to be employed in the Bladeburner division and be in BitNode-7 or have
|
||||
| [getSkillLevel(name)](./bitburner.bladeburner.getskilllevel.md) | Get skill level. |
|
||||
| [getSkillNames()](./bitburner.bladeburner.getskillnames.md) | List all skills. |
|
||||
| [getSkillPoints()](./bitburner.bladeburner.getskillpoints.md) | Get bladeburner skill points. |
|
||||
| [getSkillUpgradeCost(name)](./bitburner.bladeburner.getskillupgradecost.md) | Get cost to upgrade skill. |
|
||||
| [getSkillUpgradeCost(name, count)](./bitburner.bladeburner.getskillupgradecost.md) | Get cost to upgrade skill. |
|
||||
| [getStamina()](./bitburner.bladeburner.getstamina.md) | Get bladeburner stamina. |
|
||||
| [getTeamSize(type, name)](./bitburner.bladeburner.getteamsize.md) | Get team size. |
|
||||
| [joinBladeburnerDivision()](./bitburner.bladeburner.joinbladeburnerdivision.md) | Join the bladeburner division. |
|
||||
@ -53,5 +54,5 @@ You have to be employed in the Bladeburner division and be in BitNode-7 or have
|
||||
| [startAction(type, name)](./bitburner.bladeburner.startaction.md) | Start an action. |
|
||||
| [stopBladeburnerAction()](./bitburner.bladeburner.stopbladeburneraction.md) | Stop current action. |
|
||||
| [switchCity(name)](./bitburner.bladeburner.switchcity.md) | Travel to another city in bladeburner. |
|
||||
| [upgradeSkill(name)](./bitburner.bladeburner.upgradeskill.md) | Upgrade skill. |
|
||||
| [upgradeSkill(name, count)](./bitburner.bladeburner.upgradeskill.md) | Upgrade skill. |
|
||||
|
||||
|
@ -9,7 +9,7 @@ Upgrade skill.
|
||||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
upgradeSkill(name: string): boolean;
|
||||
upgradeSkill(name: string, count?: number): boolean;
|
||||
```
|
||||
|
||||
## Parameters
|
||||
@ -17,6 +17,7 @@ upgradeSkill(name: string): boolean;
|
||||
| Parameter | Type | Description |
|
||||
| --- | --- | --- |
|
||||
| name | string | |
|
||||
| count | number | Number of times to upgrade the skill. Defaults to 1 if not specified. |
|
||||
|
||||
<b>Returns:</b>
|
||||
|
||||
@ -28,7 +29,7 @@ true if the skill is successfully upgraded, and false otherwise.
|
||||
|
||||
RAM cost: 4 GB
|
||||
|
||||
Attempts to upgrade the specified Bladeburner skill.
|
||||
Attempts to upgrade the specified Bladeburner skill the specified number of times.
|
||||
|
||||
Returns true if the skill is successfully upgraded, and false otherwise.
|
||||
|
||||
|
@ -21,7 +21,7 @@ Bonus time for the Gang mechanic in milliseconds.
|
||||
|
||||
RAM cost: 0 GB
|
||||
|
||||
Returns the amount of accumulated “bonus time” (seconds) for the Gang mechanic.
|
||||
Returns the amount of accumulated “bonus time” (milliseconds) for the Gang mechanic.
|
||||
|
||||
“Bonus time” is accumulated when the game is offline or if the game is inactive in the browser.
|
||||
|
||||
|
@ -9,7 +9,7 @@ Start another script on any server.
|
||||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
exec(script: string, host: string, numThreads?: number, ...args: Array<string | number | boolean>): number;
|
||||
exec(script: string, host: string, numThreads?: number, ...args: (string | number | boolean)[]): number;
|
||||
```
|
||||
|
||||
## Parameters
|
||||
@ -19,7 +19,7 @@ exec(script: string, host: string, numThreads?: number, ...args: Array<string |
|
||||
| script | string | Filename of script to execute. |
|
||||
| host | string | Hostname of the <code>target server</code> on which to execute the script. |
|
||||
| numThreads | number | Optional thread count for new script. Set to 1 by default. Will be rounded to nearest integer. |
|
||||
| args | Array<string \| number \| boolean> | Additional arguments to pass into the new script that is being run. Note that if any arguments are being passed into the new script, then the third argument numThreads must be filled in with a value. |
|
||||
| args | (string \| number \| boolean)\[\] | Additional arguments to pass into the new script that is being run. Note that if any arguments are being passed into the new script, then the third argument numThreads must be filled in with a value. |
|
||||
|
||||
<b>Returns:</b>
|
||||
|
||||
|
@ -22,11 +22,11 @@ getGrowTime(host: string): number;
|
||||
|
||||
number
|
||||
|
||||
Returns the amount of time in milliseconds it takes to execute the grow Netscript function. Returns Infinity if called on a Hacknet Server.
|
||||
Returns the amount of time in milliseconds it takes to execute the grow Netscript function.
|
||||
|
||||
## Remarks
|
||||
|
||||
RAM cost: 0.05 GB
|
||||
|
||||
Returns the amount of time in milliseconds it takes to execute the grow Netscript function on the target server. The function takes in an optional hackLvl parameter that can be specified to see what the grow time would be at different hacking levels. The required time is increased by the security level of the target server and decreased by the player's hacking level.
|
||||
Returns the amount of time in milliseconds it takes to execute the grow Netscript function on the target server. The required time is increased by the security level of the target server and decreased by the player's hacking level.
|
||||
|
||||
|
@ -22,9 +22,11 @@ getHackTime(host: string): number;
|
||||
|
||||
number
|
||||
|
||||
Returns the amount of time in milliseconds it takes to execute the hack Netscript function. Returns Infinity if called on a Hacknet Server.
|
||||
Returns the amount of time in milliseconds it takes to execute the hack Netscript function.
|
||||
|
||||
## Remarks
|
||||
|
||||
RAM cost: 0.05 GB When `hack` completes an amount of money is stolen depending on the player's skills. Returns the amount of time in milliseconds it takes to execute the hack Netscript function on the target server. The function takes in an optional hackLvl parameter that can be specified to see what the hack time would be at different hacking levels. The required time is increased by the security level of the target server and decreased by the player's hacking level.
|
||||
RAM cost: 0.05 GB
|
||||
|
||||
When `hack` completes an amount of money is stolen depending on the player's skills. Returns the amount of time in milliseconds it takes to execute the hack Netscript function on the target server. The required time is increased by the security level of the target server and decreased by the player's hacking level.
|
||||
|
||||
|
@ -9,7 +9,11 @@ Get general info about a running script.
|
||||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
getRunningScript(filename?: FilenameOrPID, hostname?: string, ...args: (string | number)[]): RunningScript | null;
|
||||
getRunningScript(
|
||||
filename?: FilenameOrPID,
|
||||
hostname?: string,
|
||||
...args: (string | number | boolean)[]
|
||||
): RunningScript | null;
|
||||
```
|
||||
|
||||
## Parameters
|
||||
@ -18,7 +22,7 @@ getRunningScript(filename?: FilenameOrPID, hostname?: string, ...args: (string |
|
||||
| --- | --- | --- |
|
||||
| filename | [FilenameOrPID](./bitburner.filenameorpid.md) | Optional. Filename or PID of the script. |
|
||||
| hostname | string | Optional. Name of host server the script is running on. |
|
||||
| args | (string \| number)\[\] | Arguments to identify the script |
|
||||
| args | (string \| number \| boolean)\[\] | Arguments to identify the script |
|
||||
|
||||
<b>Returns:</b>
|
||||
|
||||
|
@ -9,7 +9,7 @@ Get the exp gain of a script.
|
||||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
getScriptExpGain(script: string, host: string, ...args: string[]): number;
|
||||
getScriptExpGain(script: string, host: string, ...args: (string | number | boolean)[]): number;
|
||||
```
|
||||
|
||||
## Parameters
|
||||
@ -18,7 +18,7 @@ getScriptExpGain(script: string, host: string, ...args: string[]): number;
|
||||
| --- | --- | --- |
|
||||
| script | string | Filename of script. |
|
||||
| host | string | Server on which script is running. |
|
||||
| args | string\[\] | Arguments that the script is running with. |
|
||||
| args | (string \| number \| boolean)\[\] | Arguments that the script is running with. |
|
||||
|
||||
<b>Returns:</b>
|
||||
|
||||
|
@ -9,7 +9,7 @@ Get the income of a script.
|
||||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
getScriptIncome(script: string, host: string, ...args: string[]): number;
|
||||
getScriptIncome(script: string, host: string, ...args: (string | number | boolean)[]): number;
|
||||
```
|
||||
|
||||
## Parameters
|
||||
@ -18,7 +18,7 @@ getScriptIncome(script: string, host: string, ...args: string[]): number;
|
||||
| --- | --- | --- |
|
||||
| script | string | Filename of script. |
|
||||
| host | string | Server on which script is running. |
|
||||
| args | string\[\] | Arguments that the script is running with. |
|
||||
| args | (string \| number \| boolean)\[\] | Arguments that the script is running with. |
|
||||
|
||||
<b>Returns:</b>
|
||||
|
||||
|
@ -9,7 +9,7 @@ Get all the logs of a script.
|
||||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
getScriptLogs(fn?: string, host?: string, ...args: any[]): string[];
|
||||
getScriptLogs(fn?: string, host?: string, ...args: (string | number | boolean)[]): string[];
|
||||
```
|
||||
|
||||
## Parameters
|
||||
@ -18,7 +18,7 @@ getScriptLogs(fn?: string, host?: string, ...args: any[]): string[];
|
||||
| --- | --- | --- |
|
||||
| fn | string | Optional. Filename of script to get logs from. |
|
||||
| host | string | Optional. Hostname of the server that the script is on. |
|
||||
| args | any\[\] | Arguments to identify which scripts to get logs for. |
|
||||
| args | (string \| number \| boolean)\[\] | Arguments to identify which scripts to get logs for. |
|
||||
|
||||
<b>Returns:</b>
|
||||
|
||||
|
@ -22,11 +22,11 @@ getWeakenTime(host: string): number;
|
||||
|
||||
number
|
||||
|
||||
Returns the amount of time in milliseconds it takes to execute the weaken Netscript function. Returns Infinity if called on a Hacknet Server.
|
||||
Returns the amount of time in milliseconds it takes to execute the weaken Netscript function.
|
||||
|
||||
## Remarks
|
||||
|
||||
RAM cost: 0.05 GB
|
||||
|
||||
Returns the amount of time in milliseconds it takes to execute the weaken Netscript function on the target server. The function takes in an optional hackLvl parameter that can be specified to see what the weaken time would be at different hacking levels. The required time is increased by the security level of the target server and decreased by the player's hacking level.
|
||||
Returns the amount of time in milliseconds it takes to execute the weaken Netscript function on the target server. The required time is increased by the security level of the target server and decreased by the player's hacking level.
|
||||
|
||||
|
@ -9,7 +9,7 @@ Check if a script is running.
|
||||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
isRunning(script: FilenameOrPID, host: string, ...args: string[]): boolean;
|
||||
isRunning(script: FilenameOrPID, host?: string, ...args: (string | number | boolean)[]): boolean;
|
||||
```
|
||||
|
||||
## Parameters
|
||||
@ -18,7 +18,7 @@ isRunning(script: FilenameOrPID, host: string, ...args: string[]): boolean;
|
||||
| --- | --- | --- |
|
||||
| script | [FilenameOrPID](./bitburner.filenameorpid.md) | Filename or PID of script to check. This is case-sensitive. |
|
||||
| host | string | Host of target server. |
|
||||
| args | string\[\] | Arguments to specify/identify which scripts to search for. |
|
||||
| args | (string \| number \| boolean)\[\] | Arguments to specify/identify which scripts to search for. |
|
||||
|
||||
<b>Returns:</b>
|
||||
|
||||
|
@ -9,7 +9,7 @@ Terminate another script.
|
||||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
kill(script: string, host: string, ...args: string[]): boolean;
|
||||
kill(script: string, host: string, ...args: (string | number | boolean)[]): boolean;
|
||||
```
|
||||
|
||||
## Parameters
|
||||
@ -18,7 +18,7 @@ kill(script: string, host: string, ...args: string[]): boolean;
|
||||
| --- | --- | --- |
|
||||
| script | string | Filename or pid of the script to kill |
|
||||
| host | string | Hostname of the server on which to kill the script. |
|
||||
| args | string\[\] | Arguments to identify which script to kill. |
|
||||
| args | (string \| number \| boolean)\[\] | Arguments to identify which script to kill. |
|
||||
|
||||
<b>Returns:</b>
|
||||
|
||||
|
@ -9,7 +9,7 @@ Start another script on the current server.
|
||||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
run(script: string, numThreads?: number, ...args: Array<string | number | boolean>): number;
|
||||
run(script: string, numThreads?: number, ...args: (string | number | boolean)[]): number;
|
||||
```
|
||||
|
||||
## Parameters
|
||||
@ -18,7 +18,7 @@ run(script: string, numThreads?: number, ...args: Array<string | number | boolea
|
||||
| --- | --- | --- |
|
||||
| script | string | Filename of script to run. |
|
||||
| numThreads | number | Optional thread count for new script. Set to 1 by default. Will be rounded to nearest integer. |
|
||||
| args | Array<string \| number \| boolean> | Additional arguments to pass into the new script that is being run. Note that if any arguments are being passed into the new script, then the second argument numThreads must be filled in with a value. |
|
||||
| args | (string \| number \| boolean)\[\] | Additional arguments to pass into the new script that is being run. Note that if any arguments are being passed into the new script, then the second argument numThreads must be filled in with a value. |
|
||||
|
||||
<b>Returns:</b>
|
||||
|
||||
|
@ -9,7 +9,7 @@ Terminate current script and start another in 10s.
|
||||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
spawn(script: string, numThreads?: number, ...args: string[]): void;
|
||||
spawn(script: string, numThreads?: number, ...args: (string | number | boolean)[]): void;
|
||||
```
|
||||
|
||||
## Parameters
|
||||
@ -18,7 +18,7 @@ spawn(script: string, numThreads?: number, ...args: string[]): void;
|
||||
| --- | --- | --- |
|
||||
| script | string | Filename of script to execute. |
|
||||
| numThreads | number | Number of threads to spawn new script with. Will be rounded to nearest integer. |
|
||||
| args | string\[\] | Additional arguments to pass into the new script that is being run. |
|
||||
| args | (string \| number \| boolean)\[\] | Additional arguments to pass into the new script that is being run. |
|
||||
|
||||
<b>Returns:</b>
|
||||
|
||||
|
@ -9,7 +9,7 @@ Open the tail window of a script.
|
||||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
tail(fn?: FilenameOrPID, host?: string, ...args: any[]): void;
|
||||
tail(fn?: FilenameOrPID, host?: string, ...args: (string | number | boolean)[]): void;
|
||||
```
|
||||
|
||||
## Parameters
|
||||
@ -18,7 +18,7 @@ tail(fn?: FilenameOrPID, host?: string, ...args: any[]): void;
|
||||
| --- | --- | --- |
|
||||
| fn | [FilenameOrPID](./bitburner.filenameorpid.md) | Optional. Filename or PID of the script being tailed. If omitted, the current script is tailed. |
|
||||
| host | string | Optional. Hostname of the script being tailed. Defaults to the server this script is running on. If args are specified, this is not optional. |
|
||||
| args | any\[\] | Arguments for the script being tailed. |
|
||||
| args | (string \| number \| boolean)\[\] | Arguments for the script being tailed. |
|
||||
|
||||
<b>Returns:</b>
|
||||
|
||||
|
@ -27,3 +27,5 @@ void
|
||||
|
||||
RAM cost: 0 GB
|
||||
|
||||
see: https://github.com/alexei/sprintf.js
|
||||
|
||||
|
13
markdown/bitburner.sleevetask.classname.md
Normal file
13
markdown/bitburner.sleevetask.classname.md
Normal file
@ -0,0 +1,13 @@
|
||||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [bitburner](./bitburner.md) > [SleeveTask](./bitburner.sleevetask.md) > [className](./bitburner.sleevetask.classname.md)
|
||||
|
||||
## SleeveTask.className property
|
||||
|
||||
Class being taken at university, if any
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
className: string;
|
||||
```
|
@ -16,6 +16,7 @@ export interface SleeveTask
|
||||
|
||||
| Property | Type | Description |
|
||||
| --- | --- | --- |
|
||||
| [className](./bitburner.sleevetask.classname.md) | string | Class being taken at university, if any |
|
||||
| [crime](./bitburner.sleevetask.crime.md) | string | Crime currently attempting, if any |
|
||||
| [factionWorkType](./bitburner.sleevetask.factionworktype.md) | string | Faction work type being performed, if any |
|
||||
| [gymStatType](./bitburner.sleevetask.gymstattype.md) | string | Stat being trained at the gym, if any |
|
||||
|
@ -17,7 +17,7 @@ import { IAction } from "./IAction";
|
||||
import { IPlayer } from "../PersonObjects/IPlayer";
|
||||
import { createTaskTracker, ITaskTracker } from "../PersonObjects/ITaskTracker";
|
||||
import { IPerson } from "../PersonObjects/IPerson";
|
||||
import { IRouter, Page } from "../ui/Router";
|
||||
import { IRouter } from "../ui/Router";
|
||||
import { ConsoleHelpText } from "./data/Help";
|
||||
import { exceptionAlert } from "../utils/helpers/exceptionAlert";
|
||||
import { getRandomInt } from "../utils/helpers/getRandomInt";
|
||||
@ -35,7 +35,6 @@ import { getTimestamp } from "../utils/helpers/getTimestamp";
|
||||
import { joinFaction } from "../Faction/FactionHelpers";
|
||||
import { WorkerScript } from "../Netscript/WorkerScript";
|
||||
import { FactionNames } from "../Faction/data/FactionNames";
|
||||
import { BlackOperationNames } from "./data/BlackOperationNames";
|
||||
import { KEY } from "../utils/helpers/keyCodes";
|
||||
|
||||
interface BlackOpsAttempt {
|
||||
@ -237,13 +236,13 @@ export class Bladeburner implements IBladeburner {
|
||||
}
|
||||
}
|
||||
|
||||
upgradeSkill(skill: Skill): void {
|
||||
upgradeSkill(skill: Skill, count = 1): void {
|
||||
// This does NOT handle deduction of skill points
|
||||
const skillName = skill.name;
|
||||
if (this.skills[skillName]) {
|
||||
++this.skills[skillName];
|
||||
this.skills[skillName] += count;
|
||||
} else {
|
||||
this.skills[skillName] = 1;
|
||||
this.skills[skillName] = count;
|
||||
}
|
||||
if (isNaN(this.skills[skillName]) || this.skills[skillName] < 0) {
|
||||
throw new Error("Level of Skill " + skillName + " is invalid: " + this.skills[skillName]);
|
||||
@ -2277,7 +2276,7 @@ export class Bladeburner implements IBladeburner {
|
||||
}
|
||||
}
|
||||
|
||||
getSkillUpgradeCostNetscriptFn(skillName: string, workerScript: WorkerScript): number {
|
||||
getSkillUpgradeCostNetscriptFn(skillName: string, count: number, workerScript: WorkerScript): number {
|
||||
if (skillName === "" || !Skills.hasOwnProperty(skillName)) {
|
||||
workerScript.log("bladeburner.getSkillUpgradeCost", () => `Invalid skill: '${skillName}'`);
|
||||
return -1;
|
||||
@ -2285,13 +2284,13 @@ export class Bladeburner implements IBladeburner {
|
||||
|
||||
const skill = Skills[skillName];
|
||||
if (this.skills[skillName] == null) {
|
||||
return skill.calculateCost(0);
|
||||
return skill.calculateCost(0, count);
|
||||
} else {
|
||||
return skill.calculateCost(this.skills[skillName]);
|
||||
return skill.calculateCost(this.skills[skillName], count);
|
||||
}
|
||||
}
|
||||
|
||||
upgradeSkillNetscriptFn(skillName: string, workerScript: WorkerScript): boolean {
|
||||
upgradeSkillNetscriptFn(skillName: string, count: number, workerScript: WorkerScript): boolean {
|
||||
const errorLogText = `Invalid skill: '${skillName}'`;
|
||||
if (!Skills.hasOwnProperty(skillName)) {
|
||||
workerScript.log("bladeburner.upgradeSkill", () => errorLogText);
|
||||
@ -2303,10 +2302,10 @@ export class Bladeburner implements IBladeburner {
|
||||
if (this.skills[skillName] && !isNaN(this.skills[skillName])) {
|
||||
currentLevel = this.skills[skillName];
|
||||
}
|
||||
const cost = skill.calculateCost(currentLevel);
|
||||
const cost = skill.calculateCost(currentLevel, count);
|
||||
|
||||
if (skill.maxLvl && currentLevel >= skill.maxLvl) {
|
||||
workerScript.log("bladeburner.upgradeSkill", () => `Skill '${skillName}' is already maxed.`);
|
||||
if (skill.maxLvl && currentLevel + count > skill.maxLvl) {
|
||||
workerScript.log("bladeburner.upgradeSkill", () => `Skill '${skillName}' cannot be upgraded ${count} time(s).`);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -2314,13 +2313,13 @@ export class Bladeburner implements IBladeburner {
|
||||
workerScript.log(
|
||||
"bladeburner.upgradeSkill",
|
||||
() =>
|
||||
`You do not have enough skill points to upgrade ${skillName} (You have ${this.skillPoints}, you need ${cost})`,
|
||||
`You do not have enough skill points to upgrade ${skillName} ${count} time(s). (You have ${this.skillPoints}, you need ${cost})`,
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
this.skillPoints -= cost;
|
||||
this.upgradeSkill(skill);
|
||||
this.upgradeSkill(skill, count);
|
||||
workerScript.log("bladeburner.upgradeSkill", () => `'${skillName}' upgraded to level ${this.skills[skillName]}`);
|
||||
return true;
|
||||
}
|
||||
|
@ -76,8 +76,8 @@ export interface IBladeburner {
|
||||
getActionEstimatedSuccessChanceNetscriptFn(person: IPerson, type: string, name: string): [number, number] | string;
|
||||
getActionCountRemainingNetscriptFn(type: string, name: string, workerScript: WorkerScript): number;
|
||||
getSkillLevelNetscriptFn(skillName: string, workerScript: WorkerScript): number;
|
||||
getSkillUpgradeCostNetscriptFn(skillName: string, workerScript: WorkerScript): number;
|
||||
upgradeSkillNetscriptFn(skillName: string, workerScript: WorkerScript): boolean;
|
||||
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;
|
||||
|
@ -133,8 +133,37 @@ export class Skill {
|
||||
}
|
||||
}
|
||||
|
||||
calculateCost(currentLevel: number): number {
|
||||
calculateCost(currentLevel: number, count = 1): number {
|
||||
//Recursive mode does not handle invalid inputs properly, but it should never
|
||||
//be possible for it to run with them. For the sake of not crashing the game,
|
||||
const recursiveMode = (currentLevel: number, count: number): number => {
|
||||
if (count <= 1) {
|
||||
return Math.floor((this.baseCost + currentLevel * this.costInc) * BitNodeMultipliers.BladeburnerSkillCost);
|
||||
} else {
|
||||
const thisUpgrade = Math.floor(
|
||||
(this.baseCost + currentLevel * this.costInc) * BitNodeMultipliers.BladeburnerSkillCost,
|
||||
);
|
||||
return this.calculateCost(currentLevel + 1, count - 1) + thisUpgrade;
|
||||
}
|
||||
};
|
||||
|
||||
//Count must be a positive integer.
|
||||
if (count < 0 || count % 1 != 0) {
|
||||
throw new Error(`${count} is an invalid number of upgrades`);
|
||||
}
|
||||
//Use recursive mode if count is small
|
||||
if (count <= 100) {
|
||||
return recursiveMode(currentLevel, count);
|
||||
}
|
||||
//Use optimized mode if count is large
|
||||
else {
|
||||
//unFloored is roughly equivalent to
|
||||
//(this.baseCost + currentLevel * this.costInc) * BitNodeMultipliers.BladeburnerSkillCost
|
||||
//being repeated for increasing currentLevel
|
||||
const preMult = (count * (2 * this.baseCost + this.costInc * (2 * currentLevel + count + 1))) / 2;
|
||||
const unFloored = preMult * BitNodeMultipliers.BladeburnerSkillCost - count / 2;
|
||||
return Math.floor(unFloored);
|
||||
}
|
||||
}
|
||||
|
||||
getMultiplier(name: string): number {
|
||||
|
@ -123,7 +123,7 @@ export const BlackOperations: {
|
||||
desc: (
|
||||
<>
|
||||
CODE RED SITUATION. Our intelligence tells us that VitaLife has discovered a new android cloning technology.
|
||||
This technology is supposedly capable of cloning Synthoid, not only physically but also their advanced AI
|
||||
This technology is supposedly capable of cloning Synthoids, not only physically but also their advanced AI
|
||||
modules. We do not believe that VitaLife is trying to use this technology illegally or maliciously, but if any
|
||||
Synthoids were able to infiltrate the corporation and take advantage of this technology then the results would
|
||||
be catastrophic.
|
||||
@ -256,8 +256,8 @@ export const BlackOperations: {
|
||||
ones from the Uprising.
|
||||
<br />
|
||||
<br />
|
||||
{FactionNames.OmniTekIncorporated} has also told us they they believe someone has triggered this malfunction in
|
||||
a large group of MK-VI Synthoids, and that these newly-radicalized Synthoids are now amassing in{" "}
|
||||
{FactionNames.OmniTekIncorporated} has also told us they believe someone has triggered this malfunction in a
|
||||
large group of MK-VI Synthoids, and that these newly-radicalized Synthoids are now amassing in{" "}
|
||||
{CityName.Volhaven} to form a terrorist group called Ultron.
|
||||
<br />
|
||||
<br />
|
||||
|
@ -229,7 +229,7 @@ export const CONSTANTS: {
|
||||
|
||||
InfiniteLoopLimit: 2000,
|
||||
|
||||
Donations: 7,
|
||||
Donations: 20,
|
||||
|
||||
LatestUpdate: `
|
||||
## [draft] v1.7.0 - 2022-04-13 to 2022-05-20
|
||||
|
@ -82,12 +82,12 @@ export function LevelUpgrade(corporation: ICorporation, upgrade: CorporationUpgr
|
||||
}
|
||||
}
|
||||
|
||||
export function IssueDividends(corporation: ICorporation, percent: number): void {
|
||||
if (isNaN(percent) || percent < 0 || percent > CorporationConstants.DividendMaxPercentage) {
|
||||
throw new Error(`Invalid value. Must be an integer between 0 and ${CorporationConstants.DividendMaxPercentage}`);
|
||||
export function IssueDividends(corporation: ICorporation, 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}`);
|
||||
}
|
||||
|
||||
corporation.dividendPercentage = percent * 100;
|
||||
corporation.dividendRate = rate;
|
||||
}
|
||||
|
||||
export function SellMaterial(mat: Material, amt: string, price: string): void {
|
||||
|
@ -35,8 +35,8 @@ export class Corporation {
|
||||
shareSalesUntilPriceUpdate = CorporationConstants.SHARESPERPRICEUPDATE;
|
||||
shareSaleCooldown = 0; // Game cycles until player can sell shares again
|
||||
issueNewSharesCooldown = 0; // Game cycles until player can issue shares again
|
||||
dividendPercentage = 0;
|
||||
dividendTaxPercentage = 50;
|
||||
dividendRate = 0;
|
||||
dividendTax = 1 - BitNodeMultipliers.CorporationSoftcap + 0.15;
|
||||
issuedShares = 0;
|
||||
sharePrice = 0;
|
||||
storedCycles = 0;
|
||||
@ -121,18 +121,19 @@ export class Corporation {
|
||||
}
|
||||
|
||||
// Process dividends
|
||||
if (this.dividendPercentage > 0 && cycleProfit > 0) {
|
||||
this.updateDividendTax();
|
||||
if (this.dividendRate > 0 && cycleProfit > 0) {
|
||||
// Validate input again, just to be safe
|
||||
if (
|
||||
isNaN(this.dividendPercentage) ||
|
||||
this.dividendPercentage < 0 ||
|
||||
this.dividendPercentage > CorporationConstants.DividendMaxPercentage * 100
|
||||
isNaN(this.dividendRate) ||
|
||||
this.dividendRate < 0 ||
|
||||
this.dividendRate > CorporationConstants.DividendMaxRate
|
||||
) {
|
||||
console.error(`Invalid Corporation dividend percentage: ${this.dividendPercentage}`);
|
||||
console.error(`Invalid Corporation dividend rate: ${this.dividendRate}`);
|
||||
} else {
|
||||
const totalDividends = (this.dividendPercentage / 100) * cycleProfit;
|
||||
const totalDividends = this.dividendRate * cycleProfit;
|
||||
const retainedEarnings = cycleProfit - totalDividends;
|
||||
player.gainMoney(this.getDividends(), "corporation");
|
||||
player.gainMoney(this.getCycleDividends(), "corporation");
|
||||
this.addFunds(retainedEarnings);
|
||||
}
|
||||
} else {
|
||||
@ -146,20 +147,23 @@ export class Corporation {
|
||||
}
|
||||
}
|
||||
|
||||
getDividends(): number {
|
||||
const profit = this.revenue - this.expenses;
|
||||
const cycleProfit = profit * CorporationConstants.SecsPerMarketCycle;
|
||||
const totalDividends = (this.dividendPercentage / 100) * cycleProfit;
|
||||
const dividendsPerShare = totalDividends / this.totalShares;
|
||||
const dividends = this.numShares * dividendsPerShare;
|
||||
let upgrades = -0.15;
|
||||
updateDividendTax(): void {
|
||||
this.dividendTax = 1 - BitNodeMultipliers.CorporationSoftcap + 0.15;
|
||||
if (this.unlockUpgrades[5] === 1) {
|
||||
upgrades += 0.05;
|
||||
this.dividendTax -= 0.05;
|
||||
}
|
||||
if (this.unlockUpgrades[6] === 1) {
|
||||
upgrades += 0.1;
|
||||
this.dividendTax -= 0.1;
|
||||
}
|
||||
return Math.pow(dividends, BitNodeMultipliers.CorporationSoftcap + upgrades);
|
||||
}
|
||||
|
||||
getCycleDividends(): number {
|
||||
const profit = this.revenue - this.expenses;
|
||||
const cycleProfit = profit * CorporationConstants.SecsPerMarketCycle;
|
||||
const totalDividends = this.dividendRate * cycleProfit;
|
||||
const dividendsPerShare = totalDividends / this.totalShares;
|
||||
const dividends = this.numShares * dividendsPerShare;
|
||||
return Math.pow(dividends, 1 - this.dividendTax);
|
||||
}
|
||||
|
||||
determineValuation(): number {
|
||||
@ -167,8 +171,8 @@ export class Corporation {
|
||||
profit = this.avgProfit;
|
||||
if (this.public) {
|
||||
// Account for dividends
|
||||
if (this.dividendPercentage > 0) {
|
||||
profit *= (100 - this.dividendPercentage) / 100;
|
||||
if (this.dividendRate > 0) {
|
||||
profit *= 1 - this.dividendRate;
|
||||
}
|
||||
|
||||
val = this.funds + profit * 85e3;
|
||||
@ -277,11 +281,7 @@ export class Corporation {
|
||||
this.funds = this.funds - price;
|
||||
|
||||
// Apply effects for one-time upgrades
|
||||
if (upgN === 5) {
|
||||
this.dividendTaxPercentage -= 5;
|
||||
} else if (upgN === 6) {
|
||||
this.dividendTaxPercentage -= 10;
|
||||
}
|
||||
this.updateDividendTax();
|
||||
}
|
||||
|
||||
//Levelable upgrades
|
||||
|
@ -19,8 +19,8 @@ export interface ICorporation {
|
||||
shareSalesUntilPriceUpdate: number;
|
||||
shareSaleCooldown: number;
|
||||
issueNewSharesCooldown: number;
|
||||
dividendPercentage: number;
|
||||
dividendTaxPercentage: number;
|
||||
dividendRate: number;
|
||||
dividendTax: number;
|
||||
issuedShares: number;
|
||||
sharePrice: number;
|
||||
storedCycles: number;
|
||||
@ -54,6 +54,7 @@ export interface ICorporation {
|
||||
getSalesMultiplier(): number;
|
||||
getScientificResearchMultiplier(): number;
|
||||
getStarterGuide(player: IPlayer): void;
|
||||
updateDividendTax(): void;
|
||||
getCycleDividends(): number;
|
||||
toJSON(): any;
|
||||
getDividends(): number;
|
||||
}
|
||||
|
@ -19,7 +19,7 @@ export const CorporationConstants: {
|
||||
BribeThreshold: number;
|
||||
BribeToRepRatio: number;
|
||||
ProductProductionCostRatio: number;
|
||||
DividendMaxPercentage: number;
|
||||
DividendMaxRate: number;
|
||||
EmployeeSalaryMultiplier: number;
|
||||
CyclesPerEmployeeRaise: number;
|
||||
EmployeeRaiseAmount: number;
|
||||
@ -61,7 +61,7 @@ export const CorporationConstants: {
|
||||
|
||||
ProductProductionCostRatio: 5, //Ratio of material cost of a product to its production cost
|
||||
|
||||
DividendMaxPercentage: 1,
|
||||
DividendMaxRate: 1,
|
||||
|
||||
EmployeeSalaryMultiplier: 3, // Employee stats multiplied by this to determine initial salary
|
||||
CyclesPerEmployeeRaise: 400, // All employees get a raise every X market cycles
|
||||
|
@ -71,7 +71,7 @@ export const CorporationUpgrades: Record<CorporationUpgradeIndex, CorporationUpg
|
||||
name: "Wilson Analytics",
|
||||
desc:
|
||||
"Purchase data and analysis from Wilson, a marketing research " +
|
||||
"firm. Each level of this upgrades increases the effectiveness of your " +
|
||||
"firm. Each level of this upgrade increases the effectiveness of your " +
|
||||
"advertising by 0.5% (additive).",
|
||||
},
|
||||
|
||||
|
@ -275,17 +275,18 @@ interface IDividendsStatsProps {
|
||||
}
|
||||
function DividendsStats({ profit }: IDividendsStatsProps): React.ReactElement {
|
||||
const corp = useCorporation();
|
||||
if (corp.dividendPercentage <= 0 || profit <= 0) return <></>;
|
||||
const totalDividends = (corp.dividendPercentage / 100) * profit;
|
||||
if (corp.dividendRate <= 0 || profit <= 0) return <></>;
|
||||
const totalDividends = corp.dividendRate * profit;
|
||||
const retainedEarnings = profit - totalDividends;
|
||||
const dividendsPerShare = totalDividends / corp.totalShares;
|
||||
const playerEarnings = corp.getCycleDividends() / CorporationConstants.SecsPerMarketCycle;
|
||||
return (
|
||||
<StatsTable
|
||||
rows={[
|
||||
["Retained Profits (after dividends):", <MoneyRate money={retainedEarnings} />],
|
||||
["Dividend Percentage:", numeralWrapper.format(corp.dividendPercentage / 100, "0%")],
|
||||
["Dividend Percentage:", numeralWrapper.format(corp.dividendRate, "0%")],
|
||||
["Dividends per share:", <MoneyRate money={dividendsPerShare} />],
|
||||
["Your earnings as a shareholder:", <MoneyRate money={corp.getDividends()} />],
|
||||
["Your earnings as a shareholder:", <MoneyRate money={playerEarnings} />],
|
||||
]}
|
||||
/>
|
||||
);
|
||||
|
@ -19,7 +19,7 @@ export function IssueDividendsModal(props: IProps): React.ReactElement {
|
||||
const corp = useCorporation();
|
||||
const [percent, setPercent] = useState(0);
|
||||
|
||||
const canIssue = !isNaN(percent) && percent >= 0 && percent <= CorporationConstants.DividendMaxPercentage * 100;
|
||||
const canIssue = !isNaN(percent) && percent >= 0 && percent <= CorporationConstants.DividendMaxRate * 100;
|
||||
function issueDividends(): void {
|
||||
if (!canIssue) return;
|
||||
if (percent === null) return;
|
||||
|
@ -66,7 +66,7 @@ export function ActiveFragmentSummary(props: IProps): React.ReactElement {
|
||||
</TableRow>
|
||||
{summary.map((entry) => {
|
||||
return (
|
||||
<TableRow>
|
||||
<TableRow key={entry.type}>
|
||||
<TableCell sx={{ borderBottom: "none", p: 0, m: 0 }}>
|
||||
<Typography>
|
||||
{entry.coordinate.map((coord) => {
|
||||
|
@ -3,7 +3,7 @@ import * as React from "react";
|
||||
import { ActiveFragment } from "../ActiveFragment";
|
||||
import { DummyGift } from "../DummyGift";
|
||||
import { Grid } from "./Grid";
|
||||
import { calculateGrid, zeros } from "../Helper";
|
||||
import { zeros } from "../Helper";
|
||||
|
||||
interface IProps {
|
||||
width: number;
|
||||
@ -13,7 +13,6 @@ interface IProps {
|
||||
|
||||
export function DummyGrid(props: IProps): React.ReactElement {
|
||||
const gift = new DummyGift(props.width, props.height, props.fragments);
|
||||
const activeGrid = calculateGrid(gift);
|
||||
const ghostGrid = zeros([props.width, props.height]);
|
||||
return (
|
||||
<Box>
|
||||
@ -21,7 +20,6 @@ export function DummyGrid(props: IProps): React.ReactElement {
|
||||
<Grid
|
||||
width={props.width}
|
||||
height={props.height}
|
||||
activeGrid={activeGrid}
|
||||
ghostGrid={ghostGrid}
|
||||
gift={gift}
|
||||
enter={() => undefined}
|
||||
|
@ -1,13 +1,13 @@
|
||||
import { TableBody, TableRow } from "@mui/material";
|
||||
import * as React from "react";
|
||||
import { ActiveFragment } from "../ActiveFragment";
|
||||
import { calculateGrid } from "../Helper";
|
||||
import { IStaneksGift } from "../IStaneksGift";
|
||||
import { Cell } from "./Cell";
|
||||
|
||||
interface IProps {
|
||||
width: number;
|
||||
height: number;
|
||||
activeGrid: number[][];
|
||||
ghostGrid: number[][];
|
||||
gift: IStaneksGift;
|
||||
enter(i: number, j: number): void;
|
||||
@ -32,11 +32,13 @@ function randomColor(fragment: ActiveFragment): string {
|
||||
}
|
||||
|
||||
export function Grid(props: IProps): React.ReactElement {
|
||||
const activeGrid = calculateGrid(props.gift);
|
||||
|
||||
function color(worldX: number, worldY: number): string {
|
||||
if (props.ghostGrid[worldX][worldY] && props.activeGrid[worldX][worldY]) return "red";
|
||||
if (props.ghostGrid[worldX][worldY] && activeGrid[worldX][worldY]) return "red";
|
||||
if (props.ghostGrid[worldX][worldY]) return "white";
|
||||
|
||||
if (props.activeGrid[worldX][worldY]) {
|
||||
if (activeGrid[worldX][worldY]) {
|
||||
const fragment = props.gift.fragmentAt(worldX, worldY);
|
||||
if (!fragment) throw new Error("ActiveFragment should not be null");
|
||||
return randomColor(fragment);
|
||||
|
@ -8,7 +8,7 @@ import Box from "@mui/material/Box";
|
||||
import Button from "@mui/material/Button";
|
||||
import { Table } from "../../ui/React/Table";
|
||||
import { Grid } from "./Grid";
|
||||
import { zeros, calculateGrid } from "../Helper";
|
||||
import { zeros } from "../Helper";
|
||||
import { ActiveFragmentSummary } from "./ActiveFragmentSummary";
|
||||
import Tooltip from "@mui/material/Tooltip";
|
||||
import Typography from "@mui/material/Typography";
|
||||
@ -18,7 +18,6 @@ interface IProps {
|
||||
}
|
||||
|
||||
export function MainBoard(props: IProps): React.ReactElement {
|
||||
const [grid, setGrid] = React.useState(calculateGrid(props.gift));
|
||||
const [ghostGrid, setGhostGrid] = React.useState(zeros([props.gift.width(), props.gift.height()]));
|
||||
const [pos, setPos] = React.useState([0, 0]);
|
||||
const [rotation, setRotation] = React.useState(0);
|
||||
@ -54,12 +53,10 @@ export function MainBoard(props: IProps): React.ReactElement {
|
||||
if (!props.gift.canPlace(worldX, worldY, rotation, selectedFragment)) return;
|
||||
props.gift.place(worldX, worldY, rotation, selectedFragment);
|
||||
}
|
||||
setGrid(calculateGrid(props.gift));
|
||||
}
|
||||
|
||||
function clear(): void {
|
||||
props.gift.clear();
|
||||
setGrid(zeros([props.gift.width(), props.gift.height()]));
|
||||
}
|
||||
|
||||
function updateSelectedFragment(fragment: Fragment): void {
|
||||
@ -92,7 +89,6 @@ export function MainBoard(props: IProps): React.ReactElement {
|
||||
<Grid
|
||||
width={props.gift.width()}
|
||||
height={props.gift.height()}
|
||||
activeGrid={grid}
|
||||
ghostGrid={ghostGrid}
|
||||
gift={props.gift}
|
||||
enter={(i, j) => moveGhost(i, j, rotation)}
|
||||
|
@ -150,7 +150,7 @@ export const FactionInfos: IMap<FactionInfo> = {
|
||||
[FactionNames.BachmanAssociates]: new FactionInfo({
|
||||
infoText: (
|
||||
<>
|
||||
Where Law and Business meet - thats where we are.
|
||||
Where Law and Business meet - that's where we are.
|
||||
<br />
|
||||
<br />
|
||||
Legal Insight - Business Instinct - Innovative Experience.
|
||||
|
@ -252,7 +252,6 @@ export class Gang implements IGang {
|
||||
const total = Object.values(AllGangs)
|
||||
.map((g) => g.territory)
|
||||
.reduce((p, c) => p + c, 0);
|
||||
console.log(total);
|
||||
Object.values(AllGangs).forEach((g) => (g.territory /= total));
|
||||
}
|
||||
}
|
||||
|
@ -426,7 +426,7 @@ function processAllHacknetServerEarnings(player: IPlayer, numCycles: number): nu
|
||||
if (upgrade === null) throw new Error("Could not get the hash upgrade");
|
||||
if (!upgrade.cost) throw new Error("Upgrade is not properly configured");
|
||||
|
||||
const multiplier = Math.floor(wastedHashes / upgrade.cost);
|
||||
const multiplier = wastedHashes / upgrade.cost;
|
||||
if (multiplier > 0) {
|
||||
player.gainMoney(upgrade.value * multiplier, "hacknet");
|
||||
}
|
||||
|
@ -244,7 +244,7 @@ export const Literatures: IMap<Literature> = {};
|
||||
"is that most of the rise is in violent crime such as homicide and assault. According " +
|
||||
"to the study, the city saw a total of 21,406 reported homicides in 2076, which is over " +
|
||||
"a 20% increase compared to 2075.<br><br>" +
|
||||
"CIA director David Glarow says its too early to know " +
|
||||
"CIA director David Glarow says it's too early to know " +
|
||||
"whether these figures indicate the beginning of a sustained increase in crime rates, or whether " +
|
||||
"the year was just an unfortunate outlier. He states that many intelligence and law enforcement " +
|
||||
"agents have noticed an increase in organized crime activites, and believes that these figures may " +
|
||||
@ -319,7 +319,7 @@ export const Literatures: IMap<Literature> = {};
|
||||
"CompanionBot, a robot meant to act as a comforting friend for lonely and grieving people, is eerily human-like " +
|
||||
"in its appearance, speech, mannerisms, and even movement. However its artificial intelligence isn't the same as " +
|
||||
"that of humans. Not yet. It doesn't have sentience or self-awareness or consciousness.<br><br>" +
|
||||
"Many neuroscientists believe that we won't ever reach the point of creating artificial human intelligence. 'At the end of the " +
|
||||
"Many neuroscientists believe that we won't ever reach the point of creating artificial human intelligence. 'At the end of " +
|
||||
"the day, AI comes down to 1's and 0's, while the human brain does not. We'll never see AI that is identical to that of " +
|
||||
"humans.'";
|
||||
Literatures[fn] = new Literature(title, fn, txt);
|
||||
|
@ -232,7 +232,7 @@ export function SpecialLocation(props: IProps): React.ReactElement {
|
||||
<>
|
||||
<Typography>
|
||||
<i>
|
||||
Allison "Mother" Stanek: I see you've taken to my creation. So much so it could hardly be recognized as
|
||||
Allison "Mother" Stanek: I see you've taken to my creation. So much that it could hardly be recognized as
|
||||
one of my own after your tinkering with it. I see you follow the ways of the Machine God as I do, and your
|
||||
mastery of the gift clearly demonstrates that. My hopes are climbing by the day for you.
|
||||
</i>
|
||||
|
@ -279,26 +279,28 @@ export function NetscriptBladeburner(player: IPlayer, workerScript: WorkerScript
|
||||
},
|
||||
getSkillUpgradeCost:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_skillName: unknown): number => {
|
||||
(_skillName: unknown, _count: unknown = 1): number => {
|
||||
const skillName = ctx.helper.string("skillName", _skillName);
|
||||
const count = ctx.helper.number("count", _count);
|
||||
checkBladeburnerAccess(ctx);
|
||||
const bladeburner = player.bladeburner;
|
||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||
try {
|
||||
return bladeburner.getSkillUpgradeCostNetscriptFn(skillName, workerScript);
|
||||
return bladeburner.getSkillUpgradeCostNetscriptFn(skillName, count, workerScript);
|
||||
} catch (e: any) {
|
||||
throw ctx.makeRuntimeErrorMsg(e);
|
||||
}
|
||||
},
|
||||
upgradeSkill:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_skillName: unknown): boolean => {
|
||||
(_skillName: unknown, _count: unknown = 1): boolean => {
|
||||
const skillName = ctx.helper.string("skillName", _skillName);
|
||||
const count = ctx.helper.number("count", _count);
|
||||
checkBladeburnerAccess(ctx);
|
||||
const bladeburner = player.bladeburner;
|
||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||
try {
|
||||
return bladeburner.upgradeSkillNetscriptFn(skillName, workerScript);
|
||||
return bladeburner.upgradeSkillNetscriptFn(skillName, count, workerScript);
|
||||
} catch (e: any) {
|
||||
throw ctx.makeRuntimeErrorMsg(e);
|
||||
}
|
||||
|
@ -913,14 +913,15 @@ export function NetscriptCorporation(player: IPlayer): InternalAPI<NSCorporation
|
||||
},
|
||||
issueDividends:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_percent: unknown): void => {
|
||||
(_rate: unknown): void => {
|
||||
checkAccess(ctx);
|
||||
const percent = ctx.helper.number("percent", _percent);
|
||||
if (percent < 0 || percent > 100)
|
||||
throw new Error("Invalid value for percent field! Must be numeric, greater than 0, and less than 100");
|
||||
const rate = ctx.helper.number("rate", _rate);
|
||||
const max = CorporationConstants.DividendMaxRate;
|
||||
if (rate < 0 || rate > max)
|
||||
throw new Error(`Invalid value for rate field! Must be numeric, greater than 0, and less than ${max}`);
|
||||
const corporation = getCorporation();
|
||||
if (!corporation.public) throw ctx.makeRuntimeErrorMsg(`Your company has not gone public!`);
|
||||
IssueDividends(corporation, percent);
|
||||
IssueDividends(corporation, rate);
|
||||
},
|
||||
|
||||
// If you modify these objects you will affect them for real, it's not
|
||||
@ -947,6 +948,9 @@ export function NetscriptCorporation(player: IPlayer): InternalAPI<NSCorporation
|
||||
shareSaleCooldown: corporation.shareSaleCooldown,
|
||||
issuedShares: corporation.issuedShares,
|
||||
sharePrice: corporation.sharePrice,
|
||||
dividendRate: corporation.dividendRate,
|
||||
dividendTax: corporation.dividendTax,
|
||||
dividendEarnings: corporation.getCycleDividends() / CorporationConstants.SecsPerMarketCycle,
|
||||
state: corporation.state.getState(),
|
||||
divisions: corporation.divisions.map((division): NSDivision => getSafeDivision(division)),
|
||||
};
|
||||
|
@ -42,7 +42,7 @@ export function NetscriptInfiltration(player: IPlayer): InternalAPI<IInfiltratio
|
||||
};
|
||||
return {
|
||||
getPossibleLocations: () => (): string[] => {
|
||||
return getLocationsWithInfiltrations.map((l) => l + "");
|
||||
return getLocationsWithInfiltrations.map((l) => l.name);
|
||||
},
|
||||
getInfiltration:
|
||||
(ctx: NetscriptContext) =>
|
||||
|
@ -164,6 +164,11 @@ export function NetscriptSingularity(player: IPlayer, workerScript: WorkerScript
|
||||
|
||||
const augs = getFactionAugmentationsFiltered(player, fac);
|
||||
|
||||
if (!player.factions.includes(fac.name)) {
|
||||
_ctx.log(() => `You can't purchase augmentations from '${facName}' because you aren't a member`);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!augs.includes(augName)) {
|
||||
_ctx.log(() => `Faction '${facName}' does not have the '${augName}' augmentation.`);
|
||||
return false;
|
||||
|
@ -1326,10 +1326,16 @@ export function createProgramWork(this: IPlayer, numCycles: number): boolean {
|
||||
|
||||
export function finishCreateProgramWork(this: IPlayer, cancelled: boolean): string {
|
||||
const programName = this.createProgramName;
|
||||
let message = "";
|
||||
if (!cancelled) {
|
||||
//Complete case
|
||||
this.gainIntelligenceExp((CONSTANTS.IntelligenceProgramBaseExpGain * this.timeWorked) / 1000);
|
||||
dialogBoxCreate(`You've finished creating ${programName}!<br>The new program can be found on your home computer.`);
|
||||
const lines = [
|
||||
`You've finished creating ${programName}!`,
|
||||
"The new program can be found on your home computer.",
|
||||
];
|
||||
dialogBoxCreate(lines.join("<br>"));
|
||||
message = lines.join(" ");
|
||||
|
||||
if (!this.getHomeComputer().programs.includes(programName)) {
|
||||
this.getHomeComputer().programs.push(programName);
|
||||
@ -1339,12 +1345,12 @@ export function finishCreateProgramWork(this: IPlayer, cancelled: boolean): stri
|
||||
const perc = (Math.floor((this.timeWorkedCreateProgram / this.timeNeededToCompleteWork) * 10000) / 100).toString();
|
||||
const incompleteName = programName + "-" + perc + "%-INC";
|
||||
this.getHomeComputer().programs.push(incompleteName);
|
||||
message = `Cancelled creating program: ${programName} (${perc}% complete)`;
|
||||
}
|
||||
|
||||
this.isWorking = false;
|
||||
|
||||
this.resetWorkStatus();
|
||||
return "You've finished creating " + programName + "! The new program can be found on your home computer.";
|
||||
return message;
|
||||
}
|
||||
|
||||
export function startGraftAugmentationWork(this: IPlayer, augmentationName: string, time: number): void {
|
||||
@ -1854,7 +1860,11 @@ export function getNextCompanyPosition(
|
||||
}
|
||||
|
||||
export function quitJob(this: IPlayer, company: string, _sing = false): void {
|
||||
if (this.isWorking == true && this.workType !== WorkType.Company && this.companyName == company) {
|
||||
if (
|
||||
this.isWorking === true &&
|
||||
[WorkType.Company, WorkType.CompanyPartTime].includes(this.workType) &&
|
||||
this.companyName === company
|
||||
) {
|
||||
this.finishWork(true);
|
||||
}
|
||||
delete this.jobs[company];
|
||||
|
@ -104,7 +104,7 @@ export function FAQModal({ open, onClose }: IProps): React.ReactElement {
|
||||
<Typography variant="h4">What is Memory?</Typography>
|
||||
<br />
|
||||
<Typography>
|
||||
Sleeve memory dictates what a sleeve's synchronization will be when its reset by switching BitNodes. For
|
||||
Sleeve memory dictates what a sleeve's synchronization will be when it's reset by switching BitNodes. For
|
||||
example, if a sleeve has a memory of 25, then when you switch BitNodes its synchronization will initially be
|
||||
set to 25, rather than 1.
|
||||
</Typography>
|
||||
|
@ -580,7 +580,7 @@ function createNewUpdateText(): void {
|
||||
() =>
|
||||
dialogBoxCreate(
|
||||
"New update!<br>" +
|
||||
"Please report any bugs/issues through the github repository " +
|
||||
"Please report any bugs/issues through the GitHub repository " +
|
||||
"or the Bitburner subreddit (reddit.com/r/bitburner).<br><br>" +
|
||||
CONSTANTS.LatestUpdate,
|
||||
resets,
|
||||
|
55
src/ScriptEditor/NetscriptDefinitions.d.ts
vendored
55
src/ScriptEditor/NetscriptDefinitions.d.ts
vendored
@ -3080,28 +3080,30 @@ export interface Bladeburner {
|
||||
* @remarks
|
||||
* RAM cost: 4 GB
|
||||
*
|
||||
* This function returns the number of skill points needed to upgrade the specified skill.
|
||||
* This function returns the number of skill points needed to upgrade the specified skill the specified number of times.
|
||||
*
|
||||
* The function returns -1 if an invalid skill name is passed in.
|
||||
*
|
||||
* @param skillName - Name of skill. Case-sensitive and must be an exact match
|
||||
* @param count - Number of times to upgrade the skill. Defaults to 1 if not specified.
|
||||
* @returns Number of skill points needed to upgrade the specified skill.
|
||||
*/
|
||||
getSkillUpgradeCost(name: string): number;
|
||||
getSkillUpgradeCost(name: string, count?: number): number;
|
||||
|
||||
/**
|
||||
* Upgrade skill.
|
||||
* @remarks
|
||||
* RAM cost: 4 GB
|
||||
*
|
||||
* Attempts to upgrade the specified Bladeburner skill.
|
||||
* Attempts to upgrade the specified Bladeburner skill the specified number of times.
|
||||
*
|
||||
* Returns true if the skill is successfully upgraded, and false otherwise.
|
||||
*
|
||||
* @param skillName - Name of skill to be upgraded. Case-sensitive and must be an exact match
|
||||
* @param count - Number of times to upgrade the skill. Defaults to 1 if not specified.
|
||||
* @returns true if the skill is successfully upgraded, and false otherwise.
|
||||
*/
|
||||
upgradeSkill(name: string): boolean;
|
||||
upgradeSkill(name: string, count?: number): boolean;
|
||||
|
||||
/**
|
||||
* Get team size.
|
||||
@ -4859,6 +4861,7 @@ export interface NS {
|
||||
* @remarks
|
||||
* RAM cost: 0 GB
|
||||
*
|
||||
* see: https://github.com/alexei/sprintf.js
|
||||
* @param format - format of the message
|
||||
* @param msg - Value to be printed.
|
||||
*/
|
||||
@ -4950,7 +4953,7 @@ export interface NS {
|
||||
* @param args - Arguments to identify which scripts to get logs for.
|
||||
* @returns Returns an string array, where each line is an element in the array. The most recently logged line is at the end of the array.
|
||||
*/
|
||||
getScriptLogs(fn?: string, host?: string, ...args: any[]): string[];
|
||||
getScriptLogs(fn?: string, host?: string, ...args: (string | number | boolean)[]): string[];
|
||||
|
||||
/**
|
||||
* Get an array of recently killed scripts across all servers.
|
||||
@ -5013,7 +5016,7 @@ export interface NS {
|
||||
* @param host - Optional. Hostname of the script being tailed. Defaults to the server this script is running on. If args are specified, this is not optional.
|
||||
* @param args - Arguments for the script being tailed.
|
||||
*/
|
||||
tail(fn?: FilenameOrPID, host?: string, ...args: any[]): void;
|
||||
tail(fn?: FilenameOrPID, host?: string, ...args: (string | number | boolean)[]): void;
|
||||
|
||||
/**
|
||||
* Close the tail window of a script.
|
||||
@ -5218,7 +5221,7 @@ export interface NS {
|
||||
* @param args - Additional arguments to pass into the new script that is being run. Note that if any arguments are being passed into the new script, then the second argument numThreads must be filled in with a value.
|
||||
* @returns Returns the PID of a successfully started script, and 0 otherwise.
|
||||
*/
|
||||
run(script: string, numThreads?: number, ...args: Array<string | number | boolean>): number;
|
||||
run(script: string, numThreads?: number, ...args: (string | number | boolean)[]): number;
|
||||
|
||||
/**
|
||||
* Start another script on any server.
|
||||
@ -5266,7 +5269,7 @@ export interface NS {
|
||||
* @param args - Additional arguments to pass into the new script that is being run. Note that if any arguments are being passed into the new script, then the third argument numThreads must be filled in with a value.
|
||||
* @returns Returns the PID of a successfully started script, and 0 otherwise.
|
||||
*/
|
||||
exec(script: string, host: string, numThreads?: number, ...args: Array<string | number | boolean>): number;
|
||||
exec(script: string, host: string, numThreads?: number, ...args: (string | number | boolean)[]): number;
|
||||
|
||||
/**
|
||||
* Terminate current script and start another in 10s.
|
||||
@ -5296,7 +5299,7 @@ export interface NS {
|
||||
* @param numThreads - Number of threads to spawn new script with. Will be rounded to nearest integer.
|
||||
* @param args - Additional arguments to pass into the new script that is being run.
|
||||
*/
|
||||
spawn(script: string, numThreads?: number, ...args: string[]): void;
|
||||
spawn(script: string, numThreads?: number, ...args: (string | number | boolean)[]): void;
|
||||
|
||||
/**
|
||||
* Terminate another script.
|
||||
@ -5366,7 +5369,7 @@ export interface NS {
|
||||
* ns.kill("foo.script", getHostname(), 1, "foodnstuff");
|
||||
* ```
|
||||
*/
|
||||
kill(script: string, host: string, ...args: string[]): boolean;
|
||||
kill(script: string, host: string, ...args: (string | number | boolean)[]): boolean;
|
||||
|
||||
/**
|
||||
* Terminate all scripts on a server.
|
||||
@ -5863,7 +5866,7 @@ export interface NS {
|
||||
* @param args - Arguments to specify/identify which scripts to search for.
|
||||
* @returns True if specified script is running on the target server, and false otherwise.
|
||||
*/
|
||||
isRunning(script: FilenameOrPID, host: string, ...args: string[]): boolean;
|
||||
isRunning(script: FilenameOrPID, host?: string, ...args: (string | number | boolean)[]): boolean;
|
||||
|
||||
/**
|
||||
* Get general info about a running script.
|
||||
@ -5878,7 +5881,11 @@ export interface NS {
|
||||
* @param args - Arguments to identify the script
|
||||
* @returns The info about the running script if found, and null otherwise.
|
||||
*/
|
||||
getRunningScript(filename?: FilenameOrPID, hostname?: string, ...args: (string | number)[]): RunningScript | null;
|
||||
getRunningScript(
|
||||
filename?: FilenameOrPID,
|
||||
hostname?: string,
|
||||
...args: (string | number | boolean)[]
|
||||
): RunningScript | null;
|
||||
|
||||
/**
|
||||
* Get cost of purchasing a server.
|
||||
@ -6204,13 +6211,13 @@ export interface NS {
|
||||
* Get the execution time of a hack() call.
|
||||
* @remarks
|
||||
* RAM cost: 0.05 GB
|
||||
*
|
||||
* When `hack` completes an amount of money is stolen depending on the player's skills.
|
||||
* Returns the amount of time in milliseconds it takes to execute the hack Netscript function on the target server.
|
||||
* The function takes in an optional hackLvl parameter that can be specified to see what the hack time would be at different hacking levels.
|
||||
* The required time is increased by the security level of the target server and decreased by the player's hacking level.
|
||||
*
|
||||
* @param host - Host of target server.
|
||||
* @returns Returns the amount of time in milliseconds it takes to execute the hack Netscript function. Returns Infinity if called on a Hacknet Server.
|
||||
* @returns Returns the amount of time in milliseconds it takes to execute the hack Netscript function.
|
||||
*/
|
||||
getHackTime(host: string): number;
|
||||
|
||||
@ -6220,11 +6227,10 @@ export interface NS {
|
||||
* RAM cost: 0.05 GB
|
||||
*
|
||||
* Returns the amount of time in milliseconds it takes to execute the grow Netscript function on the target server.
|
||||
* The function takes in an optional hackLvl parameter that can be specified to see what the grow time would be at different hacking levels.
|
||||
* The required time is increased by the security level of the target server and decreased by the player's hacking level.
|
||||
*
|
||||
* @param host - Host of target server.
|
||||
* @returns Returns the amount of time in milliseconds it takes to execute the grow Netscript function. Returns Infinity if called on a Hacknet Server.
|
||||
* @returns Returns the amount of time in milliseconds it takes to execute the grow Netscript function.
|
||||
*/
|
||||
getGrowTime(host: string): number;
|
||||
|
||||
@ -6234,11 +6240,10 @@ export interface NS {
|
||||
* RAM cost: 0.05 GB
|
||||
*
|
||||
* Returns the amount of time in milliseconds it takes to execute the weaken Netscript function on the target server.
|
||||
* The function takes in an optional hackLvl parameter that can be specified to see what the weaken time would be at different hacking levels.
|
||||
* The required time is increased by the security level of the target server and decreased by the player's hacking level.
|
||||
*
|
||||
* @param host - Host of target server.
|
||||
* @returns Returns the amount of time in milliseconds it takes to execute the weaken Netscript function. Returns Infinity if called on a Hacknet Server.
|
||||
* @returns Returns the amount of time in milliseconds it takes to execute the weaken Netscript function.
|
||||
*/
|
||||
getWeakenTime(host: string): number;
|
||||
|
||||
@ -6271,7 +6276,7 @@ export interface NS {
|
||||
/**
|
||||
* {@inheritDoc NS.(getScriptIncome:1)}
|
||||
*/
|
||||
getScriptIncome(script: string, host: string, ...args: string[]): number;
|
||||
getScriptIncome(script: string, host: string, ...args: (string | number | boolean)[]): number;
|
||||
|
||||
/**
|
||||
* Get the exp gain of a script.
|
||||
@ -6295,7 +6300,7 @@ export interface NS {
|
||||
/**
|
||||
* {@inheritDoc NS.(getScriptExpGain:1)}
|
||||
*/
|
||||
getScriptExpGain(script: string, host: string, ...args: string[]): number;
|
||||
getScriptExpGain(script: string, host: string, ...args: (string | number | boolean)[]): number;
|
||||
|
||||
/**
|
||||
* Returns the amount of time in milliseconds that have passed since you last installed Augmentations.
|
||||
@ -7047,9 +7052,9 @@ export interface Corporation extends WarehouseAPI, OfficeAPI {
|
||||
levelUpgrade(upgradeName: string): void;
|
||||
/**
|
||||
* Issue dividends
|
||||
* @param percent - Percent of profit to issue as dividends.
|
||||
* @param rate - Fraction of profit to issue as dividends.
|
||||
*/
|
||||
issueDividends(percent: number): void;
|
||||
issueDividends(rate: number): void;
|
||||
/**
|
||||
* Buyback Shares
|
||||
* @param amount - Amount of shares to buy back.
|
||||
@ -7099,6 +7104,12 @@ interface CorporationInfo {
|
||||
issuedShares: number;
|
||||
/** Price of the shares */
|
||||
sharePrice: number;
|
||||
/** Fraction of profits issued as dividends */
|
||||
dividendRate: number;
|
||||
/** Tax applied on your earnings as a shareholder */
|
||||
dividendTax: number;
|
||||
/** Your earnings as a shareholder per second this cycle */
|
||||
dividendEarnings: number;
|
||||
/** State of the corporation. Possible states are START, PURCHASE, PRODUCTION, SALE, EXPORT. */
|
||||
state: string;
|
||||
/** Array of all divisions */
|
||||
|
@ -272,6 +272,8 @@ export function SidebarRoot(props: IProps): React.ReactElement {
|
||||
// Alt-a - Augmentations
|
||||
// Alt-u - Tutorial
|
||||
// Alt-o - Options
|
||||
// Alt-b - Bladeburner
|
||||
// Alt-g - Gang
|
||||
function handleShortcuts(this: Document, event: KeyboardEvent): any {
|
||||
if (Settings.DisableHotkeys) return;
|
||||
if ((props.player.isWorking && props.player.focus) || props.router.page() === Page.BitVerse) return;
|
||||
@ -315,6 +317,9 @@ export function SidebarRoot(props: IProps): React.ReactElement {
|
||||
} else if (event.code === KEYCODE.U && event.altKey) {
|
||||
event.preventDefault();
|
||||
clickTutorial();
|
||||
} else if (event.code === KEYCODE.O && event.altKey) {
|
||||
event.preventDefault();
|
||||
clickOptions();
|
||||
} else if (event.code === KEYCODE.B && event.altKey && props.player.bladeburner) {
|
||||
event.preventDefault();
|
||||
clickBladeburner();
|
||||
|
@ -35,7 +35,7 @@ export const TerminalHelpText: string[] = [
|
||||
" rm [file] Delete a file from the server",
|
||||
" run [name] [-t n] [--tail] [args...] Execute a program or script",
|
||||
" scan Prints all immediately-available network connections",
|
||||
" scan-analyze [d] [-a] Prints info for all servers up to <i>d</i> nodes away",
|
||||
" scan-analyze [d] [-a] Prints info for all servers up to d nodes away",
|
||||
" scp [file ...] [server] Copies a file to a destination server",
|
||||
" sudov Shows whether you have root access on this computer",
|
||||
" tail [script] [args...] Displays dynamic logs for the specified script",
|
||||
|
@ -16,6 +16,7 @@ import { BitFlumeModal } from "../../BitNode/ui/BitFlumeModal";
|
||||
import { CodingContractModal } from "../../ui/React/CodingContractModal";
|
||||
|
||||
import _ from "lodash";
|
||||
import { ANSIITypography } from "../../ui/React/ANSIITypography";
|
||||
|
||||
interface IActionTimerProps {
|
||||
terminal: ITerminal;
|
||||
@ -43,37 +44,6 @@ const useStyles = makeStyles((theme: Theme) =>
|
||||
padding: theme.spacing(0),
|
||||
height: "100%",
|
||||
},
|
||||
|
||||
success: {
|
||||
whiteSpace: "pre-wrap",
|
||||
overflowWrap: "anywhere",
|
||||
margin: theme.spacing(0),
|
||||
color: theme.colors.success,
|
||||
},
|
||||
error: {
|
||||
whiteSpace: "pre-wrap",
|
||||
overflowWrap: "anywhere",
|
||||
margin: theme.spacing(0),
|
||||
color: theme.palette.error.main,
|
||||
},
|
||||
primary: {
|
||||
whiteSpace: "pre-wrap",
|
||||
overflowWrap: "anywhere",
|
||||
margin: theme.spacing(0),
|
||||
color: theme.palette.primary.main,
|
||||
},
|
||||
info: {
|
||||
whiteSpace: "pre-wrap",
|
||||
overflowWrap: "anywhere",
|
||||
margin: theme.spacing(0),
|
||||
color: theme.palette.info.main,
|
||||
},
|
||||
warning: {
|
||||
whiteSpace: "pre-wrap",
|
||||
overflowWrap: "anywhere",
|
||||
margin: theme.spacing(0),
|
||||
color: theme.palette.warning.main,
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
@ -133,194 +103,6 @@ export function TerminalRoot({ terminal, router, player }: IProps): React.ReactE
|
||||
};
|
||||
}, []);
|
||||
|
||||
function lineClass(s: string): string {
|
||||
const lineClassMap: Record<string, string> = {
|
||||
error: classes.error,
|
||||
success: classes.success,
|
||||
info: classes.info,
|
||||
warn: classes.warning,
|
||||
};
|
||||
return lineClassMap[s] || classes.primary;
|
||||
}
|
||||
|
||||
function ansiCodeStyle(code: string | null): Record<string, any> {
|
||||
// The ANSI colors actually have the dark color set as default and require extra work to get
|
||||
// bright colors. But these are rarely used or, if they are, are often re-mapped by the
|
||||
// terminal emulator to brighter colors. So for foreground colors we use the bright color set
|
||||
// and for background colors we use the dark color set. Of course, all colors are available
|
||||
// via the longer ESC[n8;5;c] sequence (n={3,4}, c=color). Ideally, these 8-bit maps could
|
||||
// be managed in the user preferences/theme.
|
||||
const COLOR_MAP_BRIGHT: Record<string | number, string> = {
|
||||
0: "#404040",
|
||||
1: "#ff0000",
|
||||
2: "#00ff00",
|
||||
3: "#ffff00",
|
||||
4: "#0000ff",
|
||||
5: "#ff00ff",
|
||||
6: "#00ffff",
|
||||
7: "#ffffff",
|
||||
};
|
||||
const COLOR_MAP_DARK: Record<string | number, string> = {
|
||||
0: "#000000",
|
||||
1: "#800000",
|
||||
2: "#008000",
|
||||
3: "#808000",
|
||||
4: "#000080",
|
||||
5: "#800080",
|
||||
6: "#008080",
|
||||
7: "#c0c0c0",
|
||||
};
|
||||
|
||||
const ansi2rgb = (code: number): string => {
|
||||
/* eslint-disable yoda */
|
||||
if (0 <= code && code < 8) {
|
||||
// x8 RGB
|
||||
return COLOR_MAP_BRIGHT[code];
|
||||
}
|
||||
if (8 <= code && code < 16) {
|
||||
// x8 RGB - "High Intensity" (but here, actually the dark set)
|
||||
return COLOR_MAP_DARK[code];
|
||||
}
|
||||
if (16 <= code && code < 232) {
|
||||
// x216 RGB
|
||||
const base = code - 16;
|
||||
const ir = Math.floor(base / 36);
|
||||
const ig = Math.floor((base % 36) / 6);
|
||||
const ib = Math.floor((base % 6) / 1);
|
||||
const r = ir <= 0 ? 0 : 55 + ir * 40;
|
||||
const g = ig <= 0 ? 0 : 55 + ig * 40;
|
||||
const b = ib <= 0 ? 0 : 55 + ib * 40;
|
||||
return `rgb(${r}, ${g}, ${b})`;
|
||||
}
|
||||
if (232 <= code && code < 256) {
|
||||
// x32 greyscale
|
||||
const base = code - 232;
|
||||
const grey = base * 10 + 8;
|
||||
return `rgb(${grey}, ${grey}, ${grey})`;
|
||||
}
|
||||
// shouldn't get here (under normal circumstances), but just in case
|
||||
return "initial";
|
||||
};
|
||||
|
||||
type styleKey = "fontWeight" | "textDecoration" | "color" | "backgroundColor" | "display";
|
||||
const style: {
|
||||
fontWeight?: string;
|
||||
textDecoration?: string;
|
||||
color?: string;
|
||||
backgroundColor?: string;
|
||||
display?: string;
|
||||
} = {};
|
||||
|
||||
if (code === null || code === "0") {
|
||||
return style;
|
||||
}
|
||||
|
||||
const codeParts = code
|
||||
.split(";")
|
||||
.map((p) => parseInt(p))
|
||||
.filter(
|
||||
(p, i, arr) =>
|
||||
// If the sequence is 38;5 (x256 foreground color) or 48;5 (x256 background color),
|
||||
// filter out the 5 so the next codePart after {38,48} is the color code.
|
||||
p != 5 || i == 0 || (arr[i - 1] != 38 && arr[i - 1] != 48),
|
||||
);
|
||||
|
||||
let nextStyleKey: styleKey | null = null;
|
||||
codeParts.forEach((codePart) => {
|
||||
/* eslint-disable yoda */
|
||||
if (nextStyleKey !== null) {
|
||||
style[nextStyleKey] = ansi2rgb(codePart);
|
||||
nextStyleKey = null;
|
||||
}
|
||||
// Decorations
|
||||
else if (codePart == 1) {
|
||||
style.fontWeight = "bold";
|
||||
} else if (codePart == 4) {
|
||||
style.textDecoration = "underline";
|
||||
}
|
||||
// Forground Color (x8)
|
||||
else if (30 <= codePart && codePart < 38) {
|
||||
if (COLOR_MAP_BRIGHT[codePart % 10]) {
|
||||
style.color = COLOR_MAP_BRIGHT[codePart % 10];
|
||||
}
|
||||
}
|
||||
// Background Color (x8)
|
||||
else if (40 <= codePart && codePart < 48) {
|
||||
if (COLOR_MAP_DARK[codePart % 10]) {
|
||||
style.backgroundColor = COLOR_MAP_DARK[codePart % 10];
|
||||
}
|
||||
}
|
||||
// Forground Color (x256)
|
||||
else if (codePart == 38) {
|
||||
nextStyleKey = "color";
|
||||
}
|
||||
// Background Color (x256)
|
||||
else if (codePart == 48) {
|
||||
nextStyleKey = "backgroundColor";
|
||||
}
|
||||
});
|
||||
// If a background color is set, render this as an inline block element (instead of inline)
|
||||
// so that the background between lines (at least those that don't wrap) is uninterrupted.
|
||||
if (style.backgroundColor !== undefined) {
|
||||
style.display = "inline-block";
|
||||
}
|
||||
return style;
|
||||
}
|
||||
|
||||
function parseOutputText(item: Output): React.ReactElement {
|
||||
const parts = [];
|
||||
// Some things, oddly, can cause item.text to not be a string (e.g. expr from the CLI), which
|
||||
// causes .matchAll to throw. Ensure it's a string immediately
|
||||
if (typeof item.text === "string") {
|
||||
// eslint-disable-next-line no-control-regex
|
||||
const ANSI_ESCAPE = new RegExp("\u{001b}\\[(?<code>.*?)m", "ug");
|
||||
// Build a look-alike regex match to place at the front of the matches list
|
||||
const INITIAL = {
|
||||
0: "",
|
||||
index: 0,
|
||||
groups: { code: null },
|
||||
};
|
||||
const matches = [INITIAL, ...item.text.matchAll(ANSI_ESCAPE), null];
|
||||
if (matches.length > 2) {
|
||||
matches.slice(0, -1).forEach((m, i) => {
|
||||
const n = matches[i + 1];
|
||||
if (!m || m.index === undefined || m.groups === undefined) {
|
||||
return;
|
||||
}
|
||||
const startIndex = m.index + m[0].length;
|
||||
const stopIndex = n ? n.index : item.text.length;
|
||||
const partText = item.text.slice(startIndex, stopIndex);
|
||||
if (startIndex !== stopIndex) {
|
||||
// Don't generate "empty" spans
|
||||
parts.push({ code: m.groups.code, text: partText });
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
if (parts.length === 0) {
|
||||
// For example, if the string was empty or there were no escape sequence matches
|
||||
parts.push({ code: null, text: item.text });
|
||||
}
|
||||
return (
|
||||
<Typography classes={{ root: lineClass(item.color) }} paragraph={false}>
|
||||
{parts.map((part, index) => {
|
||||
const spanStyle = ansiCodeStyle(part.code);
|
||||
if (!_.isEmpty(spanStyle)) {
|
||||
// Only wrap parts with spans if the calculated spanStyle is non-empty...
|
||||
return (
|
||||
<Typography key={index} paragraph={false} component="span" sx={spanStyle}>
|
||||
{part.text}
|
||||
</Typography>
|
||||
);
|
||||
} else {
|
||||
// ... otherwise yield the unmodified, unwrapped part.
|
||||
return part.text;
|
||||
}
|
||||
})}
|
||||
</Typography>
|
||||
);
|
||||
}
|
||||
|
||||
const classes = useStyles();
|
||||
return (
|
||||
<>
|
||||
@ -330,9 +112,7 @@ export function TerminalRoot({ terminal, router, player }: IProps): React.ReactE
|
||||
if (item instanceof Output)
|
||||
return (
|
||||
<ListItem key={i} classes={{ root: classes.nopadding }}>
|
||||
<Typography classes={{ root: lineClass(item.color) }} paragraph={false}>
|
||||
{parseOutputText(item)}
|
||||
</Typography>
|
||||
<ANSIITypography text={item.text} color={item.color} />
|
||||
</ListItem>
|
||||
);
|
||||
if (item instanceof RawOutput)
|
||||
|
@ -417,7 +417,7 @@ export const codingContractTypesMetadata: ICodingContractTypeMetadata[] = [
|
||||
{
|
||||
desc: (arr: number[][]): string => {
|
||||
return [
|
||||
"Given the following array of array of numbers representing a list of",
|
||||
"Given the following array of arrays of numbers representing a list of",
|
||||
"intervals, merge all overlapping intervals.\n\n",
|
||||
`[${convert2DArrayToString(arr)}]\n\n`,
|
||||
"Example:\n\n",
|
||||
@ -1282,14 +1282,15 @@ export const codingContractTypesMetadata: ICodingContractTypeMetadata[] = [
|
||||
numTries: 10,
|
||||
desc: (n: string): string => {
|
||||
return [
|
||||
"You are given the following encoded binary String: \n",
|
||||
"You are given the following encoded binary string: \n",
|
||||
`'${n}' \n`,
|
||||
"Treat it as a Hammingcode with 1 'possible' error on an random Index.\n",
|
||||
"Find the 'possible' wrong bit, fix it and extract the decimal value, which is hidden inside the string.\n\n",
|
||||
"Note: The length of the binary string is dynamic, but it's encoding/decoding is following Hammings 'rule'\n",
|
||||
"Note 2: Index 0 is an 'overall' parity bit. Watch the Hammingcode-video from 3Blue1Brown for more information\n",
|
||||
"Note 3: There's a ~55% chance for an altered Bit. So... MAYBE there is an altered Bit 😉\n",
|
||||
"Extranote for automation: return the decimal value as a string",
|
||||
"The string is a Hamming code with 1 'possible' error on a random index.\n",
|
||||
"If there is an error, find the bit that is an error and fix it.\n",
|
||||
"Extract the encoded decimal value and return a string with that value.\n\n",
|
||||
"NOTE: The length of the binary string is dynamic.\n",
|
||||
"NOTE 2: Index 0 is an 'overall' parity bit. Watch the Hamming code video from 3Blue1Brown for more information.\n",
|
||||
"NOTE 3: There's approximately a 55% chance for an altered bit. So... MAYBE there is an altered bit 😉\n",
|
||||
"NOTE 4: Return the decimal value as a string.",
|
||||
].join(" ");
|
||||
},
|
||||
gen: (): string => {
|
||||
@ -1545,7 +1546,7 @@ export const codingContractTypesMetadata: ICodingContractTypeMetadata[] = [
|
||||
return [
|
||||
"Lempel-Ziv (LZ) compression is a data compression technique which encodes data using references to",
|
||||
"earlier parts of the data. In this variant of LZ, data is encoded in two types of chunk. Each chunk",
|
||||
"begins with a length L, encoded as a single ASCII digit from 1 - 9, followed by the chunk data,",
|
||||
"begins with a length L, encoded as a single ASCII digit from 1 to 9, followed by the chunk data,",
|
||||
"which is either:\n\n",
|
||||
"1. Exactly L characters, which are to be copied directly into the uncompressed data.\n",
|
||||
"2. A reference to an earlier part of the uncompressed data. To do this, the length is followed",
|
||||
@ -1580,7 +1581,7 @@ export const codingContractTypesMetadata: ICodingContractTypeMetadata[] = [
|
||||
return [
|
||||
"Lempel-Ziv (LZ) compression is a data compression technique which encodes data using references to",
|
||||
"earlier parts of the data. In this variant of LZ, data is encoded in two types of chunk. Each chunk",
|
||||
"begins with a length L, encoded as a single ASCII digit from 1 - 9, followed by the chunk data,",
|
||||
"begins with a length L, encoded as a single ASCII digit from 1 to 9, followed by the chunk data,",
|
||||
"which is either:\n\n",
|
||||
"1. Exactly L characters, which are to be copied directly into the uncompressed data.\n",
|
||||
"2. A reference to an earlier part of the uncompressed data. To do this, the length is followed",
|
||||
|
@ -58,11 +58,12 @@ export function InteractiveTutorialRoot(): React.ReactElement {
|
||||
const [language, setLanguage] = useState(Language.None);
|
||||
const classes = useStyles();
|
||||
|
||||
const tutorialScriptName = {
|
||||
[Language.None]: "n00dles.script",
|
||||
[Language.NS1]: "n00dles.script",
|
||||
[Language.NS2]: "n00dles.js",
|
||||
const tutorialScriptExtension = {
|
||||
[Language.None]: ".script",
|
||||
[Language.NS1]: ".script",
|
||||
[Language.NS2]: ".js",
|
||||
}[language];
|
||||
const tutorialScriptName = `n00dles${tutorialScriptExtension}`;
|
||||
|
||||
const contents: { [number: string]: IContent | undefined } = {
|
||||
[iTutorialSteps.Start as number]: {
|
||||
@ -377,7 +378,9 @@ export function InteractiveTutorialRoot(): React.ReactElement {
|
||||
</Typography>
|
||||
<Typography classes={{ root: classes.textfield }}>{"[home ~/]> nano"}</Typography>
|
||||
|
||||
<Typography>Scripts must end with the .script extension. Let's make a script now by entering </Typography>
|
||||
<Typography>
|
||||
Scripts must end with the {tutorialScriptExtension} extension. Let's make a script now by entering{" "}
|
||||
</Typography>
|
||||
<Typography classes={{ root: classes.textfield }}>{`[home ~/]> nano ${tutorialScriptName}`}</Typography>
|
||||
|
||||
<Typography>
|
||||
@ -457,7 +460,7 @@ export function InteractiveTutorialRoot(): React.ReactElement {
|
||||
<>
|
||||
<Typography>
|
||||
Your script is now running! It will continuously run in the background and will automatically stop if the
|
||||
code ever completes (the n00dles.script will never complete because it runs an infinite loop). <br />
|
||||
code ever completes (the {tutorialScriptName} will never complete because it runs an infinite loop). <br />
|
||||
<br />
|
||||
These scripts can passively earn you income and hacking experience. Your scripts will also earn money and
|
||||
experience while you are offline, although at a slightly slower rate. <br />
|
||||
|
236
src/ui/React/ANSIITypography.tsx
Normal file
236
src/ui/React/ANSIITypography.tsx
Normal file
@ -0,0 +1,236 @@
|
||||
import { Typography } from "@mui/material";
|
||||
import React from "react";
|
||||
import makeStyles from "@mui/styles/makeStyles";
|
||||
import createStyles from "@mui/styles/createStyles";
|
||||
import { Theme } from "@mui/material/styles";
|
||||
import _ from "lodash";
|
||||
|
||||
// This particular eslint-disable is correct.
|
||||
// In this super specific weird case we in fact do want a regex on an ANSII character.
|
||||
// eslint-disable-next-line no-control-regex
|
||||
const ANSI_ESCAPE = new RegExp("\u{001b}\\[(?<code>.*?)m", "ug");
|
||||
|
||||
const useStyles = makeStyles((theme: Theme) =>
|
||||
createStyles({
|
||||
success: {
|
||||
whiteSpace: "pre-wrap",
|
||||
overflowWrap: "anywhere",
|
||||
margin: theme.spacing(0),
|
||||
color: theme.colors.success,
|
||||
},
|
||||
error: {
|
||||
whiteSpace: "pre-wrap",
|
||||
overflowWrap: "anywhere",
|
||||
margin: theme.spacing(0),
|
||||
color: theme.palette.error.main,
|
||||
},
|
||||
primary: {
|
||||
whiteSpace: "pre-wrap",
|
||||
overflowWrap: "anywhere",
|
||||
margin: theme.spacing(0),
|
||||
color: theme.palette.primary.main,
|
||||
},
|
||||
info: {
|
||||
whiteSpace: "pre-wrap",
|
||||
overflowWrap: "anywhere",
|
||||
margin: theme.spacing(0),
|
||||
color: theme.palette.info.main,
|
||||
},
|
||||
warning: {
|
||||
whiteSpace: "pre-wrap",
|
||||
overflowWrap: "anywhere",
|
||||
margin: theme.spacing(0),
|
||||
color: theme.palette.warning.main,
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
const lineClass = (classes: Record<string, string>, s: string): string => {
|
||||
const lineClassMap: Record<string, string> = {
|
||||
error: classes.error,
|
||||
success: classes.success,
|
||||
info: classes.info,
|
||||
warn: classes.warning,
|
||||
};
|
||||
return lineClassMap[s] || classes.primary;
|
||||
};
|
||||
|
||||
interface IProps {
|
||||
text: unknown;
|
||||
color: "primary" | "error" | "success" | "info" | "warn";
|
||||
}
|
||||
|
||||
export const ANSIITypography = React.memo((props: IProps): React.ReactElement => {
|
||||
const text = String(props.text);
|
||||
const classes = useStyles();
|
||||
const parts = [];
|
||||
|
||||
// Build a look-alike regex match to place at the front of the matches list
|
||||
const INITIAL = {
|
||||
0: "",
|
||||
index: 0,
|
||||
groups: { code: null },
|
||||
};
|
||||
const matches = [INITIAL, ...text.matchAll(ANSI_ESCAPE), null];
|
||||
if (matches.length > 2) {
|
||||
matches.slice(0, -1).forEach((m, i) => {
|
||||
const n = matches[i + 1];
|
||||
if (!m || m.index === undefined || m.groups === undefined) {
|
||||
return;
|
||||
}
|
||||
const startIndex = m.index + m[0].length;
|
||||
const stopIndex = n ? n.index : text.length;
|
||||
const partText = text.slice(startIndex, stopIndex);
|
||||
if (startIndex !== stopIndex) {
|
||||
// Don't generate "empty" spans
|
||||
parts.push({ code: m.groups.code, text: partText });
|
||||
}
|
||||
});
|
||||
}
|
||||
if (parts.length === 0) {
|
||||
// For example, if the string was empty or there were no escape sequence matches
|
||||
parts.push({ code: null, text: text });
|
||||
}
|
||||
return (
|
||||
<Typography classes={{ root: lineClass(classes, props.color) }} paragraph={false}>
|
||||
{parts.map((part, index) => {
|
||||
const spanStyle = ansiCodeStyle(part.code);
|
||||
if (!_.isEmpty(spanStyle)) {
|
||||
// Only wrap parts with spans if the calculated spanStyle is non-empty...
|
||||
return (
|
||||
<Typography key={index} paragraph={false} component="span" sx={spanStyle}>
|
||||
{part.text}
|
||||
</Typography>
|
||||
);
|
||||
} else {
|
||||
// ... otherwise yield the unmodified, unwrapped part.
|
||||
return part.text;
|
||||
}
|
||||
})}
|
||||
</Typography>
|
||||
);
|
||||
});
|
||||
|
||||
function ansiCodeStyle(code: string | null): Record<string, any> {
|
||||
// The ANSI colors actually have the dark color set as default and require extra work to get
|
||||
// bright colors. But these are rarely used or, if they are, are often re-mapped by the
|
||||
// terminal emulator to brighter colors. So for foreground colors we use the bright color set
|
||||
// and for background colors we use the dark color set. Of course, all colors are available
|
||||
// via the longer ESC[n8;5;c] sequence (n={3,4}, c=color). Ideally, these 8-bit maps could
|
||||
// be managed in the user preferences/theme.
|
||||
const COLOR_MAP_BRIGHT: Record<number, string> = {
|
||||
0: "#404040",
|
||||
1: "#ff0000",
|
||||
2: "#00ff00",
|
||||
3: "#ffff00",
|
||||
4: "#0000ff",
|
||||
5: "#ff00ff",
|
||||
6: "#00ffff",
|
||||
7: "#ffffff",
|
||||
};
|
||||
const COLOR_MAP_DARK: Record<number, string> = {
|
||||
0: "#000000",
|
||||
1: "#800000",
|
||||
2: "#008000",
|
||||
3: "#808000",
|
||||
4: "#000080",
|
||||
5: "#800080",
|
||||
6: "#008080",
|
||||
7: "#c0c0c0",
|
||||
};
|
||||
|
||||
const ansi2rgb = (code: number): string => {
|
||||
/* eslint-disable yoda */
|
||||
if (0 <= code && code < 8) {
|
||||
// x8 RGB
|
||||
return COLOR_MAP_BRIGHT[code];
|
||||
}
|
||||
if (8 <= code && code < 16) {
|
||||
// x8 RGB - "High Intensity" (but here, actually the dark set)
|
||||
return COLOR_MAP_DARK[code];
|
||||
}
|
||||
if (16 <= code && code < 232) {
|
||||
// x216 RGB
|
||||
const base = code - 16;
|
||||
const ir = Math.floor(base / 36);
|
||||
const ig = Math.floor((base % 36) / 6);
|
||||
const ib = Math.floor((base % 6) / 1);
|
||||
const r = ir <= 0 ? 0 : 55 + ir * 40;
|
||||
const g = ig <= 0 ? 0 : 55 + ig * 40;
|
||||
const b = ib <= 0 ? 0 : 55 + ib * 40;
|
||||
return `rgb(${r}, ${g}, ${b})`;
|
||||
}
|
||||
if (232 <= code && code < 256) {
|
||||
// x32 greyscale
|
||||
const base = code - 232;
|
||||
const grey = base * 10 + 8;
|
||||
return `rgb(${grey}, ${grey}, ${grey})`;
|
||||
}
|
||||
// shouldn't get here (under normal circumstances), but just in case
|
||||
return "initial";
|
||||
};
|
||||
|
||||
type styleKey = "fontWeight" | "textDecoration" | "color" | "backgroundColor" | "display";
|
||||
const style: {
|
||||
fontWeight?: string;
|
||||
textDecoration?: string;
|
||||
color?: string;
|
||||
backgroundColor?: string;
|
||||
display?: string;
|
||||
} = {};
|
||||
|
||||
if (code === null || code === "0") {
|
||||
return style;
|
||||
}
|
||||
|
||||
const codeParts = code
|
||||
.split(";")
|
||||
.map((p) => parseInt(p))
|
||||
.filter(
|
||||
(p, i, arr) =>
|
||||
// If the sequence is 38;5 (x256 foreground color) or 48;5 (x256 background color),
|
||||
// filter out the 5 so the next codePart after {38,48} is the color code.
|
||||
p != 5 || i == 0 || (arr[i - 1] != 38 && arr[i - 1] != 48),
|
||||
);
|
||||
|
||||
let nextStyleKey: styleKey | null = null;
|
||||
codeParts.forEach((codePart) => {
|
||||
/* eslint-disable yoda */
|
||||
if (nextStyleKey !== null) {
|
||||
style[nextStyleKey] = ansi2rgb(codePart);
|
||||
nextStyleKey = null;
|
||||
}
|
||||
// Decorations
|
||||
else if (codePart == 1) {
|
||||
style.fontWeight = "bold";
|
||||
} else if (codePart == 4) {
|
||||
style.textDecoration = "underline";
|
||||
}
|
||||
// Forground Color (x8)
|
||||
else if (30 <= codePart && codePart < 38) {
|
||||
if (COLOR_MAP_BRIGHT[codePart % 10]) {
|
||||
style.color = COLOR_MAP_BRIGHT[codePart % 10];
|
||||
}
|
||||
}
|
||||
// Background Color (x8)
|
||||
else if (40 <= codePart && codePart < 48) {
|
||||
if (COLOR_MAP_DARK[codePart % 10]) {
|
||||
style.backgroundColor = COLOR_MAP_DARK[codePart % 10];
|
||||
}
|
||||
}
|
||||
// Forground Color (x256)
|
||||
else if (codePart == 38) {
|
||||
nextStyleKey = "color";
|
||||
}
|
||||
// Background Color (x256)
|
||||
else if (codePart == 48) {
|
||||
nextStyleKey = "backgroundColor";
|
||||
}
|
||||
});
|
||||
// If a background color is set, render this as an inline block element (instead of inline)
|
||||
// so that the background between lines (at least those that don't wrap) is uninterrupted.
|
||||
if (style.backgroundColor !== undefined) {
|
||||
style.display = "inline-block";
|
||||
}
|
||||
return style;
|
||||
}
|
@ -19,6 +19,7 @@ import { findRunningScript } from "../../Script/ScriptHelpers";
|
||||
import { Player } from "../../Player";
|
||||
import { debounce } from "lodash";
|
||||
import { Settings } from "../../Settings/Settings";
|
||||
import { ANSIITypography } from "./ANSIITypography";
|
||||
|
||||
let layerCounter = 0;
|
||||
|
||||
@ -185,20 +186,20 @@ function LogWindow(props: IProps): React.ReactElement {
|
||||
setMinimized(!minimized);
|
||||
}
|
||||
|
||||
function lineColor(s: string): string {
|
||||
function lineColor(s: string): "error" | "success" | "warn" | "info" | "primary" {
|
||||
if (s.match(/(^\[[^\]]+\] )?ERROR/) || s.match(/(^\[[^\]]+\] )?FAIL/)) {
|
||||
return Settings.theme.error;
|
||||
return "error";
|
||||
}
|
||||
if (s.match(/(^\[[^\]]+\] )?SUCCESS/)) {
|
||||
return Settings.theme.success;
|
||||
return "success";
|
||||
}
|
||||
if (s.match(/(^\[[^\]]+\] )?WARN/)) {
|
||||
return Settings.theme.warning;
|
||||
return "warn";
|
||||
}
|
||||
if (s.match(/(^\[[^\]]+\] )?INFO/)) {
|
||||
return Settings.theme.info;
|
||||
return "info";
|
||||
}
|
||||
return Settings.theme.primary;
|
||||
return "primary";
|
||||
}
|
||||
|
||||
// And trigger fakeDrag when the window is resized
|
||||
@ -319,10 +320,9 @@ function LogWindow(props: IProps): React.ReactElement {
|
||||
<span style={{ display: "flex", flexDirection: "column" }}>
|
||||
{script.logs.map(
|
||||
(line: string, i: number): JSX.Element => (
|
||||
<Typography key={i} sx={{ color: lineColor(line) }}>
|
||||
{line}
|
||||
<br />
|
||||
</Typography>
|
||||
<React.Fragment key={i}>
|
||||
<ANSIITypography text={line} color={lineColor(line)} />
|
||||
</React.Fragment>
|
||||
),
|
||||
)}
|
||||
</span>
|
||||
|
Loading…
Reference in New Issue
Block a user