mirror of
https://github.com/bitburner-official/bitburner-src.git
synced 2025-01-11 15:57:33 +01:00
Added BitNode multipliers for purchased servers. Fixed bugs in new Script Editor implementation. Added documentation for script editors
This commit is contained in:
parent
d54f0906f0
commit
a09ea46a38
@ -6,7 +6,7 @@
|
||||
|
||||
#codemirror-form-wrapper {
|
||||
height: 80%;
|
||||
margin: 10px 0px 10px 6px;
|
||||
margin: 10px 0px 0px 6px;
|
||||
}
|
||||
|
||||
.CodeMirror {
|
||||
@ -29,7 +29,6 @@
|
||||
background-color: #8F908A;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Show Invisibles
|
||||
*/
|
||||
@ -38,3 +37,13 @@
|
||||
pointer-events: none;
|
||||
color: #404F7D;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vim command display
|
||||
*/
|
||||
#codemirror-vim-command-display-wrapper {
|
||||
background-color: white;
|
||||
font-size: 13px;
|
||||
height: 30px;
|
||||
margin-left: 6px;
|
||||
}
|
||||
|
@ -93,6 +93,7 @@
|
||||
overflow: auto;
|
||||
z-index: 1;
|
||||
color: #fff;
|
||||
max-height: 50%;
|
||||
}
|
||||
|
||||
#script-editor-options-panel fieldset {
|
||||
|
3284
dist/engine.bundle.js
vendored
3284
dist/engine.bundle.js
vendored
File diff suppressed because it is too large
Load Diff
14
dist/engine.css
vendored
14
dist/engine.css
vendored
@ -5,7 +5,7 @@
|
||||
*/
|
||||
#codemirror-form-wrapper {
|
||||
height: 80%;
|
||||
margin: 10px 0px 10px 6px; }
|
||||
margin: 10px 0px 0px 6px; }
|
||||
|
||||
.CodeMirror {
|
||||
height: 100%;
|
||||
@ -32,6 +32,15 @@
|
||||
pointer-events: none;
|
||||
color: #404F7D; }
|
||||
|
||||
/**
|
||||
* Vim command display
|
||||
*/
|
||||
#codemirror-vim-command-display-wrapper {
|
||||
background-color: white;
|
||||
font-size: 13px;
|
||||
height: 30px;
|
||||
margin-left: 6px; }
|
||||
|
||||
/* COLORS */
|
||||
/* Attributes */
|
||||
/* COLORS */
|
||||
@ -886,7 +895,8 @@ button {
|
||||
padding: 2px;
|
||||
overflow: auto;
|
||||
z-index: 1;
|
||||
color: #fff; }
|
||||
color: #fff;
|
||||
max-height: 50%; }
|
||||
|
||||
#script-editor-options-panel fieldset {
|
||||
margin-top: 8px;
|
||||
|
1855
dist/vendor.bundle.js
vendored
1855
dist/vendor.bundle.js
vendored
File diff suppressed because one or more lines are too long
29
dist/vendor.css
vendored
29
dist/vendor.css
vendored
@ -5383,6 +5383,35 @@ THE SOFTWARE.
|
||||
.cm-s-zenburn .CodeMirror-focused div.CodeMirror-selected {
|
||||
background: #4f4f4f; }
|
||||
|
||||
.CodeMirror-dialog {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
background: inherit;
|
||||
z-index: 15;
|
||||
padding: .1em .8em;
|
||||
overflow: hidden;
|
||||
color: inherit; }
|
||||
|
||||
.CodeMirror-dialog-top {
|
||||
border-bottom: 1px solid #eee;
|
||||
top: 0; }
|
||||
|
||||
.CodeMirror-dialog-bottom {
|
||||
border-top: 1px solid #eee;
|
||||
bottom: 0; }
|
||||
|
||||
.CodeMirror-dialog input {
|
||||
border: none;
|
||||
outline: none;
|
||||
background: transparent;
|
||||
width: 20em;
|
||||
color: inherit;
|
||||
font-family: monospace; }
|
||||
|
||||
.CodeMirror-dialog button {
|
||||
font-size: 70%; }
|
||||
|
||||
.CodeMirror-foldmarker {
|
||||
color: blue;
|
||||
text-shadow: #b9f 1px 1px 2px, #b9f -1px -1px 2px, #b9f 1px -1px 2px, #b9f -1px 1px 2px;
|
||||
|
@ -23,6 +23,7 @@ secrets that you've been searching for.
|
||||
Basic Gameplay <basicgameplay>
|
||||
Advanced Gameplay <advancedgameplay>
|
||||
Keyboard Shortcuts <shortcuts>
|
||||
Script Editors <scripteditors>
|
||||
Game Frozen or Stuck? <gamefrozen>
|
||||
Changelog <changelog>
|
||||
|
||||
|
140
doc/source/scripteditors.rst
Normal file
140
doc/source/scripteditors.rst
Normal file
@ -0,0 +1,140 @@
|
||||
.. _scripteditors:
|
||||
|
||||
Script Editors
|
||||
==============
|
||||
Third-party libraries are used to implement the game's Script Editor(s). There are
|
||||
currently two options for the Script Editor:
|
||||
|
||||
* `Ace <https://ace.c9.io/>`_
|
||||
* `CodeMirror <https://codemirror.net/>`_
|
||||
|
||||
You can select which of the two editors you want to use on the Script Editor page
|
||||
('Create Script' on the main menu).
|
||||
|
||||
Ace was the game's original Script Editor, while CodeMirror was added later in
|
||||
v0.43.0. The two editors share many of the same features, so there is not a significant
|
||||
difference between the two. Currently, CodeMirror is slightly more modern,
|
||||
more customizable, and has a few quality-of-life improvements compared to Ace.
|
||||
|
||||
Universal Key Bindings
|
||||
----------------------
|
||||
These keyboard shortcuts are available in both the Ace and CodeMirror editors, regardless
|
||||
of what key binding option you are using:
|
||||
|
||||
============= ===========================================================================
|
||||
Shortcut Action
|
||||
============= ===========================================================================
|
||||
Ctrl + b Save script and return to :ref:`terminal`
|
||||
Ctrl + space Show Autocomplete Hints
|
||||
============= ===========================================================================
|
||||
|
||||
.. _scripteditor_linter:
|
||||
|
||||
Linter
|
||||
------
|
||||
Both script editors contain a linter, which is a tool that analyzes your
|
||||
code and flags anything it thinks might be an error. You can see
|
||||
warnings and errors from the linter on the left-hand side of the script editor. There
|
||||
will be an icon on whatever lines the linter thinks might be problematic. Hovering
|
||||
over the icon will display information on what the issue is.
|
||||
|
||||
Note that **just because the linter shows an error/warning, this does NOT automatically mean that**
|
||||
**your script is broken and will fail to run.** This is especially true if you are using
|
||||
:ref:`netscriptjs`. The linter used by the script editors isn't necessarily perfect or
|
||||
up-to-date. Furthermore, the linter does not affect anything when you actually run scripts.
|
||||
|
||||
Ace
|
||||
---
|
||||
The following documents what the different settings/options do for the Ace editor,
|
||||
as well as the different key binding settings. Note that the
|
||||
information for the key bindings may not be completely comprehensive. You'll
|
||||
have to dig into the editor source code if you want to learn more.
|
||||
|
||||
Settings
|
||||
~~~~~~~~
|
||||
|
||||
===================== ===========================================================================================================
|
||||
Setting Effect
|
||||
===================== ===========================================================================================================
|
||||
Theme Switch between different color schemes
|
||||
Key Binding Switch between different key binding options. This changes what keyboard shortcuts are available
|
||||
Highlight Active Line When enabled, the line on which the cursor currently resides will be highlighted.
|
||||
Show Invisibles When enabled, you will be able to view hidden whitespace characters such as spaces, tabs, and newlines.
|
||||
Use Soft Tab When enabled, tabs will be replaced with spaces
|
||||
Max Error Count Specifies the (approximate) number of lines that will be linted
|
||||
===================== ===========================================================================================================
|
||||
|
||||
Ace Key Bindings
|
||||
~~~~~~~~~~~~~~~~
|
||||
For Ace, the "Ace" Key Binding setting uses the default configuration. A list of these
|
||||
`can be found here <https://github.com/ajaxorg/ace/wiki/Default-Keyboard-Shortcuts>`_.
|
||||
|
||||
Vim Key Bindings
|
||||
~~~~~~~~~~~~~~~~
|
||||
For Ace, the "Vim" Key Binding setting configures the editor to use
|
||||
`Vim <https://en.wikipedia.org/wiki/Vim_(text_editor)>`_ key mappings. Note that while this tries
|
||||
to emulate Vim features as faithfully as possible, it is not a complete Vim implementation.
|
||||
|
||||
Since I'm not familiar with Vim, I'll leave
|
||||
`Ace's Vim Mode implementation here <https://github.com/ajaxorg/ace/blob/96088d0fc292daf0706b2d029cc03c3799be5974/lib/ace/keyboard/vim.js#L860>`_,
|
||||
which I believe shows most of the implemented features.
|
||||
|
||||
Note that the following Vim Ex commands will properly save the script and/or quit the editor in game:
|
||||
|
||||
======= ==============================================
|
||||
Command Effect
|
||||
======= ==============================================
|
||||
:w Save the script and return to :ref:`terminal`
|
||||
:q Return to :ref:`terminal` **WITHOUT** saving
|
||||
:x Save the script and return to :ref:`terminal`
|
||||
:wq Save the script and return to :ref:`terminal`
|
||||
======= ==============================================
|
||||
|
||||
Emacs Key Bindings
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
For Ace, the "Emacs" Key Binding setting configures the editor to use
|
||||
`Emacs <https://en.wikipedia.org/wiki/Emacs>`_ key mappings. Note that while this tries
|
||||
to emulate the Emacs key mappings as faithfully as possible, it won't necessarily be a
|
||||
complete implementation.
|
||||
|
||||
Since I'm not familiar with Emacs, I'll leave
|
||||
`Ace's Emacs Mode implementation here <https://github.com/ajaxorg/ace/blob/96088d0fc292daf0706b2d029cc03c3799be5974/lib/ace/keyboard/emacs.js#L343>`_,
|
||||
which I believe shows most of the implemented features.
|
||||
|
||||
CodeMirror
|
||||
----------
|
||||
The following documents what the different settings/options do for the CodeMirror editor,
|
||||
as well as the shortcuts for the different key binding settings. Note that the
|
||||
information for the key bindings may not be completely comprehensive. You'll
|
||||
have to dig into the editor source code if you want to learn everything.
|
||||
|
||||
Settings
|
||||
~~~~~~~~
|
||||
========================== ===========================================================================================================
|
||||
Setting Effect
|
||||
========================== ===========================================================================================================
|
||||
Theme Switch between different color schemes
|
||||
Key Binding Switch between different key binding options. This changes what keyboard shortcuts are available
|
||||
Highlight Active Line When enabled, the line on which the cursor currently resides will be highlighted.
|
||||
Show Invisibles When enabled, you will be able to view hidden whitespace characters such as spaces, tabs, and newlines.
|
||||
Use Soft Tab When enabled, tabs will be replaced with spaces
|
||||
Auto-Close Brackets/Quotes When enabled, any opening brackets or quotes that are typed will be closed
|
||||
Enable Linting Enable/Disable the :ref:`scripteditor_linter`
|
||||
Continue Comments When enabled, pressing 'Enter' inside a comment block will continue the comment on the next line
|
||||
========================== ===========================================================================================================
|
||||
|
||||
Default Key Bindings
|
||||
~~~~~~~~~~~~~~~~~~~~
|
||||
.. todo:: Fill out
|
||||
|
||||
Sublime Key Bindings
|
||||
~~~~~~~~~~~~~~~~~~~~
|
||||
.. todo:: Fill out
|
||||
|
||||
Vim Key Bindings
|
||||
~~~~~~~~~~~~~~~~
|
||||
.. todo:: Fill out
|
||||
|
||||
Emacs Key Bindings
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
.. todo:: Fill out
|
@ -35,20 +35,7 @@ Alt + o Switch to 'Options' page
|
||||
|
||||
Script Editor
|
||||
-------------
|
||||
These shortcuts are available only in the Script Editor
|
||||
|
||||
============= ===========================================================================
|
||||
Shortcut Action
|
||||
============= ===========================================================================
|
||||
Ctrl + b Save script and return to :ref:`terminal`
|
||||
Ctrl + space Function autocompletion
|
||||
============= ===========================================================================
|
||||
|
||||
In the Script Editor you can configure your key binding mode to three preset options:
|
||||
|
||||
* `Ace <https://github.com/ajaxorg/ace/wiki/Default-Keyboard-Shortcuts>`_
|
||||
* Vim
|
||||
* Emacs
|
||||
See the :ref:`Script Editor <scripteditors>` documentation for more details.
|
||||
|
||||
Terminal Shortcuts
|
||||
------------------
|
||||
@ -92,10 +79,13 @@ Alt + f Move cursor to next word
|
||||
Ctrl + h/d Delete previous character ('Backspace')
|
||||
============= ===========================================================================
|
||||
|
||||
Misc Shortcuts
|
||||
--------------
|
||||
Popup/Dialog Box Shortcuts
|
||||
--------------------------
|
||||
The following shortcuts work if there are any popup or dialog boxes on the screen.
|
||||
|
||||
============= ===========================================================================
|
||||
Shortcut Action
|
||||
============= ===========================================================================
|
||||
Esc Close a script's log window
|
||||
Esc Close the current popup, cancelling any prompts on a dialog box
|
||||
Enter Clicks the "Yes/Confirm" option for every dialog box
|
||||
============= ===========================================================================
|
||||
|
@ -120,6 +120,9 @@
|
||||
|
||||
<div id="ace-editor"></div>
|
||||
<form id="codemirror-form-wrapper"><textarea id="codemirror-editor"></textarea></form>
|
||||
<div id="codemirror-vim-command-display-wrapper">
|
||||
Key Buffer: <span id="codemirror-vim-command-display"></span>
|
||||
</div>
|
||||
|
||||
<div id="script-editor-buttons-wrapper"></div> <!-- Buttons below script editor -->
|
||||
</div> <!-- End wrapper -->
|
||||
|
@ -168,6 +168,7 @@ function initBitNodes() {
|
||||
"In this BitNode:<br><br>" +
|
||||
"Your stats are significantly decreased.<br>" +
|
||||
"All methods of gaining money are half as profitable (except Stock Market)<br>" +
|
||||
"Purchased servers are more expensive, have less max RAM, and a lower maximum limit<br>" +
|
||||
"Augmentations are 5x as expensive and require twice as much reputation<br><br>" +
|
||||
"Destroying this BitNode will give you Source-File 10, or if you already have this Source-File it will " +
|
||||
"upgrade its level up to a maximum of 3. This Source-File unlocks Sleeve technology in other BitNodes. " +
|
||||
@ -337,6 +338,9 @@ function initBitNodeMultipliers() {
|
||||
BitNodeMultipliers.CorporationValuation = 0.5;
|
||||
BitNodeMultipliers.AugmentationMoneyCost = 5;
|
||||
BitNodeMultipliers.AugmentationRepCost = 2;
|
||||
BitNodeMultipliers.PurchasedServerCost = 5;
|
||||
BitNodeMultipliers.PurchasedServerLimit = 0.6;
|
||||
BitNodeMultipliers.PurchasedServerMaxRam = 0.5;
|
||||
case 11: //The Big Crash
|
||||
BitNodeMultipliers.ServerMaxMoney = 0.1;
|
||||
BitNodeMultipliers.ServerStartingMoney = 0.1;
|
||||
|
@ -125,6 +125,20 @@ interface IBitNodeMultipliers {
|
||||
*/
|
||||
ManualHackMoney: number;
|
||||
|
||||
/**
|
||||
* Influence how much it costs to purchase a server
|
||||
*/
|
||||
PurchasedServerCost: number;
|
||||
|
||||
/**
|
||||
* Influences the maximum number of purchased servers you can have
|
||||
*/
|
||||
PurchasedServerLimit: number;
|
||||
|
||||
/**
|
||||
* Influences the maximum allowed RAM for a purchased server
|
||||
*/
|
||||
PurchasedServerMaxRam: number;
|
||||
/**
|
||||
* Influences the minimum favor the player must have with a faction before they can donate to gain rep.
|
||||
*/
|
||||
@ -184,6 +198,10 @@ export const BitNodeMultipliers: IBitNodeMultipliers = {
|
||||
ServerStartingSecurity: 1,
|
||||
ServerWeakenRate: 1,
|
||||
|
||||
PurchasedServerCost: 1,
|
||||
PurchasedServerLimit: 1,
|
||||
PurchasedServerMaxRam: 1,
|
||||
|
||||
CompanyWorkMoney: 1,
|
||||
CrimeMoney: 1,
|
||||
HacknetNodeMoney: 1,
|
||||
|
@ -524,10 +524,11 @@ export let CONSTANTS: IMap<any> = {
|
||||
|
||||
* Script Editor Changes:
|
||||
** Added new script editor: CodeMirror. You can choose between the old editor (Ace) or CodeMirror
|
||||
** Navigation keyboard shortcuts no longer work on the script editor page
|
||||
** Navigation keyboard shortcuts no longer work if the script editor is focused
|
||||
|
||||
* Trying to programmatically run a script (run(), exec()) with a 'threads' argument of 0 will now cause the function to return false without running the script
|
||||
* Home Computer RAM is now capped at 2 ^ 30 GB (1073741824 GB)
|
||||
* The maximum amount, maximum RAM, and cost of purchasing servers can now vary between different BitNodes (new BitNode multipliers)
|
||||
* Pop-up dialog boxes are a little bit bigger
|
||||
* Bug Fix: When importing scripts, "./" will now be properly ignored (e.g. import { foo } from "./lib.script" )
|
||||
`
|
||||
|
@ -481,7 +481,7 @@ function createFactionAugmentationDisplayElements(augmentationsList, augs, facti
|
||||
}
|
||||
|
||||
var item = createElement("li");
|
||||
var span = createElement("span", {display:"inline-block"});
|
||||
var span = createElement("span", { display:"inline-block", margin: "4px", padding: "4px" });
|
||||
var aDiv = createElement("div", {tooltip:aug.info});
|
||||
var aElem = createElement("a", {
|
||||
innerText:aug.name, display:"inline",
|
||||
|
@ -1,10 +1,12 @@
|
||||
import {Engine} from "./engine";
|
||||
import {Player} from "./Player";
|
||||
import {Settings} from "./Settings/Settings";
|
||||
import {clearEventListeners} from "../utils/uiHelpers/clearEventListeners";
|
||||
import {createElement} from "../utils/uiHelpers/createElement";
|
||||
import {createPopup} from "../utils/uiHelpers/createPopup";
|
||||
import {removeElementById} from "../utils/uiHelpers/removeElementById";
|
||||
import { Engine } from "./engine";
|
||||
import { Player } from "./Player";
|
||||
import { Settings } from "./Settings/Settings";
|
||||
import { initializeMainMenuLinks } from "./ui/MainMenu/Links";
|
||||
import { exceptionAlert } from "../utils/helpers/exceptionAlert";
|
||||
import { clearEventListeners } from "../utils/uiHelpers/clearEventListeners";
|
||||
import { createElement } from "../utils/uiHelpers/createElement";
|
||||
import { createPopup } from "../utils/uiHelpers/createPopup";
|
||||
import { removeElementById } from "../utils/uiHelpers/removeElementById";
|
||||
|
||||
//Ordered array of keys to Interactive Tutorial Steps
|
||||
const orderedITutorialSteps = [
|
||||
@ -472,7 +474,19 @@ function iTutorialEnd() {
|
||||
}
|
||||
|
||||
console.log("Ending interactive tutorial");
|
||||
|
||||
// Initialize references to main menu links
|
||||
// We have to call initializeMainMenuLinks() again because the Interactive Tutorial
|
||||
// re-creates Main menu links with clearEventListeners()
|
||||
if (!initializeMainMenuLinks()) {
|
||||
const errorMsg = "Failed to initialize Main Menu Links. Please try refreshing the page. " +
|
||||
"If that doesn't work, report the issue to the developer";
|
||||
exceptionAlert(new Error(errorMsg));
|
||||
console.error(errorMsg);
|
||||
return;
|
||||
}
|
||||
Engine.init();
|
||||
|
||||
ITutorial.currStep = iTutorialSteps.End;
|
||||
ITutorial.isRunning = false;
|
||||
document.getElementById("interactive-tutorial-container").style.display = "none";
|
||||
|
@ -12,8 +12,9 @@ import {hasBladeburnerSF} from "./NetscriptFunctions";
|
||||
import {Locations} from "./Locations";
|
||||
import {Player} from "./Player";
|
||||
import {Server, AllServers, AddToAllServers} from "./Server";
|
||||
import {purchaseServer,
|
||||
purchaseRamForHomeComputer} from "./ServerPurchases";
|
||||
import { getPurchaseServerCost,
|
||||
purchaseServer,
|
||||
purchaseRamForHomeComputer} from "./ServerPurchases";
|
||||
import {Settings} from "./Settings/Settings";
|
||||
import { SourceFileFlags } from "./SourceFile/SourceFileFlags";
|
||||
import {SpecialServerNames, SpecialServerIps} from "./SpecialServerIps";
|
||||
@ -191,16 +192,16 @@ function displayLocationContent() {
|
||||
purchaseHomeRam.style.display = "none";
|
||||
purchaseHomeCores.style.display = "none";
|
||||
|
||||
purchase2gb.innerHTML = "Purchase 2GB Server - $" + formatNumber(2*CONSTANTS.BaseCostFor1GBOfRamServer, 2);
|
||||
purchase4gb.innerHTML = "Purchase 4GB Server - $" + formatNumber(4*CONSTANTS.BaseCostFor1GBOfRamServer, 2);
|
||||
purchase8gb.innerHTML = "Purchase 8GB Server - $" + formatNumber(8*CONSTANTS.BaseCostFor1GBOfRamServer, 2);
|
||||
purchase16gb.innerHTML = "Purchase 16GB Server - $" + formatNumber(16*CONSTANTS.BaseCostFor1GBOfRamServer, 2);
|
||||
purchase32gb.innerHTML = "Purchase 32GB Server - $" + formatNumber(32*CONSTANTS.BaseCostFor1GBOfRamServer, 2);
|
||||
purchase64gb.innerHTML = "Purchase 64GB Server - $" + formatNumber(64*CONSTANTS.BaseCostFor1GBOfRamServer, 2);
|
||||
purchase128gb.innerHTML = "Purchase 128GB Server - $" + formatNumber(128*CONSTANTS.BaseCostFor1GBOfRamServer, 2);
|
||||
purchase256gb.innerHTML = "Purchase 256GB Server - $" + formatNumber(256*CONSTANTS.BaseCostFor1GBOfRamServer, 2);
|
||||
purchase512gb.innerHTML = "Purchase 512GB Server - $" + formatNumber(512*CONSTANTS.BaseCostFor1GBOfRamServer, 2);
|
||||
purchase1tb.innerHTML = "Purchase 1TB Server - $" + formatNumber(1024*CONSTANTS.BaseCostFor1GBOfRamServer, 2);
|
||||
purchase2gb.innerHTML = "Purchase 2GB Server - " + numeralWrapper.formatMoney(getPurchaseServerCost(2));
|
||||
purchase4gb.innerHTML = "Purchase 4GB Server - " + numeralWrapper.formatMoney(getPurchaseServerCost(4));
|
||||
purchase8gb.innerHTML = "Purchase 8GB Server - " + numeralWrapper.formatMoney(getPurchaseServerCost(8));
|
||||
purchase16gb.innerHTML = "Purchase 16GB Server - " + numeralWrapper.formatMoney(getPurchaseServerCost(16));
|
||||
purchase32gb.innerHTML = "Purchase 32GB Server - " + numeralWrapper.formatMoney(getPurchaseServerCost(32));
|
||||
purchase64gb.innerHTML = "Purchase 64GB Server - " + numeralWrapper.formatMoney(getPurchaseServerCost(64));
|
||||
purchase128gb.innerHTML = "Purchase 128GB Server - " + numeralWrapper.formatMoney(getPurchaseServerCost(128));
|
||||
purchase256gb.innerHTML = "Purchase 256GB Server - " + numeralWrapper.formatMoney(getPurchaseServerCost(256));
|
||||
purchase512gb.innerHTML = "Purchase 512GB Server - " + numeralWrapper.formatMoney(getPurchaseServerCost(512));
|
||||
purchase1tb.innerHTML = "Purchase 1TB Server - " + numeralWrapper.formatMoney(getPurchaseServerCost(1024));
|
||||
if (!SpecialServerIps.hasOwnProperty("Darkweb Server")) {
|
||||
purchaseTor.classList.add("a-link-button");
|
||||
purchaseTor.classList.remove("a-link-button-bought");
|
||||
@ -1726,61 +1727,61 @@ function initLocationButtons() {
|
||||
|
||||
purchase2gb.addEventListener("click", function(e) {
|
||||
if (!e.isTrusted) {return false;}
|
||||
purchaseServerBoxCreate(2, 2 * CONSTANTS.BaseCostFor1GBOfRamServer);
|
||||
purchaseServerBoxCreate(2);
|
||||
return false;
|
||||
});
|
||||
|
||||
purchase4gb.addEventListener("click", function(e) {
|
||||
if (!e.isTrusted) {return false;}
|
||||
purchaseServerBoxCreate(4, 4 * CONSTANTS.BaseCostFor1GBOfRamServer);
|
||||
purchaseServerBoxCreate(4);
|
||||
return false;
|
||||
});
|
||||
|
||||
purchase8gb.addEventListener("click", function(e) {
|
||||
if (!e.isTrusted) {return false;}
|
||||
purchaseServerBoxCreate(8, 8 * CONSTANTS.BaseCostFor1GBOfRamServer);
|
||||
purchaseServerBoxCreate(8);
|
||||
return false;
|
||||
});
|
||||
|
||||
purchase16gb.addEventListener("click", function(e) {
|
||||
if (!e.isTrusted) {return false;}
|
||||
purchaseServerBoxCreate(16, 16 * CONSTANTS.BaseCostFor1GBOfRamServer);
|
||||
purchaseServerBoxCreate(16);
|
||||
return false;
|
||||
});
|
||||
|
||||
purchase32gb.addEventListener("click", function(e) {
|
||||
if (!e.isTrusted) {return false;}
|
||||
purchaseServerBoxCreate(32, 32 * CONSTANTS.BaseCostFor1GBOfRamServer);
|
||||
purchaseServerBoxCreate(32);
|
||||
return false;
|
||||
});
|
||||
|
||||
purchase64gb.addEventListener("click", function(e) {
|
||||
if (!e.isTrusted) {return false;}
|
||||
purchaseServerBoxCreate(64, 64 * CONSTANTS.BaseCostFor1GBOfRamServer);
|
||||
purchaseServerBoxCreate(64);
|
||||
return false;
|
||||
});
|
||||
|
||||
purchase128gb.addEventListener("click", function(e) {
|
||||
if (!e.isTrusted) {return false;}
|
||||
purchaseServerBoxCreate(128, 128 * CONSTANTS.BaseCostFor1GBOfRamServer);
|
||||
purchaseServerBoxCreate(128);
|
||||
return false;
|
||||
});
|
||||
|
||||
purchase256gb.addEventListener("click", function(e) {
|
||||
if (!e.isTrusted) {return false;}
|
||||
purchaseServerBoxCreate(256, 256 * CONSTANTS.BaseCostFor1GBOfRamServer);
|
||||
purchaseServerBoxCreate(256);
|
||||
return false;
|
||||
});
|
||||
|
||||
purchase512gb.addEventListener("click", function(e) {
|
||||
if (!e.isTrusted) {return false;}
|
||||
purchaseServerBoxCreate(512, 512 * CONSTANTS.BaseCostFor1GBOfRamServer);
|
||||
purchaseServerBoxCreate(512);
|
||||
return false;
|
||||
});
|
||||
|
||||
purchase1tb.addEventListener("click", function(e) {
|
||||
if (!e.isTrusted) {return false;}
|
||||
purchaseServerBoxCreate(1024, 1024 * CONSTANTS.BaseCostFor1GBOfRamServer);
|
||||
purchaseServerBoxCreate(1024);
|
||||
return false;
|
||||
});
|
||||
|
||||
@ -2264,13 +2265,19 @@ function travelBoxCreate(destCityName, cost) {
|
||||
yesNoBoxCreate("Would you like to travel to " + destCityName + "? The trip will cost $" + formatNumber(cost, 2) + ".");
|
||||
}
|
||||
|
||||
function purchaseServerBoxCreate(ram, cost) {
|
||||
function purchaseServerBoxCreate(ram) {
|
||||
const cost = getPurchaseServerCost(ram);
|
||||
if (cost === Infinity) {
|
||||
dialogBoxCreate("Something went wrong when trying to purchase this server. Please contact developer");
|
||||
return;
|
||||
}
|
||||
|
||||
var yesBtn = yesNoTxtInpBoxGetYesButton();
|
||||
var noBtn = yesNoTxtInpBoxGetNoButton();
|
||||
yesBtn.innerHTML = "Purchase Server";
|
||||
noBtn.innerHTML = "Cancel";
|
||||
yesBtn.addEventListener("click", function() {
|
||||
purchaseServer(ram, cost);
|
||||
purchaseServer(ram);
|
||||
yesNoTxtInpBoxClose();
|
||||
});
|
||||
noBtn.addEventListener("click", function() {
|
||||
|
@ -40,6 +40,9 @@ import {Script, findRunningScript, RunningScript,
|
||||
import {Server, getServer, AddToAllServers,
|
||||
AllServers, processSingleServerGrowth,
|
||||
GetServerByHostname, numCycleForGrowth} from "./Server";
|
||||
import { getPurchaseServerCost,
|
||||
getPurchaseServerLimit,
|
||||
getPurchaseServerMaxRam } from "./ServerPurchases";
|
||||
import {Settings} from "./Settings/Settings";
|
||||
import {SpecialServerIps} from "./SpecialServerIps";
|
||||
import {Stock} from "./StockMarket/Stock";
|
||||
@ -234,24 +237,6 @@ function NetscriptFunctions(workerScript) {
|
||||
return server.getContract(fn);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {number} ram The amount of server RAM to calculate cost of.
|
||||
* @exception {Error} If the value passed in is not numeric, out of range, or too large of a value.
|
||||
* @returns {number} The cost of
|
||||
*/
|
||||
const getPurchaseServerRamCostGuard = (ram) => {
|
||||
const guardedRam = Math.round(ram);
|
||||
if (isNaN(guardedRam) || !isPowerOfTwo(guardedRam)) {
|
||||
throw Error("failed due to invalid ram argument. Must be numeric and a power of 2");
|
||||
}
|
||||
|
||||
if (guardedRam > CONSTANTS.PurchasedServerMaxRam) {
|
||||
throw Error("failed because specified RAM was too high. Maximum RAM on a purchased server is " + CONSTANTS.PurchasedServerMaxRam + "GB");
|
||||
}
|
||||
|
||||
return guardedRam * CONSTANTS.BaseCostFor1GBOfRamServer;
|
||||
};
|
||||
|
||||
return {
|
||||
hacknet : {
|
||||
numNodes : function() {
|
||||
@ -1911,7 +1896,7 @@ function NetscriptFunctions(workerScript) {
|
||||
}
|
||||
updateDynamicRam("getPurchasedServerLimit", CONSTANTS.ScriptGetPurchasedServerLimit);
|
||||
|
||||
return CONSTANTS.PurchasedServerLimit;
|
||||
return getPurchaseServerLimit();
|
||||
},
|
||||
getPurchasedServerMaxRam: function() {
|
||||
if (workerScript.checkingRam) {
|
||||
@ -1919,7 +1904,7 @@ function NetscriptFunctions(workerScript) {
|
||||
}
|
||||
updateDynamicRam("getPurchasedServerMaxRam", CONSTANTS.ScriptGetPurchasedServerMaxRam);
|
||||
|
||||
return CONSTANTS.PurchasedServerMaxRam;
|
||||
return getPurchaseServerMaxRam();
|
||||
},
|
||||
getPurchasedServerCost: function(ram) {
|
||||
if (workerScript.checkingRam) {
|
||||
@ -1927,11 +1912,9 @@ function NetscriptFunctions(workerScript) {
|
||||
}
|
||||
updateDynamicRam("getPurchasedServerCost", CONSTANTS.ScriptGetPurchaseServerRamCost);
|
||||
|
||||
let cost = 0;
|
||||
try {
|
||||
cost = getPurchaseServerRamCostGuard(ram);
|
||||
} catch (e) {
|
||||
workerScript.scriptRef.log("ERROR: 'getPurchasedServerCost()' " + e.message);
|
||||
const cost = getPurchaseServerCost(ram);
|
||||
if (cost === Infinity) {
|
||||
workerScript.scriptRef.log("ERROR: 'getPurchasedServerCost()' failed due to an invalid 'ram' argument");
|
||||
return Infinity;
|
||||
}
|
||||
|
||||
@ -1945,26 +1928,23 @@ function NetscriptFunctions(workerScript) {
|
||||
var hostnameStr = String(hostname);
|
||||
hostnameStr = hostnameStr.replace(/\s+/g, '');
|
||||
if (hostnameStr == "") {
|
||||
workerScript.scriptRef.log("ERROR: Passed empty string for hostname argument of purchaseServer()");
|
||||
workerScript.log("ERROR: Passed empty string for hostname argument of purchaseServer()");
|
||||
return "";
|
||||
}
|
||||
|
||||
if (Player.purchasedServers.length >= CONSTANTS.PurchasedServerLimit) {
|
||||
workerScript.scriptRef.log("ERROR: You have reached the maximum limit of " + CONSTANTS.PurchasedServerLimit +
|
||||
" servers. You cannot purchase any more.");
|
||||
if (Player.purchasedServers.length >= getPurchaseServerLimit()) {
|
||||
workerScript.log(`ERROR: You have reached the maximum limit of ${getPurchaseServerLimit()} servers. You cannot purchase any more.`);
|
||||
return "";
|
||||
}
|
||||
|
||||
let cost = 0;
|
||||
try {
|
||||
cost = getPurchaseServerRamCostGuard(ram);
|
||||
} catch (e) {
|
||||
workerScript.scriptRef.log("ERROR: 'purchaseServer()' " + e.message);
|
||||
return "";
|
||||
const cost = getPurchaseServerCost(ram);
|
||||
if (cost === Infinity) {
|
||||
workerScript.log("ERROR: 'purchaseServer()' failed due to an invalid 'ram' argument");
|
||||
return Infinity;
|
||||
}
|
||||
|
||||
if (Player.money.lt(cost)) {
|
||||
workerScript.scriptRef.log("ERROR: Not enough money to purchase server. Need $" + formatNumber(cost, 2));
|
||||
workerScript.log("ERROR: Not enough money to purchase server. Need $" + formatNumber(cost, 2));
|
||||
return "";
|
||||
}
|
||||
var newServ = new Server({
|
||||
|
@ -16,6 +16,7 @@ import { Person,
|
||||
import { BitNodeMultipliers } from "../../BitNode/BitNodeMultipliers";
|
||||
|
||||
import { Crime } from "../../Crime/Crime";
|
||||
import { Crimes } from "../../Crime/Crimes";
|
||||
|
||||
import { Cities } from "../../Locations/Cities";
|
||||
|
||||
@ -42,6 +43,12 @@ export class Sleeve extends Person {
|
||||
return Generic_fromJSON(Sleeve, value.data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores the type of crime the sleeve is currently attempting
|
||||
* Must match the name of a Crime object
|
||||
*/
|
||||
crimeType: string = "";
|
||||
|
||||
/**
|
||||
* Enum value for current task
|
||||
*/
|
||||
@ -136,8 +143,10 @@ export class Sleeve extends Person {
|
||||
/**
|
||||
* Commit crimes
|
||||
*/
|
||||
commitCrime(p: IPlayer, crime: Crime): boolean {
|
||||
commitCrime(p: IPlayer, crimeKey: string): boolean {
|
||||
const crime: Crime | null = Crimes[crimeKey];
|
||||
if (!(crime instanceof Crime)) { return false; }
|
||||
|
||||
if (this.currentTask !== SleeveTaskType.Idle) {
|
||||
this.finishTask(p);
|
||||
} else {
|
||||
@ -154,19 +163,7 @@ export class Sleeve extends Person {
|
||||
|
||||
this.currentTaskLocation = String(this.gainRatesForTask.money);
|
||||
|
||||
// We'll determine success now and adjust the earnings accordingly
|
||||
if (Math.random() < crime.successRate(p)) {
|
||||
this.gainRatesForTask.hack *= 2;
|
||||
this.gainRatesForTask.str *= 2;
|
||||
this.gainRatesForTask.def *= 2;
|
||||
this.gainRatesForTask.dex *= 2;
|
||||
this.gainRatesForTask.agi *= 2;
|
||||
this.gainRatesForTask.cha *= 2;
|
||||
} else {
|
||||
this.gainRatesForTask.money = 0;
|
||||
}
|
||||
|
||||
|
||||
this.crimeType = crimeKey;
|
||||
this.currentTaskMaxTime = crime.time;
|
||||
this.currentTask = SleeveTaskType.Crime;
|
||||
return true;
|
||||
@ -181,8 +178,26 @@ export class Sleeve extends Person {
|
||||
if (this.currentTask === SleeveTaskType.Crime) {
|
||||
// For crimes, all experience and money is gained at the end
|
||||
if (this.currentTaskTime >= this.currentTaskMaxTime) {
|
||||
retValue = this.gainExperience(p, this.gainRatesForTask);
|
||||
this.gainMoney(p, this.gainRatesForTask);
|
||||
const crime: Crime | null = Crimes[this.crimeType];
|
||||
if (!(crime instanceof Crime)) {
|
||||
console.error(`Invalid data stored in sleeve.crimeType: ${this.crimeType}`);
|
||||
this.resetTaskStatus();
|
||||
return retValue;
|
||||
}
|
||||
if (Math.random() < crime.successRate(p)) {
|
||||
// Success
|
||||
const successGainRates: ITaskTracker = createTaskTracker();
|
||||
|
||||
const keysForIteration: (keyof ITaskTracker)[] = (<(keyof ITaskTracker)[]>Object.keys(successGainRates));
|
||||
for (let i = 0; i < keysForIteration.length; ++i) {
|
||||
const key = keysForIteration[i];
|
||||
successGainRates[key] = this.gainRatesForTask[key] * 2;
|
||||
}
|
||||
retValue = this.gainExperience(p, successGainRates);
|
||||
this.gainMoney(p, this.gainRatesForTask);
|
||||
} else {
|
||||
retValue = this.gainExperience(p, this.gainRatesForTask);
|
||||
}
|
||||
|
||||
// Do not reset task to IDLE
|
||||
this.currentTaskTime = 0;
|
||||
@ -261,7 +276,7 @@ export class Sleeve extends Person {
|
||||
this.defense_exp += pDefExp;
|
||||
p.gainDefenseExp(pDefExp);
|
||||
this.earningsForPlayer.def += pDefExp;
|
||||
this.earningsForTask.dex += pDefExp;
|
||||
this.earningsForTask.def += pDefExp;
|
||||
}
|
||||
|
||||
if (pDexExp > 0) {
|
||||
@ -464,6 +479,9 @@ export class Sleeve extends Person {
|
||||
this.currentTaskTime = 0;
|
||||
this.currentTaskMaxTime = 0;
|
||||
this.factionWorkType = FactionWorkType.None;
|
||||
this.crimeType = "";
|
||||
this.currentTaskLocation = "";
|
||||
this.gymStatType = "";
|
||||
}
|
||||
|
||||
/**
|
||||
@ -630,12 +648,16 @@ export class Sleeve extends Person {
|
||||
this.resetTaskStatus();
|
||||
}
|
||||
|
||||
const factionInfo = Factions[factionName].getInfo();
|
||||
|
||||
// Set type of work (hacking/field/security), and the experience gains
|
||||
const sanitizedWorkType: string = workType.toLowerCase();
|
||||
if (sanitizedWorkType.includes("hack")) {
|
||||
if (!factionInfo.offerHackingWork) { return false; }
|
||||
this.factionWorkType = FactionWorkType.Hacking;
|
||||
this.gainRatesForTask.hack = .15 * this.hacking_exp_mult * BitNodeMultipliers.FactionWorkExpGain;
|
||||
} else if (sanitizedWorkType.includes("field")) {
|
||||
if (!factionInfo.offerFieldWork) { return false; }
|
||||
this.factionWorkType = FactionWorkType.Field;
|
||||
this.gainRatesForTask.hack = .1 * this.hacking_exp_mult * BitNodeMultipliers.FactionWorkExpGain;
|
||||
this.gainRatesForTask.str = .1 * this.strength_exp_mult * BitNodeMultipliers.FactionWorkExpGain;
|
||||
@ -644,6 +666,7 @@ export class Sleeve extends Person {
|
||||
this.gainRatesForTask.agi = .1 * this.agility_exp_mult * BitNodeMultipliers.FactionWorkExpGain;
|
||||
this.gainRatesForTask.cha = .1 * this.charisma_exp_mult * BitNodeMultipliers.FactionWorkExpGain;
|
||||
} else if (sanitizedWorkType.includes("security")) {
|
||||
if (!factionInfo.offerSecurityWork) { return false; }
|
||||
this.factionWorkType = FactionWorkType.Security;
|
||||
this.gainRatesForTask.hack = .1 * this.hacking_exp_mult * BitNodeMultipliers.FactionWorkExpGain;
|
||||
this.gainRatesForTask.str = .15 * this.strength_exp_mult * BitNodeMultipliers.FactionWorkExpGain;
|
||||
|
@ -10,8 +10,12 @@ import { IPlayer } from "../IPlayer";
|
||||
import { CONSTANTS } from "../../Constants";
|
||||
import { Locations } from "../../Locations";
|
||||
|
||||
import { Faction } from "../../Faction/Faction";
|
||||
import { Factions } from "../../Faction/Factions";
|
||||
import { FactionWorkType } from "../../Faction/FactionWorkTypeEnum";
|
||||
|
||||
import { Cities } from "../../Locations/Cities";
|
||||
import { Crime } from "../../Crime/Crime";
|
||||
import { Crimes } from "../../Crime/Crimes";
|
||||
|
||||
import { numeralWrapper } from "../../ui/numeralFormat";
|
||||
@ -23,6 +27,7 @@ import { dialogBoxCreate } from "../../../utils/DialogBox";
|
||||
import { createProgressBarText } from "../../../utils/helpers/createProgressBarText";
|
||||
import { exceptionAlert } from "../../../utils/helpers/exceptionAlert";
|
||||
|
||||
import { clearEventListeners } from "../../../utils/uiHelpers/clearEventListeners";
|
||||
import { createElement } from "../../../utils/uiHelpers/createElement";
|
||||
import { createOptionElement } from "../../../utils/uiHelpers/createOptionElement";
|
||||
import { createPopup } from "../../../utils/uiHelpers/createPopup";
|
||||
@ -229,7 +234,7 @@ function createSleeveUi(sleeve: Sleeve, allSleeves: Sleeve[]): ISleeveUIElems {
|
||||
popupArguments.push(createElement("p", {
|
||||
innerText: "Have this sleeve travel to a different city. This affects " +
|
||||
"the gyms and universities at which this sleeve can study. " +
|
||||
`Traveling to a different city costs ${numeralWrapper.formatMoney(CONSTANTS.TravelCost)}.` +
|
||||
`Traveling to a different city costs ${numeralWrapper.formatMoney(CONSTANTS.TravelCost)}. ` +
|
||||
"It will also CANCEL the sleeve's current task (setting it to idle)",
|
||||
}));
|
||||
for (const label in Cities) {
|
||||
@ -250,6 +255,7 @@ function createSleeveUi(sleeve: Sleeve, allSleeves: Sleeve[]): ISleeveUIElems {
|
||||
sleeve.resetTaskStatus();
|
||||
removeElementById(popupId);
|
||||
updateSleeveUi(sleeve, elems);
|
||||
updateSleeveTaskSelector(sleeve, elems, allSleeves);
|
||||
return false;
|
||||
}
|
||||
}));
|
||||
@ -401,12 +407,6 @@ function updateSleeveUi(sleeve: Sleeve, elems: ISleeveUIElems) {
|
||||
}
|
||||
}
|
||||
|
||||
const factionWorkTypeSelectorOptions: string[] = [
|
||||
"Hacking Contracts",
|
||||
"Security Work",
|
||||
"Field Work"
|
||||
];
|
||||
|
||||
const universitySelectorOptions: string[] = [
|
||||
"Study Computer Science",
|
||||
"Data Structures",
|
||||
@ -450,6 +450,7 @@ function updateSleeveTaskSelector(sleeve: Sleeve, elems: ISleeveUIElems, allSlee
|
||||
// Reset Selectors
|
||||
removeChildrenFromElement(elems.taskDetailsSelector);
|
||||
removeChildrenFromElement(elems.taskDetailsSelector2);
|
||||
elems.taskDetailsSelector2 = clearEventListeners(elems.taskDetailsSelector2!) as HTMLSelectElement;
|
||||
|
||||
const value: string = getSelectValue(elems.taskSelector);
|
||||
switch(value) {
|
||||
@ -486,29 +487,57 @@ function updateSleeveTaskSelector(sleeve: Sleeve, elems: ISleeveUIElems, allSlee
|
||||
++factionCount;
|
||||
}
|
||||
}
|
||||
for (let i = 0; i < factionWorkTypeSelectorOptions.length; ++i) {
|
||||
elems.taskDetailsSelector2!.add(createOptionElement(factionWorkTypeSelectorOptions[i]));
|
||||
}
|
||||
|
||||
// Set initial value for faction work type
|
||||
switch (sleeve.factionWorkType) {
|
||||
case FactionWorkType.Hacking:
|
||||
elems.taskDetailsSelector2!.selectedIndex = 0;
|
||||
break;
|
||||
case FactionWorkType.Security:
|
||||
elems.taskDetailsSelector2!.selectedIndex = 0;
|
||||
break;
|
||||
case FactionWorkType.Field:
|
||||
elems.taskDetailsSelector2!.selectedIndex = 0;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
// The available faction work types depends on the faction
|
||||
elems.taskDetailsSelector!.addEventListener("change", () => {
|
||||
const facName = getSelectValue(elems.taskDetailsSelector!);
|
||||
const faction: Faction | null = Factions[facName];
|
||||
if (faction == null) {
|
||||
console.warn(`Invalid faction name when trying to update Sleeve Task Selector: ${facName}`);
|
||||
return;
|
||||
}
|
||||
const facInfo = faction.getInfo();
|
||||
removeChildrenFromElement(elems.taskDetailsSelector2!);
|
||||
let numOptionsAdded = 0;
|
||||
if (facInfo.offerHackingWork) {
|
||||
elems.taskDetailsSelector2!.add(createOptionElement("Hacking Contracts"));
|
||||
if (sleeve.factionWorkType === FactionWorkType.Hacking) {
|
||||
elems.taskDetailsSelector2!.selectedIndex = numOptionsAdded;
|
||||
}
|
||||
++numOptionsAdded;
|
||||
}
|
||||
if (facInfo.offerFieldWork) {
|
||||
elems.taskDetailsSelector2!.add(createOptionElement("Field Work"));
|
||||
if (sleeve.factionWorkType === FactionWorkType.Field) {
|
||||
elems.taskDetailsSelector2!.selectedIndex = numOptionsAdded;
|
||||
}
|
||||
++numOptionsAdded;
|
||||
}
|
||||
if (facInfo.offerSecurityWork) {
|
||||
elems.taskDetailsSelector2!.add(createOptionElement("Security Work"));
|
||||
if (sleeve.factionWorkType === FactionWorkType.Security) {
|
||||
elems.taskDetailsSelector2!.selectedIndex = numOptionsAdded;
|
||||
}
|
||||
++numOptionsAdded;
|
||||
}
|
||||
});
|
||||
elems.taskDetailsSelector!.dispatchEvent(new Event("change"));
|
||||
break;
|
||||
case "Commit Crime":
|
||||
let i = 0;
|
||||
for (const crimeLabel in Crimes) {
|
||||
const name: string = Crimes[crimeLabel].name;
|
||||
elems.taskDetailsSelector!.add(createOptionElement(name, crimeLabel));
|
||||
|
||||
// Set initial value for crime type
|
||||
if (sleeve.crimeType === "") { continue; }
|
||||
const crime: Crime | null = Crimes[sleeve.crimeType];
|
||||
if (crime == null) { continue; }
|
||||
if (name === crime!.name) {
|
||||
elems.taskDetailsSelector!.selectedIndex = i;
|
||||
}
|
||||
|
||||
++i;
|
||||
}
|
||||
|
||||
elems.taskDetailsSelector2!.add(createOptionElement("------"));
|
||||
@ -614,7 +643,7 @@ function setSleeveTask(sleeve: Sleeve, elems: ISleeveUIElems): boolean {
|
||||
res = sleeve.workForFaction(playerRef!, detailValue, detailValue2);
|
||||
break;
|
||||
case "Commit Crime":
|
||||
res = sleeve.commitCrime(playerRef!, Crimes[detailValue]);
|
||||
res = sleeve.commitCrime(playerRef!, detailValue);
|
||||
break;
|
||||
case "Take University Course":
|
||||
res = sleeve.takeUniversityCourse(playerRef!, detailValue2, detailValue);
|
||||
@ -637,7 +666,15 @@ function setSleeveTask(sleeve: Sleeve, elems: ISleeveUIElems): boolean {
|
||||
if (res) {
|
||||
updateSleeveTaskDescription(sleeve, elems);
|
||||
} else {
|
||||
elems.taskDescription!.innerText = "Failed to assign sleeve to task. Invalid choice(s).";
|
||||
switch (taskValue) {
|
||||
case "Work for Faction":
|
||||
elems.taskDescription!.innerText = "Failed to assign sleeve to task. This is most likely because the selected faction does not offer the selected work type.";
|
||||
break;
|
||||
default:
|
||||
elems.taskDescription!.innerText = "Failed to assign sleeve to task. Invalid choice(s).";
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (routing.isOn(Page.Sleeves)) {
|
||||
@ -672,16 +709,13 @@ function updateSleeveTaskDescription(sleeve: Sleeve, elems: ISleeveUIElems): voi
|
||||
elems.taskDescription!.innerText = "This sleeve is currently idle";
|
||||
break;
|
||||
case "Work for Company":
|
||||
elems.taskDescription!.innerText = `This sleeve is currently working your ` +
|
||||
`job at ${sleeve.currentTaskLocation}.`;
|
||||
elems.taskDescription!.innerText = `This sleeve is currently working your job at ${sleeve.currentTaskLocation}.`;
|
||||
break;
|
||||
case "Work for Faction":
|
||||
elems.taskDescription!.innerText = `This sleeve is currently doing ${detailValue2} for ` +
|
||||
`${sleeve.currentTaskLocation}.`;
|
||||
elems.taskDescription!.innerText = `This sleeve is currently doing ${detailValue2} for ${sleeve.currentTaskLocation}.`;
|
||||
break;
|
||||
case "Commit Crime":
|
||||
elems.taskDescription!.innerText = `This sleeve is currently attempting to ` +
|
||||
`${Crimes[detailValue].type}.`;
|
||||
elems.taskDescription!.innerText = `This sleeve is currently attempting to ${Crimes[detailValue].type} (Success Rate: ${numeralWrapper.formatPercentage(Crimes[detailValue].successRate(playerRef))}).`;
|
||||
break;
|
||||
case "Take University Course":
|
||||
elems.taskDescription!.innerText = `This sleeve is currently studying/taking a course at ${sleeve.currentTaskLocation}.`;
|
||||
|
@ -201,6 +201,7 @@ function PlayerObject() {
|
||||
// Sleeves & Re-sleeving
|
||||
this.sleeves = [];
|
||||
this.resleeves = [];
|
||||
this.sleevesFromCovenant = 0; // # of Duplicate sleeves purchased from the covenant
|
||||
|
||||
//bitnode
|
||||
this.bitNodeN = 1;
|
||||
@ -369,9 +370,7 @@ PlayerObject.prototype.prestigeSourceFile = function() {
|
||||
this.resleeves = [];
|
||||
|
||||
// Duplicate sleeves are reset to level 1 every Bit Node (but the number of sleeves you have persists)
|
||||
if (this.sleeves.length < SourceFileFlags[10]) {
|
||||
this.sleeves.length = SourceFileFlags[10];
|
||||
}
|
||||
this.sleeves.length = SourceFileFlags[10] + this.sleevesFromCovenant;
|
||||
for (let i = 0; i < this.sleeves.length; ++i) {
|
||||
this.sleeves[i] = new Sleeve();
|
||||
}
|
||||
|
@ -41,8 +41,6 @@ function scriptEditorInit() {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Beautify button
|
||||
const beautifyButton = createElement("button", {
|
||||
class: "std-button",
|
||||
@ -210,8 +208,9 @@ $(document).keydown(function(e) {
|
||||
function saveAndCloseScriptEditor() {
|
||||
var filename = document.getElementById("script-editor-filename").value;
|
||||
|
||||
let code;
|
||||
try {
|
||||
let code = getCurrentEditor().getCode();
|
||||
code = getCurrentEditor().getCode();
|
||||
} catch(e) {
|
||||
dialogBoxCreate("Something went wrong when trying to save (getCurrentEditor().getCode()). Please report to game developer with details");
|
||||
return;
|
||||
|
@ -18,6 +18,7 @@ require("brace/ext/language_tools");
|
||||
|
||||
import { NetscriptFunctions } from "../NetscriptFunctions";
|
||||
import { Settings } from "../Settings/Settings";
|
||||
import { AceKeybindingSetting } from "../Settings/SettingEnums";
|
||||
|
||||
import { clearEventListeners } from "../../utils/uiHelpers/clearEventListeners";
|
||||
import { createElement } from "../../utils/uiHelpers/createElement";
|
||||
@ -43,6 +44,7 @@ function validateInitializationParamters(params) {
|
||||
class AceEditorWrapper extends ScriptEditor {
|
||||
constructor() {
|
||||
super();
|
||||
this.vimCommandDisplayWrapper = null;
|
||||
}
|
||||
|
||||
init(params) {
|
||||
@ -73,7 +75,7 @@ class AceEditorWrapper extends ScriptEditor {
|
||||
editorElement.style.fontSize = '16px';
|
||||
this.editor.setOption("showPrintMargin", false);
|
||||
|
||||
//Configure some of the VIM keybindings
|
||||
// Configure some of the VIM keybindings
|
||||
ace.config.loadModule('ace/keyboard/vim', function(module) {
|
||||
var VimApi = module.CodeMirror.Vim;
|
||||
VimApi.defineEx('write', 'w', function(cm, input) {
|
||||
@ -90,6 +92,13 @@ class AceEditorWrapper extends ScriptEditor {
|
||||
});
|
||||
});
|
||||
|
||||
// Store a reference to the VIM command display
|
||||
this.vimCommandDisplayWrapper = document.getElementById("codemirror-vim-command-display-wrapper");
|
||||
if (this.vimCommandDisplayWrapper == null) {
|
||||
console.error(`Could not get Vim Command Display element (id=codemirror-vim-command-display-wrapper)`);
|
||||
return false;
|
||||
}
|
||||
|
||||
//Function autocompleter
|
||||
this.editor.setOption("enableBasicAutocompletion", true);
|
||||
var autocompleter = {
|
||||
@ -160,6 +169,11 @@ class AceEditorWrapper extends ScriptEditor {
|
||||
elem.style.display = "block";
|
||||
}
|
||||
|
||||
// Make sure the Vim command display from CodeMirror is invisible
|
||||
if (this.vimCommandDisplayWrapper instanceof HTMLElement) {
|
||||
this.vimCommandDisplayWrapper.style.display = "none";
|
||||
}
|
||||
|
||||
// Theme
|
||||
const themeDropdown = safeClearEventListeners("script-editor-option-theme", "Theme Selector");
|
||||
removeChildrenFromElement(themeDropdown);
|
||||
@ -195,10 +209,14 @@ class AceEditorWrapper extends ScriptEditor {
|
||||
// Keybinding
|
||||
const keybindingDropdown = safeClearEventListeners("script-editor-option-keybinding", "Keybinding Selector");
|
||||
removeChildrenFromElement(keybindingDropdown);
|
||||
keybindingDropdown.add(createOptionElement("Ace", "ace"));
|
||||
keybindingDropdown.add(createOptionElement("Vim", "vim"));
|
||||
keybindingDropdown.add(createOptionElement("Emacs", "emacs"));
|
||||
keybindingDropdown.add(createOptionElement("Ace", AceKeybindingSetting.Ace));
|
||||
keybindingDropdown.add(createOptionElement("Vim", AceKeybindingSetting.Vim));
|
||||
keybindingDropdown.add(createOptionElement("Emacs", AceKeybindingSetting.Emacs));
|
||||
if (Settings.EditorKeybinding) {
|
||||
// Sanitize the Keybinding setting
|
||||
if (!(Object.values(AceKeybindingSetting).includes(Settings.EditorKeybinding))) {
|
||||
Settings.EditorKeybinding = AceKeybindingSetting.Ace;
|
||||
}
|
||||
var initialIndex = 0;
|
||||
for (var i = 0; i < keybindingDropdown.options.length; ++i) {
|
||||
if (keybindingDropdown.options[i].value === Settings.EditorKeybinding) {
|
||||
|
@ -71,6 +71,8 @@ import 'codemirror/keymap/vim.js';
|
||||
import 'codemirror/keymap/emacs.js';
|
||||
|
||||
import 'codemirror/addon/comment/continuecomment.js';
|
||||
import 'codemirror/addon/dialog/dialog.css';
|
||||
import 'codemirror/addon/dialog/dialog.js';
|
||||
import 'codemirror/addon/edit/closebrackets.js';
|
||||
import 'codemirror/addon/edit/matchbrackets.js';
|
||||
import 'codemirror/addon/fold/foldcode.js';
|
||||
@ -79,6 +81,7 @@ import 'codemirror/addon/fold/foldgutter.css';
|
||||
import 'codemirror/addon/fold/brace-fold.js';
|
||||
import 'codemirror/addon/fold/indent-fold.js';
|
||||
import 'codemirror/addon/fold/comment-fold.js';
|
||||
import 'codemirror/addon/hint/javascript-hint.js';
|
||||
import 'codemirror/addon/hint/show-hint.js';
|
||||
import 'codemirror/addon/hint/show-hint.css';
|
||||
import 'codemirror/addon/lint/lint.js';
|
||||
@ -87,10 +90,11 @@ import 'codemirror/addon/search/match-highlighter.js';
|
||||
import 'codemirror/addon/selection/active-line.js';
|
||||
|
||||
window.JSHINT = require('jshint').JSHINT;
|
||||
import './CodeMirrorNetscriptHint.js';
|
||||
import './CodeMirrorNetscriptLint.js';
|
||||
|
||||
import { NetscriptFunctions } from "../NetscriptFunctions";
|
||||
import { CodeMirrorThemeSetting } from "../Settings/SettingEnums";
|
||||
import { CodeMirrorKeybindingSetting,
|
||||
CodeMirrorThemeSetting } from "../Settings/SettingEnums";
|
||||
import { Settings } from "../Settings/Settings";
|
||||
|
||||
import { clearEventListeners } from "../../utils/uiHelpers/clearEventListeners";
|
||||
@ -114,6 +118,8 @@ function validateInitializationParamters(params) {
|
||||
class CodeMirrorEditorWrapper extends ScriptEditor {
|
||||
constructor() {
|
||||
super();
|
||||
this.vimCommandDisplay = null;
|
||||
this.vimCommandDisplayWrapper = null;
|
||||
this.tabsStyleElement = null;
|
||||
}
|
||||
|
||||
@ -160,6 +166,10 @@ class CodeMirrorEditorWrapper extends ScriptEditor {
|
||||
this.tabsStyleElement = document.createElement('style');
|
||||
document.head.appendChild(this.tabsStyleElement);
|
||||
|
||||
// Store a reference to the VIM command display
|
||||
this.vimCommandDisplay = document.getElementById("codemirror-vim-command-display");
|
||||
this.vimCommandDisplayWrapper = document.getElementById("codemirror-vim-command-display-wrapper");
|
||||
|
||||
// Define a "Save" command for CodeMirror so shortcuts like Ctrl + s
|
||||
// will save in-game
|
||||
CodeMirror.commands.save = function() { params.saveAndCloseFn(); }
|
||||
@ -206,6 +216,21 @@ class CodeMirrorEditorWrapper extends ScriptEditor {
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
// Configure VIM keybindings
|
||||
var VimApi = CodeMirror.Vim;
|
||||
VimApi.defineEx('write', 'w', function(cm, input) {
|
||||
params.saveAndCloseFn();
|
||||
});
|
||||
VimApi.defineEx('quit', 'q', function(cm, input) {
|
||||
params.quitFn();
|
||||
});
|
||||
VimApi.defineEx('xwritequit', 'x', function(cm, input) {
|
||||
params.saveAndCloseFn();
|
||||
});
|
||||
VimApi.defineEx('wqwritequit', 'wq', function(cm, input) {
|
||||
params.saveAndCloseFn();
|
||||
});
|
||||
}
|
||||
|
||||
initialized() {
|
||||
@ -237,6 +262,11 @@ class CodeMirrorEditorWrapper extends ScriptEditor {
|
||||
return;
|
||||
}
|
||||
|
||||
// Get and sanitize the keybinding (keymap) setting
|
||||
if (!(Object.values(CodeMirrorKeybindingSetting).includes(Settings.EditorKeybinding))) {
|
||||
Settings.EditorKeybinding = CodeMirrorKeybindingSetting.Default;
|
||||
}
|
||||
|
||||
// Initialize CodeMirror Editor
|
||||
const textAreaElement = safeGetElementById("codemirror-editor", "CodeMirror Textarea");
|
||||
const formElement = safeGetElementById("codemirror-form-wrapper", "CodeMirror Form Wrapper");
|
||||
@ -294,10 +324,10 @@ class CodeMirrorEditorWrapper extends ScriptEditor {
|
||||
return false;
|
||||
}
|
||||
removeChildrenFromElement(keybindingDropdown);
|
||||
keybindingDropdown.add(createOptionElement("Default", "default"));
|
||||
keybindingDropdown.add(createOptionElement("Sublime", "sublime"));
|
||||
keybindingDropdown.add(createOptionElement("Vim", "vim"));
|
||||
keybindingDropdown.add(createOptionElement("Emacs", "emacs"));
|
||||
keybindingDropdown.add(createOptionElement("Default", CodeMirrorKeybindingSetting.Default));
|
||||
keybindingDropdown.add(createOptionElement("Sublime", CodeMirrorKeybindingSetting.Sublime));
|
||||
keybindingDropdown.add(createOptionElement("Vim", CodeMirrorKeybindingSetting.Vim));
|
||||
keybindingDropdown.add(createOptionElement("Emacs", CodeMirrorKeybindingSetting.Emacs));
|
||||
if (Settings.EditorKeybinding) {
|
||||
var initialIndex = 0;
|
||||
for (var i = 0; i < keybindingDropdown.options.length; ++i) {
|
||||
@ -311,14 +341,39 @@ class CodeMirrorEditorWrapper extends ScriptEditor {
|
||||
keybindingDropdown.selectedIndex = 0;
|
||||
}
|
||||
keybindingDropdown.onchange = () => {
|
||||
// Set Vim command display to be invisible initially
|
||||
this.vimCommandDisplayWrapper.style.display = "none";
|
||||
|
||||
const val = keybindingDropdown.value;
|
||||
Settings.EditorKeybinding = val;
|
||||
this.editor.removeKeyMap("sublime");
|
||||
this.editor.removeKeyMap("emacs");
|
||||
this.editor.removeKeyMap("vim");
|
||||
this.editor.removeKeyMap(CodeMirror.keyMap.default);
|
||||
this.editor.removeKeyMap(CodeMirror.keyMap.sublime);
|
||||
this.editor.removeKeyMap(CodeMirror.keyMap.emacs);
|
||||
this.editor.removeKeyMap(CodeMirror.keyMap.vim);
|
||||
|
||||
// Setup the VIM command display
|
||||
let keys = '';
|
||||
const handleVimKeyPress = (key) => {
|
||||
keys = keys + key;
|
||||
this.vimCommandDisplay.innerHTML = keys;
|
||||
}
|
||||
const handleVimCommandDone = (e) => {
|
||||
keys = '';
|
||||
this.vimCommandDisplay.innerHTML = keys;
|
||||
}
|
||||
if (val === CodeMirrorKeybindingSetting.Vim) {
|
||||
this.vimCommandDisplayWrapper.style.display = "block";
|
||||
this.editor.on('vim-keypress', handleVimKeyPress);
|
||||
this.editor.on('vim-command-done', handleVimCommandDone);
|
||||
|
||||
} else {
|
||||
this.vimCommandDisplayWrapper.style.display = "none";
|
||||
this.editor.off('vim-keypress', handleVimKeyPress);
|
||||
this.editor.off('vim-command-done', handleVimCommandDone);
|
||||
}
|
||||
|
||||
this.editor.addKeyMap(val);
|
||||
this.editor.setOption("keyMap", val);
|
||||
console.log(`Set keymap to ${val} for CodeMirror`);
|
||||
};
|
||||
keybindingDropdown.onchange();
|
||||
|
||||
@ -489,9 +544,8 @@ class CodeMirrorEditorWrapper extends ScriptEditor {
|
||||
removeFlexibleOption("script-editor-option-flex4-fieldset");
|
||||
|
||||
this.editor.refresh();
|
||||
console.log(this.editor.options);
|
||||
} catch(e) {
|
||||
console.error(`Exception caught: ${e}`);
|
||||
console.error(`Exception caught: ${e}. ${e.stack}`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -33,8 +33,12 @@
|
||||
}
|
||||
const sanitizedText = splitText.join("\n");
|
||||
|
||||
// Configure JSHINT options
|
||||
if (!options.indent) // JSHint error.character actually is a column index, this fixes underlining on lines using tabs for indentation
|
||||
options.indent = 1; // JSHint default value is 4
|
||||
|
||||
options.esversion = 6;
|
||||
|
||||
JSHINT(sanitizedText, options, options.globals);
|
||||
var errors = JSHINT.data().errors, result = [];
|
||||
if (errors) parseErrors(errors, result);
|
@ -1,16 +1,46 @@
|
||||
import {CONSTANTS} from "./Constants";
|
||||
import {Player} from "./Player";
|
||||
import {Server, AllServers, AddToAllServers} from "./Server";
|
||||
import {dialogBoxCreate} from "../utils/DialogBox";
|
||||
import {createRandomIp} from "../utils/IPAddress";
|
||||
import {yesNoTxtInpBoxGetInput} from "../utils/YesNoBox";
|
||||
|
||||
|
||||
/* Functions to handle any server-related purchasing:
|
||||
* Purchasing new servers
|
||||
* Purchasing more RAM for home computer
|
||||
/**
|
||||
* Implements functions for purchasing servers or purchasing more RAM for
|
||||
* the home computer
|
||||
*/
|
||||
function purchaseServer(ram, cost) {
|
||||
import { BitNodeMultipliers } from "./BitNode/BitNodeMultipliers";
|
||||
import { CONSTANTS } from "./Constants";
|
||||
import { Player } from "./Player";
|
||||
import { Server,
|
||||
AllServers,
|
||||
AddToAllServers} from "./Server";
|
||||
import { dialogBoxCreate } from "../utils/DialogBox";
|
||||
import { createRandomIp } from "../utils/IPAddress";
|
||||
import { yesNoTxtInpBoxGetInput } from "../utils/YesNoBox";
|
||||
import { isPowerOfTwo } from "../utils/helpers/isPowerOfTwo";
|
||||
|
||||
// Returns the cost of purchasing a server with the given RAM
|
||||
// Returns Infinity for invalid 'ram' arguments
|
||||
export function getPurchaseServerCost(ram) {
|
||||
const sanitizedRam = Math.round(ram);
|
||||
if (isNaN(sanitizedRam) || !isPowerOfTwo(sanitizedRam)) {
|
||||
return Infinity;
|
||||
}
|
||||
|
||||
if (sanitizedRam > getPurchaseServerMaxRam()) {
|
||||
return Infinity;
|
||||
}
|
||||
|
||||
return sanitizedRam * CONSTANTS.BaseCostFor1GBOfRamServer * BitNodeMultipliers.PurchasedServerCost;
|
||||
}
|
||||
|
||||
export function getPurchaseServerLimit() {
|
||||
return Math.round(CONSTANTS.PurchasedServerLimit * BitNodeMultipliers.PurchasedServerLimit);
|
||||
}
|
||||
|
||||
export function getPurchaseServerMaxRam() {
|
||||
// TODO ensure this is a power of 2?
|
||||
return Math.round(CONSTANTS.PurchasedServerMaxRam * BitNodeMultipliers.PurchasedServerMaxRam);
|
||||
}
|
||||
|
||||
// Manually purchase a server (NOT through Netscript)
|
||||
export function purchaseServer(ram) {
|
||||
const cost = getPurchaseServerCost(ram);
|
||||
|
||||
//Check if player has enough money
|
||||
if (Player.money.lt(cost)) {
|
||||
dialogBoxCreate("You don't have enough money to purchase this server!");
|
||||
@ -18,8 +48,8 @@ function purchaseServer(ram, cost) {
|
||||
}
|
||||
|
||||
//Maximum server limit
|
||||
if (Player.purchasedServers.length >= CONSTANTS.PurchasedServerLimit) {
|
||||
dialogBoxCreate("You have reached the maximum limit of " + CONSTANTS.PurchasedServerLimit + " servers. " +
|
||||
if (Player.purchasedServers.length >= getPurchaseServerLimit()) {
|
||||
dialogBoxCreate("You have reached the maximum limit of " + getPurchaseServerLimit() + " servers. " +
|
||||
"You cannot purchase any more. You can " +
|
||||
"delete some of your purchased servers using the deleteServer() Netscript function in a script");
|
||||
return;
|
||||
@ -51,8 +81,8 @@ function purchaseServer(ram, cost) {
|
||||
dialogBoxCreate("Server successfully purchased with hostname " + hostname);
|
||||
}
|
||||
|
||||
|
||||
function purchaseRamForHomeComputer(cost) {
|
||||
// Manually upgrade RAM on home computer (NOT through Netscript)
|
||||
export function purchaseRamForHomeComputer(cost) {
|
||||
if (Player.money.lt(cost)) {
|
||||
dialogBoxCreate("You do not have enough money to purchase additional RAM for your home computer");
|
||||
return;
|
||||
@ -70,5 +100,3 @@ function purchaseRamForHomeComputer(cost) {
|
||||
|
||||
dialogBoxCreate("Purchased additional RAM for home computer! It now has " + homeComputer.maxRam + "GB of RAM.");
|
||||
}
|
||||
|
||||
export {purchaseServer, purchaseRamForHomeComputer};
|
||||
|
@ -1,5 +1,27 @@
|
||||
// Enums that defined allowed values for setting configuration
|
||||
|
||||
/**
|
||||
* Allowed values for 'Keybinding/Keymap' setting in Ace editor
|
||||
*/
|
||||
export enum AceKeybindingSetting {
|
||||
Ace = "ace",
|
||||
Emacs = "emacs",
|
||||
Vim = "vim",
|
||||
}
|
||||
|
||||
/**
|
||||
* Allowed values for 'Keybinding/Keymap' setting in Code Mirror editor
|
||||
*/
|
||||
export enum CodeMirrorKeybindingSetting {
|
||||
Default = "default",
|
||||
Emacs = "emacs",
|
||||
Sublime = "sublime",
|
||||
Vim = "vim",
|
||||
}
|
||||
|
||||
/**
|
||||
* Allowed values for 'Theme' setting in Code Mirror editor
|
||||
*/
|
||||
export enum CodeMirrorThemeSetting {
|
||||
Monokai = "monokai",
|
||||
Day_3024 = "3024-day",
|
||||
@ -57,6 +79,7 @@ export enum CodeMirrorThemeSetting {
|
||||
Yeti = "yeti",
|
||||
Zenburn = "zenburn",
|
||||
}
|
||||
|
||||
/**
|
||||
* Allowed values for the "Editor" setting
|
||||
*/
|
||||
|
@ -1,5 +1,7 @@
|
||||
import { ISelfInitializer, ISelfLoading } from "../types";
|
||||
import { CodeMirrorThemeSetting,
|
||||
import { AceKeybindingSetting,
|
||||
CodeMirrorKeybindingSetting,
|
||||
CodeMirrorThemeSetting,
|
||||
EditorSetting,
|
||||
OwnedAugmentationsOrderSetting,
|
||||
PurchaseAugmentationsOrderSetting } from "./SettingEnums";
|
||||
@ -77,7 +79,7 @@ interface ISettings extends IDefaultSettings {
|
||||
* The keybinding to use in the script editor.
|
||||
* TODO: This should really be an enum of allowed values.
|
||||
*/
|
||||
EditorKeybinding: string;
|
||||
EditorKeybinding: AceKeybindingSetting | CodeMirrorKeybindingSetting;
|
||||
|
||||
/**
|
||||
* The theme used in the script editor.
|
||||
@ -119,7 +121,7 @@ export const Settings: ISettings & ISelfInitializer & ISelfLoading = {
|
||||
CodeInstructionRunTime: 25,
|
||||
DisableHotkeys: defaultSettings.DisableHotkeys,
|
||||
Editor: EditorSetting.Ace,
|
||||
EditorKeybinding: "ace",
|
||||
EditorKeybinding: AceKeybindingSetting.Ace,
|
||||
EditorTheme: "Monokai",
|
||||
Locale: "en",
|
||||
MaxLogCapacity: defaultSettings.MaxLogCapacity,
|
||||
|
@ -564,6 +564,7 @@ const Engine = {
|
||||
MainMenuLinks.Factions.classList.remove("active");
|
||||
MainMenuLinks.Augmentations.classList.remove("active");
|
||||
MainMenuLinks.HacknetNodes.classList.remove("active");
|
||||
MainMenuLinks.Sleeves.classList.remove("active");
|
||||
MainMenuLinks.City.classList.remove("active");
|
||||
MainMenuLinks.Travel.classList.remove("active");
|
||||
MainMenuLinks.Job.classList.remove("active");
|
||||
@ -1580,6 +1581,7 @@ const Engine = {
|
||||
const errorMsg = "Failed to initialize Main Menu Links. Please try refreshing the page. " +
|
||||
"If that doesn't work, report the issue to the developer";
|
||||
exceptionAlert(new Error(errorMsg));
|
||||
console.error(errorMsg);
|
||||
return;
|
||||
}
|
||||
},
|
||||
@ -1596,6 +1598,7 @@ const Engine = {
|
||||
const errorMsg = "Failed to initialize Main Menu Headers. Please try refreshing the page. " +
|
||||
"If that doesn't work, report the issue to the developer";
|
||||
exceptionAlert(new Error(errorMsg));
|
||||
console.error(errorMsg);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1641,6 +1644,7 @@ const Engine = {
|
||||
|
||||
MainMenuLinks.Sleeves.addEventListener("click", function() {
|
||||
Engine.loadSleevesContent();
|
||||
MainMenuLinks.Sleeves.classList.add("active");
|
||||
return false;
|
||||
});
|
||||
|
||||
|
@ -122,6 +122,9 @@ if (htmlWebpackPlugin.options.googleAnalytics.trackingId) { %>
|
||||
|
||||
<div id="ace-editor"></div>
|
||||
<form id="codemirror-form-wrapper"><textarea id="codemirror-editor"></textarea></form>
|
||||
<div id="codemirror-vim-command-display-wrapper">
|
||||
Key Buffer: <span id="codemirror-vim-command-display"></span>
|
||||
</div>
|
||||
|
||||
<div id="script-editor-buttons-wrapper"></div> <!-- Buttons below script editor -->
|
||||
</div> <!-- End wrapper -->
|
||||
|
@ -65,7 +65,7 @@ export function initializeMainMenuLinks(): boolean {
|
||||
MainMenuLinks.Factions = safeGetLink("factions-menu-link");
|
||||
MainMenuLinks.Augmentations = safeGetLink("augmentations-menu-link");
|
||||
MainMenuLinks.HacknetNodes = safeGetLink("hacknet-nodes-menu-link");
|
||||
MainMenuLinks.Sleeves = safeGetLink("sleeves-menu-link");
|
||||
MainMenuLinks.Sleeves = safeGetLink("sleeves-menu-link");
|
||||
MainMenuLinks.City = safeGetLink("city-menu-link");
|
||||
MainMenuLinks.Travel = safeGetLink("travel-menu-link");
|
||||
MainMenuLinks.Job = safeGetLink("job-menu-link");
|
||||
|
@ -5,9 +5,15 @@ import { getElementById } from "./getElementById";
|
||||
* replacing. Then returns the new cloned element.
|
||||
* @param elemId The HTML ID to retrieve the element by.
|
||||
*/
|
||||
export function clearEventListeners(elemId: string): HTMLElement | null {
|
||||
export function clearEventListeners(elemId: string | HTMLElement): HTMLElement | null {
|
||||
try {
|
||||
const elem: HTMLElement = getElementById(elemId);
|
||||
let elem: HTMLElement;
|
||||
if (typeof elemId === "string") {
|
||||
elem = getElementById(elemId);
|
||||
} else {
|
||||
elem = elemId;
|
||||
}
|
||||
|
||||
const newElem: HTMLElement = elem.cloneNode(true) as HTMLElement;
|
||||
if (elem.parentNode !== null) {
|
||||
elem.parentNode.replaceChild(newElem, elem);
|
||||
|
Loading…
Reference in New Issue
Block a user