mirror of
https://github.com/bitburner-official/bitburner-src.git
synced 2025-03-07 19:14:37 +01:00
Merge branch 'dev' into dev
This commit is contained in:
32
dist/vendor.bundle.js
vendored
32
dist/vendor.bundle.js
vendored
File diff suppressed because one or more lines are too long
@ -3,6 +3,57 @@
|
||||
Changelog
|
||||
=========
|
||||
|
||||
v0.57.0 - 2021-10-16 It was too cheap! (hydroflame & community)
|
||||
-------------------------------------------
|
||||
|
||||
** BREAKING (kindof) **
|
||||
|
||||
* purchased server cost now scales exponentially past 2^10.
|
||||
I'm going to actually explain this one: Currently the cost of a 2^20GB server is 57b
|
||||
Most players can get that before their first install. In an effort to nerf good players
|
||||
a softcap was added. This softcap is different for every BN.
|
||||
|
||||
** Script Editor **
|
||||
|
||||
* Added a theme that is close to monokai. Unfortunately a full monokai is impossible because
|
||||
Monaco doesn't have a very good tokenizer.
|
||||
* Opening a file and connecting to a new server will still save the file on the server that the file
|
||||
was opened.
|
||||
|
||||
** Netscript **
|
||||
|
||||
* New function: alert, which creates a textbox.
|
||||
* New function: toast, creates a notification in the bottom right.
|
||||
* New function: upgradeHomeCores (@Saynt_Garmo)
|
||||
* New function: atExit, allows you to set a callback for when the script closes.
|
||||
* New kindof function: autocomplete, this allows you to tell the game what it should
|
||||
autocomplete on the terminal.
|
||||
|
||||
** Augmentation **
|
||||
|
||||
* ENM Core (the Augmentation from The Black Hand with the highest rep cost) rep cost
|
||||
reduced from 250 to 175. This will help new players transition from TBH to BitRunners more easily.
|
||||
|
||||
** Bladeburner **
|
||||
|
||||
* New general action: Incite Violence. This action adds other action counts but increases chaos.
|
||||
|
||||
** Misc. **
|
||||
|
||||
* Current bladeburner action is shown on the character overview.
|
||||
* Fix blackop being #000 on #000.
|
||||
* The last clicked Tail Box goes in front of the others.
|
||||
* Fixed an issue where some values were loaded as 0 when they should be null.
|
||||
* Implemented toasts.
|
||||
* .msg are no longer saved in the text file.
|
||||
* Tail boxes no longer display all the args, they use "..." after 30 characters.
|
||||
* Fixed cancelation penalty bonus not being properly applied after the IP <-> hostname switch.
|
||||
* Fixed an exploit where you could send non-strings or numbers to other scripts.
|
||||
* Fixed issue when trying to work for a faction with a work type that doesn't exist while
|
||||
already working for that faction.
|
||||
* Fixed not being able to work for the CIA. (Don't ask)
|
||||
* nerf noodle bar
|
||||
|
||||
v0.56.0 - 2021-10-11 Trimming the backlog (hydroflame & community)
|
||||
-------------------------------------------
|
||||
|
||||
|
@ -64,9 +64,9 @@ documentation_title = '{0} Documentation'.format(project)
|
||||
# built documents.
|
||||
#
|
||||
# The short X.Y version.
|
||||
version = '0.56'
|
||||
version = '0.57'
|
||||
# The full version, including alpha/beta/rc tags.
|
||||
release = '0.56.0'
|
||||
release = '0.57.0'
|
||||
|
||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||
# for a list of supported languages.
|
||||
|
@ -1,13 +1,13 @@
|
||||
autocomplete() Netscript Function
|
||||
============================
|
||||
|
||||
.. warning:: This feature is not officially supported yet and the API might change.
|
||||
.. warning:: This feature is not officially supported yet and the API might change. It is also only supported in ns2
|
||||
|
||||
.. js:function:: autocomplete(data, args)
|
||||
|
||||
:RAM cost: 0 GB
|
||||
:param Object data: general data about the game you might want to autocomplete.
|
||||
:param string[] args: current arguments.
|
||||
:param string[] args: current arguments. Minus `run script.ns`
|
||||
|
||||
data is an object with the following properties::
|
||||
|
||||
@ -15,7 +15,10 @@ autocomplete() Netscript Function
|
||||
servers: list of all servers in the game.
|
||||
txts: list of all text files on the current server.
|
||||
scripts: list of all scripts on the current server.
|
||||
flags: the same flags function as passed with ns. Calling this function adds all the flags as autocomplete arguments
|
||||
}
|
||||
|
||||
This function is special as it must be declared as a top level function like `main`.
|
||||
|
||||
Example:
|
||||
|
||||
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -567,6 +567,7 @@ export function initBitNodeMultipliers(p: IPlayer): void {
|
||||
BitNodeMultipliers.FactionWorkRepGain = 0.5;
|
||||
BitNodeMultipliers.FactionPassiveRepGain = 0;
|
||||
BitNodeMultipliers.GangKarmaRequirement = 0;
|
||||
BitNodeMultipliers.PurchasedServerSoftcap = 1.4;
|
||||
break;
|
||||
case 3: // Corporatocracy
|
||||
BitNodeMultipliers.HackingLevelMultiplier = 0.8;
|
||||
@ -583,6 +584,7 @@ export function initBitNodeMultipliers(p: IPlayer): void {
|
||||
BitNodeMultipliers.HomeComputerRamCost = 1.5;
|
||||
BitNodeMultipliers.PurchasedServerCost = 2;
|
||||
BitNodeMultipliers.GangKarmaRequirement = 3;
|
||||
BitNodeMultipliers.PurchasedServerSoftcap = 1.4;
|
||||
break;
|
||||
case 4: // The Singularity
|
||||
BitNodeMultipliers.ServerMaxMoney = 0.15;
|
||||
@ -597,6 +599,7 @@ export function initBitNodeMultipliers(p: IPlayer): void {
|
||||
BitNodeMultipliers.HackExpGain = 0.4;
|
||||
BitNodeMultipliers.CrimeExpGain = 0.5;
|
||||
BitNodeMultipliers.FactionWorkRepGain = 0.75;
|
||||
BitNodeMultipliers.PurchasedServerSoftcap = 1.3;
|
||||
break;
|
||||
case 5: // Artificial intelligence
|
||||
BitNodeMultipliers.ServerMaxMoney = 2;
|
||||
@ -610,6 +613,7 @@ export function initBitNodeMultipliers(p: IPlayer): void {
|
||||
BitNodeMultipliers.AugmentationMoneyCost = 2;
|
||||
BitNodeMultipliers.HackExpGain = 0.5;
|
||||
BitNodeMultipliers.CorporationValuation = 0.5;
|
||||
BitNodeMultipliers.PurchasedServerSoftcap = 1.3;
|
||||
break;
|
||||
case 6: // Bladeburner
|
||||
BitNodeMultipliers.HackingLevelMultiplier = 0.35;
|
||||
@ -626,6 +630,7 @@ export function initBitNodeMultipliers(p: IPlayer): void {
|
||||
BitNodeMultipliers.HackExpGain = 0.25;
|
||||
BitNodeMultipliers.DaedalusAugsRequirement = 1.166; // Results in 35 Augs needed
|
||||
BitNodeMultipliers.GangKarmaRequirement = 5;
|
||||
BitNodeMultipliers.PurchasedServerSoftcap = 2;
|
||||
break;
|
||||
case 7: // Bladeburner 2079
|
||||
BitNodeMultipliers.BladeburnerRank = 0.6;
|
||||
@ -647,6 +652,7 @@ export function initBitNodeMultipliers(p: IPlayer): void {
|
||||
BitNodeMultipliers.FourSigmaMarketDataApiCost = 2;
|
||||
BitNodeMultipliers.DaedalusAugsRequirement = 1.166; // Results in 35 Augs needed
|
||||
BitNodeMultipliers.GangKarmaRequirement = 5;
|
||||
BitNodeMultipliers.PurchasedServerSoftcap = 2;
|
||||
break;
|
||||
case 8: // Ghost of Wall Street
|
||||
BitNodeMultipliers.ScriptHackMoney = 0.3;
|
||||
@ -660,6 +666,7 @@ export function initBitNodeMultipliers(p: IPlayer): void {
|
||||
BitNodeMultipliers.CorporationValuation = 0;
|
||||
BitNodeMultipliers.CodingContractMoney = 0;
|
||||
BitNodeMultipliers.GangKarmaRequirement = 10;
|
||||
BitNodeMultipliers.PurchasedServerSoftcap = 5;
|
||||
break;
|
||||
case 9: // Hacktocracy
|
||||
BitNodeMultipliers.HackingLevelMultiplier = 0.4;
|
||||
@ -706,6 +713,7 @@ export function initBitNodeMultipliers(p: IPlayer): void {
|
||||
BitNodeMultipliers.PurchasedServerMaxRam = 0.5;
|
||||
BitNodeMultipliers.BladeburnerRank = 0.8;
|
||||
BitNodeMultipliers.GangKarmaRequirement = 3;
|
||||
BitNodeMultipliers.PurchasedServerSoftcap = 1.2;
|
||||
break;
|
||||
case 11: //The Big Crash
|
||||
BitNodeMultipliers.HackingLevelMultiplier = 0.5;
|
||||
@ -724,6 +732,7 @@ export function initBitNodeMultipliers(p: IPlayer): void {
|
||||
BitNodeMultipliers.CodingContractMoney = 0.25;
|
||||
BitNodeMultipliers.FourSigmaMarketDataCost = 4;
|
||||
BitNodeMultipliers.FourSigmaMarketDataApiCost = 4;
|
||||
BitNodeMultipliers.PurchasedServerSoftcap = 2.2;
|
||||
break;
|
||||
case 12: {
|
||||
//The Recursion
|
||||
@ -760,6 +769,7 @@ export function initBitNodeMultipliers(p: IPlayer): void {
|
||||
BitNodeMultipliers.PurchasedServerCost = inc;
|
||||
BitNodeMultipliers.PurchasedServerLimit = dec;
|
||||
BitNodeMultipliers.PurchasedServerMaxRam = dec;
|
||||
BitNodeMultipliers.PurchasedServerSoftcap = inc;
|
||||
|
||||
BitNodeMultipliers.ManualHackMoney = dec;
|
||||
BitNodeMultipliers.ScriptHackMoney = dec;
|
||||
|
@ -156,6 +156,11 @@ interface IBitNodeMultipliers {
|
||||
*/
|
||||
PurchasedServerCost: number;
|
||||
|
||||
/**
|
||||
* Influence how much it costs to purchase a server
|
||||
*/
|
||||
PurchasedServerSoftcap: number;
|
||||
|
||||
/**
|
||||
* Influences the maximum number of purchased servers you can have
|
||||
*/
|
||||
@ -237,6 +242,7 @@ export const BitNodeMultipliers: IBitNodeMultipliers = {
|
||||
HomeComputerRamCost: 1,
|
||||
|
||||
PurchasedServerCost: 1,
|
||||
PurchasedServerSoftcap: 1,
|
||||
PurchasedServerLimit: 1,
|
||||
PurchasedServerMaxRam: 1,
|
||||
|
||||
|
@ -339,7 +339,7 @@ export class Bladeburner implements IBladeburner {
|
||||
action.type = ActionTypes["Hyperbolic Regeneration Chamber"];
|
||||
action.name = "Hyperbolic Regeneration Chamber";
|
||||
break;
|
||||
case "stir trouble":
|
||||
case "incite violence":
|
||||
action.type = ActionTypes["Incite Violence"];
|
||||
action.name = "Incite Violence";
|
||||
break;
|
||||
@ -1503,16 +1503,18 @@ export class Bladeburner implements IBladeburner {
|
||||
for (const contract of Object.keys(this.contracts)) {
|
||||
const growthF = Growths[contract];
|
||||
if (!growthF) throw new Error("trying to generate count for action that doesn't exist? " + contract);
|
||||
this.contracts[contract].count += (60 * 3 * growthF()) / BladeburnerConstants.ActionCountGrowthPeriod;
|
||||
this.contracts[contract].count += (60 * 6 * growthF()) / BladeburnerConstants.ActionCountGrowthPeriod;
|
||||
}
|
||||
for (const operation of Object.keys(this.operations)) {
|
||||
const growthF = Growths[operation];
|
||||
if (!growthF) throw new Error("trying to generate count for action that doesn't exist? " + operation);
|
||||
this.operations[operation].count += (60 * 3 * growthF()) / BladeburnerConstants.ActionCountGrowthPeriod;
|
||||
this.operations[operation].count += (60 * 6 * growthF()) / BladeburnerConstants.ActionCountGrowthPeriod;
|
||||
}
|
||||
if (this.logging.general) {
|
||||
this.log(`Incited violence in the synthoid communities.`);
|
||||
}
|
||||
const city = this.cities[this.city];
|
||||
city.chaos *= (city.chaos + 100) * 2;
|
||||
this.startAction(player, this.action);
|
||||
break;
|
||||
}
|
||||
|
@ -12,13 +12,13 @@ export const Growths: {
|
||||
["Stealth Retirement Operation"]: () => number;
|
||||
["Assassination"]: () => number;
|
||||
} = {
|
||||
Tracking: () => getRandomInt(5, 75) / 10,
|
||||
"Bounty Hunter": () => getRandomInt(5, 75) / 10,
|
||||
Retirement: () => getRandomInt(5, 75) / 10,
|
||||
Investigation: () => getRandomInt(10, 40) / 10,
|
||||
"Undercover Operation": () => getRandomInt(10, 40) / 10,
|
||||
"Sting Operation": () => getRandomInt(3, 40) / 10,
|
||||
Raid: () => getRandomInt(2, 40) / 10,
|
||||
"Stealth Retirement Operation": () => getRandomInt(1, 20) / 10,
|
||||
Assassination: () => getRandomInt(1, 20) / 10,
|
||||
Tracking: () => getRandomInt(5, 75) / 20,
|
||||
"Bounty Hunter": () => getRandomInt(5, 75) / 20,
|
||||
Retirement: () => getRandomInt(5, 75) / 20,
|
||||
Investigation: () => getRandomInt(10, 40) / 20,
|
||||
"Undercover Operation": () => getRandomInt(10, 40) / 20,
|
||||
"Sting Operation": () => getRandomInt(3, 40) / 20,
|
||||
Raid: () => getRandomInt(2, 40) / 20,
|
||||
"Stealth Retirement Operation": () => getRandomInt(1, 20) / 20,
|
||||
Assassination: () => getRandomInt(1, 20) / 20,
|
||||
};
|
||||
|
122
src/Constants.ts
122
src/Constants.ts
@ -114,7 +114,7 @@ export const CONSTANTS: {
|
||||
TotalNumBitNodes: number;
|
||||
LatestUpdate: string;
|
||||
} = {
|
||||
Version: "0.56.0",
|
||||
Version: "0.57.0",
|
||||
|
||||
// Speed (in ms) at which the main loop is updated
|
||||
_idleSpeed: 200,
|
||||
@ -281,107 +281,55 @@ export const CONSTANTS: {
|
||||
TotalNumBitNodes: 24,
|
||||
|
||||
LatestUpdate: `
|
||||
v0.56.0 - 2021-10-11 Trimming the backlog (hydroflame & community)
|
||||
v0.57.0 - 2021-10-16 It was too cheap! (hydroflame & community)
|
||||
-------------------------------------------
|
||||
|
||||
** BREAKING **
|
||||
** BREAKING (kindof) **
|
||||
|
||||
* The 'write' function is now async. This helps when making scripts that write scripts.
|
||||
* purchased server cost now scales exponentially past 2^10.
|
||||
I'm going to actually explain this one: Currently the cost of a 2^20GB server is 57b
|
||||
Most players can get that before their first install. In an effort to nerf good players
|
||||
a softcap was added. This softcap is different for every BN.
|
||||
|
||||
** Terminal **
|
||||
** Script Editor **
|
||||
|
||||
* 'grow' and 'weaken' have been added as terminal command. This should help player transition
|
||||
from commands to scripts. The tutorial also talks about it.
|
||||
* 'cp' command added
|
||||
* Improved performance by rate limiting refresh.
|
||||
|
||||
** IP vs Hostname **
|
||||
|
||||
* The game now uses hostname as primary key for it's servers (yeah believe it or not IPs were
|
||||
used until then). This has caused some issues with purchased servers (they couldn't be sold).
|
||||
You might need to soft reset for the game to fully convert itself.
|
||||
|
||||
** Sleeve **
|
||||
|
||||
* Fixed bug where they couldn't train at Volhaven.
|
||||
* No longer consume all bonus time at once, making it look buggy.
|
||||
|
||||
** SF9 **
|
||||
|
||||
* Now boosts hacknet production by 8/12/14%
|
||||
|
||||
** Hacknet Servers **
|
||||
|
||||
* production nerfed by 10%
|
||||
* Max money increase gets weaker above 10t max money
|
||||
|
||||
** Corporation **
|
||||
|
||||
* Warehouse tooltip now also displays the amount of space taken by products.
|
||||
* Changed research box completely to avoid dependency on Treant (Treant is a pita)
|
||||
* All textbox should accept MAX/MP case insensitive.
|
||||
* Fixed export popup not refreshing dropdowns correctly.
|
||||
* Fixed product mku becoming zero
|
||||
* Increased scaling of Wilson to avoid feedback loop.
|
||||
* Can no longer get in debt by buying real estate
|
||||
* Bonus time is consumed faster.
|
||||
* Added a theme that is close to monokai. Unfortunately a full monokai is impossible because
|
||||
Monaco doesn't have a very good tokenizer.
|
||||
* Opening a file and connecting to a new server will still save the file on the server that the file
|
||||
was opened.
|
||||
|
||||
** Netscript **
|
||||
|
||||
* isBusy takes bitverse and infiltration into account
|
||||
* hospitalize can't be called when in infiltration.
|
||||
* setToCommitCrime now accepts crime rough name instead of perfect name.
|
||||
* disableLog All now works for bladeburner functions.
|
||||
* Fixed netscript port for ns1.
|
||||
|
||||
* New function: alert, which creates a textbox.
|
||||
* New function: toast, creates a notification in the bottom right.
|
||||
* New function: upgradeHomeCores (@Saynt_Garmo)
|
||||
* New function: atExit, allows you to set a callback for when the script closes.
|
||||
* New kindof function: autocomplete, this allows you to tell the game what it should
|
||||
autocomplete on the terminal.
|
||||
|
||||
** Augmentation **
|
||||
|
||||
* Added augmentation to Ti Di Hui that removes penalty for being unfocused.
|
||||
* Neuroflux no longer appears in special factions.
|
||||
* ENM Core (the Augmentation from The Black Hand with the highest rep cost) rep cost
|
||||
reduced from 250 to 175. This will help new players transition from TBH to BitRunners more easily.
|
||||
|
||||
** Script Editor **
|
||||
** Bladeburner **
|
||||
|
||||
* Ram check is debounced instead of refreshed every second.
|
||||
* Added the vscode extension documentation to the game (it doesn't work well, thought)
|
||||
* Fixed issue where autocomplete list would grow forever
|
||||
* Added semi-monokai as theme.
|
||||
* Fixed issue where modifying filename would mess it up.
|
||||
* Font size can be changed now.
|
||||
|
||||
** Infiltration **
|
||||
|
||||
* Fixed issue where game controls would become unfocused.
|
||||
* New general action: Incite Violence. This action adds other action counts but increases chaos.
|
||||
|
||||
** Misc. **
|
||||
|
||||
* Fixed loader incorrectly assuming some null values are incorrect.
|
||||
* installBackdoor trigger Bitverse sequence
|
||||
* Some improvements to the theme editor
|
||||
* Improved documentation about where to learn javascript.
|
||||
* Added some instructions for contributors.
|
||||
* Fixed typo in corporation sell shares modal (@Saynt_Garmo)
|
||||
* Fixed pagination being black on black in Active Scripts
|
||||
* Create Script tab renamed to Script Editor
|
||||
* Fixed an issue where corp some textbox wouldn't update when changing city.
|
||||
* Fixed an issue where hacknet online time was always 0.
|
||||
* Netscript function prompt fixed.
|
||||
* Fixed miscalculation in growth.
|
||||
* Script with syntax errors will try to be a tad more helpful.
|
||||
* Corporations can no longer bribe bladeburners.
|
||||
* Augmentation Graphene Branchiblade renamed to Brachi, like the rest of them.
|
||||
* All ram is displayed in GB/TB/PB now.
|
||||
* Game now saves when saving a file, this can be turned off.
|
||||
* Several improvement to log window.
|
||||
* Bladeburner current action returns General type instead of the name of the action.
|
||||
* Bladeburner travel and Sleeve travel respect disable ASCII.
|
||||
* Tutorial fits on small screens.
|
||||
* Import is much slower but more consistent now.
|
||||
* Fix intelligence not updating properly.
|
||||
* Added SF -1: Time Compression
|
||||
* ReadTheDoc theme now matches the game.
|
||||
* Logbox should wrap text better
|
||||
* Logbox behavior should feel better.
|
||||
* Fix font for AutoLink.exe
|
||||
* Current bladeburner action is shown on the character overview.
|
||||
* Fix blackop being #000 on #000.
|
||||
* The last clicked Tail Box goes in front of the others.
|
||||
* Fixed an issue where some values were loaded as 0 when they should be null.
|
||||
* Implemented toasts.
|
||||
* .msg are no longer saved in the text file.
|
||||
* Tail boxes no longer display all the args, they use "..." after 30 characters.
|
||||
* Fixed cancelation penalty bonus not being properly applied after the IP <-> hostname switch.
|
||||
* Fixed an exploit where you could send non-strings or numbers to other scripts.
|
||||
* Fixed issue when trying to work for a faction with a work type that doesn't exist while
|
||||
already working for that faction.
|
||||
* Fixed not being able to work for the CIA. (Don't ask)
|
||||
* nerf noodle bar
|
||||
`,
|
||||
};
|
||||
|
@ -646,6 +646,11 @@ export function runScriptFromScript(
|
||||
return 0;
|
||||
}
|
||||
|
||||
args = args.map((arg) => {
|
||||
if (typeof arg === "number") return arg;
|
||||
return arg + ""; // force cast to string
|
||||
});
|
||||
|
||||
// Check if the script is already running
|
||||
const runningScriptObj = server.getRunningScript(scriptname, args);
|
||||
if (runningScriptObj != null) {
|
||||
|
@ -58,6 +58,7 @@ import { Reputation } from "../../ui/React/Reputation";
|
||||
import { Money } from "../../ui/React/Money";
|
||||
|
||||
import React from "react";
|
||||
import { serverMetadata } from "../../Server/data/servers";
|
||||
|
||||
export function init(this: IPlayer): void {
|
||||
/* Initialize Player's home computer */
|
||||
@ -515,6 +516,7 @@ export function resetWorkStatus(this: IPlayer, generalType?: string, group?: str
|
||||
this.currentWorkFactionDescription = "";
|
||||
this.createProgramName = "";
|
||||
this.className = "";
|
||||
this.workType = "";
|
||||
}
|
||||
|
||||
export function processWorkEarnings(this: IPlayer, numCycles = 1): void {
|
||||
@ -606,7 +608,9 @@ export function process(this: IPlayer, router: IRouter, numCycles = 1): void {
|
||||
}
|
||||
|
||||
export function cancelationPenalty(this: IPlayer): number {
|
||||
const server = GetServer(this.companyName);
|
||||
const data = serverMetadata.find((s) => s.specialName === this.companyName);
|
||||
if (!data) return 0.5; // Does not have special server.
|
||||
const server = GetServer(data.hostname);
|
||||
if (server instanceof Server) {
|
||||
if (server && server.backdoorInstalled) return 0.75;
|
||||
}
|
||||
@ -2655,9 +2659,12 @@ export function setMult(this: IPlayer, name: string, mult: number): void {
|
||||
(this as any)[name] = mult;
|
||||
}
|
||||
|
||||
export function sourceFileLvl(this: IPlayer, n: number): number {
|
||||
for (const sf of this.sourceFiles) {
|
||||
if (sf.n === n) return sf.lvl;
|
||||
}
|
||||
return 0;
|
||||
export function canAccessCotMG(this: IPlayer): boolean {
|
||||
return this.bitNodeN === 13 || SourceFileFlags[13] > 0;
|
||||
}
|
||||
|
||||
export function sourceFileLvl(this: IPlayer, n: number): number {
|
||||
const sf = this.sourceFiles.find((sf) => sf.n === n);
|
||||
if (!sf) return 0;
|
||||
return sf.lvl;
|
||||
}
|
||||
|
@ -55,12 +55,13 @@ export function SetupTextEditor(): void {
|
||||
symbols = populate(ns);
|
||||
|
||||
const exclude = ["heart", "break", "exploit", "bypass", "corporation"];
|
||||
symbols = symbols.filter((symbol: string) => !exclude.includes(symbol));
|
||||
symbols = symbols.filter((symbol: string) => !exclude.includes(symbol)).sort();
|
||||
}
|
||||
|
||||
interface IProps {
|
||||
filename: string;
|
||||
code: string;
|
||||
hostname: string;
|
||||
player: IPlayer;
|
||||
router: IRouter;
|
||||
}
|
||||
@ -75,17 +76,23 @@ interface IProps {
|
||||
// https://www.npmjs.com/package/@monaco-editor/react#development-playground
|
||||
// https://microsoft.github.io/monaco-editor/playground.html#extending-language-services-custom-languages
|
||||
// https://github.com/threehams/typescript-error-guide/blob/master/stories/components/Editor.tsx#L11-L39
|
||||
// https://blog.checklyhq.com/customizing-monaco/
|
||||
|
||||
// These variables are used to reload a script when it's clicked on. Because we
|
||||
// won't have references to the old script.
|
||||
let lastFilename = "";
|
||||
let lastCode = "";
|
||||
let hostname = "";
|
||||
let lastPosition: monaco.Position | null = null;
|
||||
|
||||
export function Root(props: IProps): React.ReactElement {
|
||||
const editorRef = useRef<IStandaloneCodeEditor | null>(null);
|
||||
const [filename, setFilename] = useState(props.filename ? props.filename : lastFilename);
|
||||
const [code, setCode] = useState<string>(props.filename ? props.code : lastCode);
|
||||
hostname = props.filename ? props.hostname : hostname;
|
||||
if (hostname === "") {
|
||||
hostname = props.player.getCurrentServer().hostname;
|
||||
}
|
||||
const [ram, setRAM] = useState("RAM: ???");
|
||||
const [updatingRam, setUpdatingRam] = useState(false);
|
||||
const [optionsOpen, setOptionsOpen] = useState(false);
|
||||
@ -128,7 +135,7 @@ export function Root(props: IProps): React.ReactElement {
|
||||
if (ITutorial.isRunning && ITutorial.currStep === iTutorialSteps.TerminalTypeScript) {
|
||||
//Make sure filename + code properly follow tutorial
|
||||
if (filename !== "n00dles.script") {
|
||||
dialogBoxCreate("Leave the script name as 'n00dles'!");
|
||||
dialogBoxCreate("Leave the script name as 'n00dles.script'!");
|
||||
return;
|
||||
}
|
||||
if (code.replace(/\s/g, "").indexOf("while(true){hack('n00dles');}") == -1) {
|
||||
@ -142,14 +149,14 @@ export function Root(props: IProps): React.ReactElement {
|
||||
let found = false;
|
||||
for (let i = 0; i < server.scripts.length; i++) {
|
||||
if (filename == server.scripts[i].filename) {
|
||||
server.scripts[i].saveScript(filename, code, props.player.currentServer, server.scripts);
|
||||
server.scripts[i].saveScript(filename, code, hostname, server.scripts);
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
const script = new Script();
|
||||
script.saveScript(filename, code, props.player.currentServer, server.scripts);
|
||||
script.saveScript(filename, code, hostname, server.scripts);
|
||||
server.scripts.push(script);
|
||||
}
|
||||
|
||||
@ -311,6 +318,21 @@ export function Root(props: IProps): React.ReactElement {
|
||||
return { suggestions: suggestions };
|
||||
},
|
||||
});
|
||||
(async function () {
|
||||
// We have to improve the default js language otherwise theme sucks
|
||||
const l = await monaco.languages
|
||||
.getLanguages()
|
||||
.find((l: any) => l.id === "javascript")
|
||||
.loader();
|
||||
l.language.tokenizer.root.unshift(["ns", { token: "ns" }]);
|
||||
for (const symbol of symbols) l.language.tokenizer.root.unshift(["\\." + symbol, { token: "netscriptfunction" }]);
|
||||
const otherKeywords = ["let", "const", "var", "function"];
|
||||
const otherKeyvars = ["true", "false", "null", "undefined"];
|
||||
otherKeywords.forEach((k) => l.language.tokenizer.root.unshift([k, { token: "otherkeywords" }]));
|
||||
otherKeyvars.forEach((k) => l.language.tokenizer.root.unshift([k, { token: "otherkeyvars" }]));
|
||||
l.language.tokenizer.root.unshift(["this", { token: "this" }]);
|
||||
})();
|
||||
|
||||
monaco.languages.typescript.javascriptDefaults.addExtraLib(libSource, "netscript.d.ts");
|
||||
monaco.languages.typescript.typescriptDefaults.addExtraLib(libSource, "netscript.d.ts");
|
||||
loadThemes(monaco);
|
||||
@ -322,11 +344,12 @@ export function Root(props: IProps): React.ReactElement {
|
||||
<>
|
||||
<Box display="flex" flexDirection="row" alignItems="center">
|
||||
<TextField
|
||||
placeholder="filename"
|
||||
type="text"
|
||||
tabIndex={1}
|
||||
value={filename}
|
||||
onChange={onFilenameChange}
|
||||
InputProps={{ startAdornment: <Typography>Script name: </Typography> }}
|
||||
InputProps={{ startAdornment: <Typography>{hostname}:~/</Typography> }}
|
||||
/>
|
||||
<IconButton onClick={() => setOptionsOpen(true)}>
|
||||
<>
|
||||
|
@ -19,6 +19,10 @@ export async function loadThemes(monaco: { editor: any }): Promise<void> {
|
||||
token: "number",
|
||||
foreground: "ae81ff",
|
||||
},
|
||||
{
|
||||
token: "otherkeyvars",
|
||||
foreground: "ae81ff",
|
||||
},
|
||||
{
|
||||
foreground: "ae81ff",
|
||||
token: "function",
|
||||
@ -31,11 +35,22 @@ export async function loadThemes(monaco: { editor: any }): Promise<void> {
|
||||
token: "storage.type.function.js",
|
||||
foreground: "ae81ff",
|
||||
},
|
||||
|
||||
// {
|
||||
// foreground: "ae81ff",
|
||||
// token: "entity.name.function",
|
||||
// },
|
||||
{
|
||||
token: "ns",
|
||||
foreground: "97d92b",
|
||||
},
|
||||
{
|
||||
token: "netscriptfunction",
|
||||
foreground: "53d3e4",
|
||||
},
|
||||
{
|
||||
token: "otherkeywords",
|
||||
foreground: "53d3e4",
|
||||
},
|
||||
{
|
||||
token: "this",
|
||||
foreground: "fd971f",
|
||||
},
|
||||
],
|
||||
colors: {
|
||||
"editor.foreground": "#F8F8F2",
|
||||
|
@ -2,7 +2,6 @@
|
||||
* Abstract Base Class for any Server object
|
||||
*/
|
||||
import { CodingContract } from "../CodingContracts";
|
||||
import { Message } from "../Message/Message";
|
||||
import { RunningScript } from "../Script/RunningScript";
|
||||
import { Script } from "../Script/Script";
|
||||
import { isValidFilePath } from "../Terminal/DirectoryHelpers";
|
||||
|
@ -28,7 +28,14 @@ export function getPurchaseServerCost(ram: number): number {
|
||||
return Infinity;
|
||||
}
|
||||
|
||||
return sanitizedRam * CONSTANTS.BaseCostFor1GBOfRamServer * BitNodeMultipliers.PurchasedServerCost;
|
||||
const upg = Math.max(0, Math.log(sanitizedRam) / Math.log(2) - 9);
|
||||
|
||||
return (
|
||||
sanitizedRam *
|
||||
CONSTANTS.BaseCostFor1GBOfRamServer *
|
||||
BitNodeMultipliers.PurchasedServerCost *
|
||||
Math.pow(BitNodeMultipliers.PurchasedServerSoftcap, upg)
|
||||
);
|
||||
}
|
||||
|
||||
export function getPurchaseServerLimit(): number {
|
||||
|
@ -239,7 +239,7 @@ export const Settings: ISettings & ISelfInitializer & ISelfLoading = {
|
||||
SuppressMessages: defaultSettings.SuppressMessages,
|
||||
SuppressTravelConfirmation: defaultSettings.SuppressTravelConfirmation,
|
||||
SuppressBladeburnerPopup: defaultSettings.SuppressBladeburnerPopup,
|
||||
MonacoTheme: "vs-dark",
|
||||
MonacoTheme: "monokai",
|
||||
MonacoInsertSpaces: false,
|
||||
MonacoFontSize: 20,
|
||||
|
||||
|
@ -215,7 +215,7 @@ export function TerminalInput({ terminal, router, player }: IProps): React.React
|
||||
|
||||
let newValue = tabCompletion(command, arg, allPos, value);
|
||||
if (typeof newValue === "string" && newValue !== "") {
|
||||
if (!newValue.endsWith(" ") && allPos.length === 1) newValue += " ";
|
||||
if (!newValue.endsWith(" ") && !newValue.endsWith("/") && allPos.length === 1) newValue += " ";
|
||||
saveValue(newValue);
|
||||
}
|
||||
if (Array.isArray(newValue)) {
|
||||
|
@ -305,7 +305,13 @@ export function GameRoot({ player, engine, terminal }: IProps): React.ReactEleme
|
||||
) : page === Page.Stats ? (
|
||||
<CharacterStats />
|
||||
) : page === Page.ScriptEditor ? (
|
||||
<ScriptEditorRoot filename={filename} code={code} player={player} router={Router} />
|
||||
<ScriptEditorRoot
|
||||
filename={filename}
|
||||
code={code}
|
||||
hostname={player.getCurrentServer().hostname}
|
||||
player={player}
|
||||
router={Router}
|
||||
/>
|
||||
) : page === Page.ActiveScripts ? (
|
||||
<ActiveScriptsRoot workerScripts={workerScripts} />
|
||||
) : page === Page.Hacknet ? (
|
||||
|
@ -88,7 +88,6 @@ function LogWindow(props: IProps): React.ReactElement {
|
||||
killWorkerScript(props.script, props.script.server, true);
|
||||
props.onClose();
|
||||
}
|
||||
//useEffect(() => TerminalEvents.subscribe(_.debounce(async () => rerender(), 25, { maxWait: 50 })), []);
|
||||
|
||||
function updateLayer(): void {
|
||||
const c = container.current;
|
||||
@ -98,6 +97,15 @@ function LogWindow(props: IProps): React.ReactElement {
|
||||
rerender();
|
||||
}
|
||||
|
||||
function title(): string {
|
||||
const maxLength = 30;
|
||||
const t = `${props.script.filename} ${props.script.args.map((x: any): string => `${x}`).join(" ")}`;
|
||||
if (t.length <= maxLength) {
|
||||
return t;
|
||||
}
|
||||
return t.slice(0, maxLength - 3) + "...";
|
||||
}
|
||||
|
||||
return (
|
||||
<Draggable handle=".drag">
|
||||
<Paper
|
||||
@ -119,7 +127,7 @@ function LogWindow(props: IProps): React.ReactElement {
|
||||
>
|
||||
<Box className="drag" display="flex" alignItems="center">
|
||||
<Typography color="primary" variant="h6">
|
||||
{props.script.filename} {props.script.args.map((x: any): string => `${x}`).join(" ")}
|
||||
{title()}
|
||||
</Typography>
|
||||
|
||||
<Box position="absolute" right={0}>
|
||||
|
@ -302,7 +302,7 @@ export function refreshTheme(): void {
|
||||
border: "1px solid " + Settings.theme.well,
|
||||
},
|
||||
standardSuccess: {
|
||||
color: Settings.theme.successLight,
|
||||
color: Settings.theme.primaryLight,
|
||||
},
|
||||
standardError: {
|
||||
color: Settings.theme.errorlight,
|
||||
|
@ -361,5 +361,7 @@ export function WorkInProgressRoot(): React.ReactElement {
|
||||
);
|
||||
}
|
||||
|
||||
if (!player.workType) router.toTerminal();
|
||||
|
||||
return <></>;
|
||||
}
|
||||
|
Reference in New Issue
Block a user