Merge pull request #823 from danielyxie/dev

v0.50.2
This commit is contained in:
hydroflame 2021-03-25 21:16:22 -04:00 committed by GitHub
commit 93f8785ec6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 312 additions and 144 deletions

File diff suppressed because one or more lines are too long

18
dist/vendor.bundle.js vendored

File diff suppressed because one or more lines are too long

@ -66,7 +66,7 @@ documentation_title = '{0} Documentation'.format(project)
# The short X.Y version.
version = '0.50'
# The full version, including alpha/beta/rc tags.
release = '0.50.1'
release = '0.50.2'
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.

@ -24,6 +24,8 @@ level 3, then you will be able to access all of the Singularity Functions.
travelToCity() <singularityfunctions/travelToCity>
purchaseTor() <singularityfunctions/purchaseTor>
purchaseProgram() <singularityfunctions/purchaseProgram>
connect() <singularityfunctions/connect>
manualHack() <singularityfunctions/manualHack>
getStats() <singularityfunctions/getStats>
getCharacterInformation() <singularityfunctions/getCharacterInformation>
isBusy() <singularityfunctions/isBusy>

@ -0,0 +1,20 @@
connect() Netscript Function
============================
.. js:function:: connect(hostname)
:RAM cost: 2 GB
:param string hostname: hostname of the server to connect.
:returns: ``true`` if the connection was a success.
If you are not in BitNode-4, then you must have Level 1 of Source-File 4 in order to use this function.
This function will connect you to the specified server if it's directly connected to the current server.
You can also pass in 'home' to return to your home server from anywhere.
Examples:
.. code-block:: javascript
connect("joesguns");
connect("CSEC");

@ -0,0 +1,24 @@
manualHack() Netscript Function
===============================
.. js:function:: manualHack()
:RAM cost: 2 GB
:returns: The amount of money stolen if the hack is successful, and zero otherwise
If you are not in BitNode-4, then you must have Level 1 of Source-File 4 in order to use this function.
This function will perform a manual hack on the server you are currently connected to.
This is typically required to join factions.
Examples:
.. code-block:: javascript
connect("CSEC");
manualHack();
.. warning::
For NS2 users:
This function is async.

@ -31,6 +31,8 @@ Alt + f Switch to 'Factions' page
Alt + a Switch to 'Augmentations' page
Alt + u Switch to 'Tutorial' page
Alt + o Switch to 'Options' page
Alt + g Switch to 'Gang' page
Alt + b Switch to 'Bladeburner' page
========== ===========================================================================
Script Editor

@ -274,6 +274,7 @@ export function initBitNodeMultipliers(p: IPlayer) {
BitNodeMultipliers.InfiltrationMoney = 3;
BitNodeMultipliers.FactionWorkRepGain = 0.5;
BitNodeMultipliers.FactionPassiveRepGain = 0;
BitNodeMultipliers.GangKarmaRequirement = 0;
break;
case 3: // Corporatocracy
BitNodeMultipliers.HackingLevelMultiplier = 0.8;
@ -289,6 +290,7 @@ export function initBitNodeMultipliers(p: IPlayer) {
BitNodeMultipliers.HacknetNodeMoney = 0.25;
BitNodeMultipliers.HomeComputerRamCost = 1.5;
BitNodeMultipliers.PurchasedServerCost = 2;
BitNodeMultipliers.GangKarmaRequirement = 3;
break;
case 4: // The Singularity
BitNodeMultipliers.ServerMaxMoney = 0.15;
@ -331,6 +333,7 @@ export function initBitNodeMultipliers(p: IPlayer) {
BitNodeMultipliers.FactionPassiveRepGain = 0;
BitNodeMultipliers.HackExpGain = 0.25;
BitNodeMultipliers.DaedalusAugsRequirement = 1.166; // Results in 35 Augs needed
BitNodeMultipliers.GangKarmaRequirement = 5;
break;
case 7: // Bladeburner 2079
BitNodeMultipliers.BladeburnerRank = 0.6;
@ -351,6 +354,7 @@ export function initBitNodeMultipliers(p: IPlayer) {
BitNodeMultipliers.FourSigmaMarketDataCost = 2;
BitNodeMultipliers.FourSigmaMarketDataApiCost = 2;
BitNodeMultipliers.DaedalusAugsRequirement = 1.166; // Results in 35 Augs needed
BitNodeMultipliers.GangKarmaRequirement = 5;
break;
case 8: // Ghost of Wall Street
BitNodeMultipliers.ScriptHackMoney = 0.3;
@ -363,6 +367,7 @@ export function initBitNodeMultipliers(p: IPlayer) {
BitNodeMultipliers.RepToDonateToFaction = 0;
BitNodeMultipliers.CorporationValuation = 0;
BitNodeMultipliers.CodingContractMoney = 0;
BitNodeMultipliers.GangKarmaRequirement = 10;
break;
case 9: // Hacktocracy
BitNodeMultipliers.HackingLevelMultiplier = 0.4;
@ -384,6 +389,7 @@ export function initBitNodeMultipliers(p: IPlayer) {
BitNodeMultipliers.FourSigmaMarketDataApiCost = 4;
BitNodeMultipliers.BladeburnerRank = 0.9;
BitNodeMultipliers.BladeburnerSkillCost = 1.2;
BitNodeMultipliers.GangKarmaRequirement = 3;
break;
case 10: // Digital Carbon
BitNodeMultipliers.HackingLevelMultiplier = 0.2;
@ -407,6 +413,7 @@ export function initBitNodeMultipliers(p: IPlayer) {
BitNodeMultipliers.PurchasedServerLimit = 0.6;
BitNodeMultipliers.PurchasedServerMaxRam = 0.5;
BitNodeMultipliers.BladeburnerRank = 0.8;
BitNodeMultipliers.GangKarmaRequirement = 3;
break;
case 11: //The Big Crash
BitNodeMultipliers.HackingLevelMultiplier = 0.5;

@ -109,6 +109,11 @@ interface IBitNodeMultipliers {
*/
FourSigmaMarketDataCost: number;
/**
* Influences how much negative karma is required to create a gang in this bitnode.
*/
GangKarmaRequirement: number;
/**
* Influences the experienced gained when hacking a server.
*/
@ -268,4 +273,5 @@ export const BitNodeMultipliers: IBitNodeMultipliers = {
BladeburnerSkillCost: 1,
DaedalusAugsRequirement: 1,
GangKarmaRequirement: 1,
};

@ -6,7 +6,7 @@
import { IMap } from "./types";
export let CONSTANTS: IMap<any> = {
Version: "0.50.1",
Version: "0.50.2",
/** Max level for any skill, assuming no multipliers. Determined by max numerical value in javascript for experience
* and the skill level formula in Player.js. Note that all this means it that when experience hits MAX_INT, then
@ -228,21 +228,18 @@ export let CONSTANTS: IMap<any> = {
LatestUpdate:
`
v0.50.1 - 2021-03-22 (hydroflame)
v0.50.2 - 2021-03-25 Everyone asked for this one. (hydroflame)
-------
BitNodeMultipliers
* 'GangKarmaRequirements': a new multipler that influences how much karma is required to make a gang different bitnodes.
Netscript
* getTaskStats works
Source-File -1
* Added a new Exploit
Factions
* Augmentations offered by a Faction but already bought are in a separate list at the bottom of the page.
Bug fixed
* Fixed a bug where completing a maxed non-repeatable BitNode would make its color on the BitVerse like level 1.
* 'connect': a new singularity function that connects you to a server. (like the terminal command)
* 'manualHack': a new singularity function that performs a manual hack on the players current server.
* ns2 stack trace works on Firefox now.
Misc.
* Minor spacing in stats tables.
* New shortcut, Alt + b, brings you to bladeburner
* New shortcut, Alt + g, brings you to gang
`
}

@ -1516,7 +1516,6 @@ HackingMission.prototype.finishMission = function(win) {
var gain = this.reward * Player.faction_rep_mult * favorMult;
dialogBoxCreate("Mission won! You earned " +
numeralWrapper.format(gain, '0.000a') + " reputation with " + this.faction.name);
console.log(`diff ${this.difficulty}`);
Player.gainIntelligenceExp(this.difficulty * CONSTANTS.IntelligenceHackingMissionBaseExpGain);
this.faction.playerReputation += gain;
} else {

@ -176,6 +176,8 @@ export const RamCosts: IMap<any> = {
travelToCity: () => RamCostConstants.ScriptSingularityFn1RamCost,
purchaseTor: () => RamCostConstants.ScriptSingularityFn1RamCost,
purchaseProgram: () => RamCostConstants.ScriptSingularityFn1RamCost,
connect: () => RamCostConstants.ScriptSingularityFn1RamCost,
manualHack: () => RamCostConstants.ScriptSingularityFn1RamCost,
getStats: () => RamCostConstants.ScriptSingularityFn1RamCost / 4,
getCharacterInformation: () => RamCostConstants.ScriptSingularityFn1RamCost / 4,
isBusy: () => RamCostConstants.ScriptSingularityFn1RamCost / 4,

@ -59,6 +59,7 @@ import {
import { HacknetServer, MaxNumberHacknetServers } from "./Hacknet/HacknetServer";
import { CityName } from "./Locations/data/CityNames";
import { LocationName } from "./Locations/data/LocationNames";
import { Terminal } from "./Terminal";
import { Message } from "./Message/Message";
import { Messages } from "./Message/MessageHelpers";
@ -405,16 +406,42 @@ function NetscriptFunctions(workerScript) {
}
if(!filename) continue
const lineRe = /.*:(\d+):\d+.*/;
const lineMatch = stackline.match(lineRe);
function parseChromeStackline(line) {
const lineRe = /.*:(\d+):\d+.*/;
const funcRe = /.*at (.+) \(.*/;
const lineMatch = line.match(lineRe);
const funcMatch = line.match(funcRe);
if(lineMatch && funcMatch) {
let func = funcMatch[1];
return {line: lineMatch[1], func: func};
}
return null;
}
let call = {line: "-1", func: "unknown"};;
let chromeCall = parseChromeStackline(stackline);
if (chromeCall) {
call = chromeCall;
}
const funcRe = /.*at (.+) \(.*/;
const funcMatch = stackline.match(funcRe);
let func = funcMatch[1];
if(func.includes('.')) func = func.split('.')[1];
function parseFirefoxStackline(line) {
const lineRe = /.*:(\d+):\d+$/;
const lineMatch = line.match(lineRe);
userstack.push(`${filename}:L${lineMatch[1]}@${func}`);
const lio = line.lastIndexOf("@");
if(lineMatch && lio !== -1) {
return {line: lineMatch[1], func: line.slice(0, lio)};
}
return null;
}
let firefoxCall = parseFirefoxStackline(stackline);
if (firefoxCall) {
call = firefoxCall;
}
userstack.push(`${filename}:L${call.line}@${call.func}`);
}
workerScript.log(caller, msg);
@ -537,29 +564,97 @@ function NetscriptFunctions(workerScript) {
const runAfterReset = function(cbScript=null) {
//Run a script after reset
console.log(cbScript);
if (cbScript && isString(cbScript)) {
console.log('here');
const home = Player.getHomeComputer();
for (const script of home.scripts) {
console.log('here 2'+script);
if (script.filename === cbScript) {
console.log('here 3');
const ramUsage = script.ramUsage;
const ramAvailable = home.maxRam - home.ramUsed;
if (ramUsage > ramAvailable) {
console.log('here 4');
return; // Not enough RAM
}
const runningScriptObj = new RunningScript(script, []); // No args
runningScriptObj.threads = 1; // Only 1 thread
console.log('running!');
startWorkerScript(runningScriptObj, home);
}
}
}
}
const hack = function(ip, manual, { threads: requestedThreads, stock } = {}) {
if (ip === undefined) {
throw makeRuntimeErrorMsg("hack", "Takes 1 argument.");
}
const threads = resolveNetscriptRequestedThreads(workerScript, "hack", requestedThreads);
const server = getServer(ip);
if (server == null) {
throw makeRuntimeErrorMsg("hack", `Invalid IP/hostname: ${ip}.`);
}
// Calculate the hacking time
var hackingTime = calculateHackingTime(server); // This is in seconds
// No root access or skill level too low
const canHack = netscriptCanHack(server, Player);
if (!canHack.res) {
throw makeRuntimeErrorMsg('hack', canHack.msg);
}
workerScript.log("hack", `Executing ${ip} in ${hackingTime.toFixed(3)} seconds (t=${threads})`);
return netscriptDelay(hackingTime * 1000, workerScript).then(function() {
if (workerScript.env.stopFlag) {return Promise.reject(workerScript);}
var hackChance = calculateHackingChance(server);
var rand = Math.random();
var expGainedOnSuccess = calculateHackingExpGain(server) * threads;
var expGainedOnFailure = (expGainedOnSuccess / 4);
if (rand < hackChance) { // Success!
const percentHacked = calculatePercentMoneyHacked(server);
let maxThreadNeeded = Math.ceil(1/percentHacked*(server.moneyAvailable/server.moneyMax));
if (isNaN(maxThreadNeeded)) {
// Server has a 'max money' of 0 (probably). We'll set this to an arbitrarily large value
maxThreadNeeded = 1e6;
}
let moneyDrained = Math.floor(server.moneyAvailable * percentHacked) * threads;
// Over-the-top safety checks
if (moneyDrained <= 0) {
moneyDrained = 0;
expGainedOnSuccess = expGainedOnFailure;
}
if (moneyDrained > server.moneyAvailable) {moneyDrained = server.moneyAvailable;}
server.moneyAvailable -= moneyDrained;
if (server.moneyAvailable < 0) {server.moneyAvailable = 0;}
const moneyGained = moneyDrained * BitNodeMultipliers.ScriptHackMoneyGain;
Player.gainMoney(moneyGained);
workerScript.scriptRef.onlineMoneyMade += moneyGained;
Player.scriptProdSinceLastAug += moneyGained;
Player.recordMoneySource(moneyGained, "hacking");
workerScript.scriptRef.recordHack(server.ip, moneyGained, threads);
Player.gainHackingExp(expGainedOnSuccess);
workerScript.scriptRef.onlineExpGained += expGainedOnSuccess;
workerScript.log("hack", `Successfully hacked '${server.hostname}' for ${numeralWrapper.format(moneyGained, '$0.000a')} and ${numeralWrapper.format(expGainedOnSuccess, '0.000a')} exp (t=${threads})`);
server.fortify(CONSTANTS.ServerFortifyAmount * Math.min(threads, maxThreadNeeded));
if (stock) {
influenceStockThroughServerHack(server, moneyGained);
}
if(manual) {
server.manuallyHacked = true;
}
return Promise.resolve(moneyGained);
} else {
// Player only gains 25% exp for failure?
Player.gainHackingExp(expGainedOnFailure);
workerScript.scriptRef.onlineExpGained += expGainedOnFailure;
workerScript.log("hack", `Failed to hack '${server.hostname}'. Gained ${numeralWrapper.format(expGainedOnFailure, '0.000a')} exp (t=${threads})`);
return Promise.resolve(0);
}
});
}
return {
hacknet : {
numNodes : function() {
@ -676,74 +771,7 @@ function NetscriptFunctions(workerScript) {
},
hack : function(ip, { threads: requestedThreads, stock } = {}){
updateDynamicRam("hack", getRamCost("hack"));
if (ip === undefined) {
throw makeRuntimeErrorMsg("hack", "Takes 1 argument.");
}
const threads = resolveNetscriptRequestedThreads(workerScript, "hack", requestedThreads);
const server = getServer(ip);
if (server == null) {
throw makeRuntimeErrorMsg("hack", `Invalid IP/hostname: ${ip}.`);
}
// Calculate the hacking time
var hackingTime = calculateHackingTime(server); // This is in seconds
// No root access or skill level too low
const canHack = netscriptCanHack(server, Player);
if (!canHack.res) {
throw makeRuntimeErrorMsg('hack', canHack.msg);
}
workerScript.log("hack", `Executing ${ip} in ${hackingTime.toFixed(3)} seconds (t=${threads})`);
return netscriptDelay(hackingTime * 1000, workerScript).then(function() {
if (workerScript.env.stopFlag) {return Promise.reject(workerScript);}
var hackChance = calculateHackingChance(server);
var rand = Math.random();
var expGainedOnSuccess = calculateHackingExpGain(server) * threads;
var expGainedOnFailure = (expGainedOnSuccess / 4);
if (rand < hackChance) { // Success!
const percentHacked = calculatePercentMoneyHacked(server);
let maxThreadNeeded = Math.ceil(1/percentHacked*(server.moneyAvailable/server.moneyMax));
if (isNaN(maxThreadNeeded)) {
// Server has a 'max money' of 0 (probably). We'll set this to an arbitrarily large value
maxThreadNeeded = 1e6;
}
let moneyDrained = Math.floor(server.moneyAvailable * percentHacked) * threads;
// Over-the-top safety checks
if (moneyDrained <= 0) {
moneyDrained = 0;
expGainedOnSuccess = expGainedOnFailure;
}
if (moneyDrained > server.moneyAvailable) {moneyDrained = server.moneyAvailable;}
server.moneyAvailable -= moneyDrained;
if (server.moneyAvailable < 0) {server.moneyAvailable = 0;}
const moneyGained = moneyDrained * BitNodeMultipliers.ScriptHackMoneyGain;
Player.gainMoney(moneyGained);
workerScript.scriptRef.onlineMoneyMade += moneyGained;
Player.scriptProdSinceLastAug += moneyGained;
Player.recordMoneySource(moneyGained, "hacking");
workerScript.scriptRef.recordHack(server.ip, moneyGained, threads);
Player.gainHackingExp(expGainedOnSuccess);
workerScript.scriptRef.onlineExpGained += expGainedOnSuccess;
workerScript.log("hack", `Successfully hacked '${server.hostname}' for ${numeralWrapper.format(moneyGained, '$0.000a')} and ${numeralWrapper.format(expGainedOnSuccess, '0.000a')} exp (t=${threads})`);
server.fortify(CONSTANTS.ServerFortifyAmount * Math.min(threads, maxThreadNeeded));
if (stock) {
influenceStockThroughServerHack(server, moneyGained);
}
return Promise.resolve(moneyGained);
} else {
// Player only gains 25% exp for failure?
Player.gainHackingExp(expGainedOnFailure);
workerScript.scriptRef.onlineExpGained += expGainedOnFailure;
workerScript.log("hack", `Failed to hack '${server.hostname}'. Gained ${numeralWrapper.format(expGainedOnFailure, '0.000a')} exp (t=${threads})`);
return Promise.resolve(0);
}
});
return hack(ip, false, {threads: requestedThreads, stock: stock});
},
hackAnalyzeThreads : function(ip, hackAmount) {
updateDynamicRam("hackAnalyzeThreads", getRamCost("hackAnalyzeThreads"));
@ -1686,8 +1714,6 @@ function NetscriptFunctions(workerScript) {
checkTixApiAccess("buyStock");
const stock = getStockFromSymbol(symbol, "buyStock");
const res = buyStock(stock, shares, workerScript, { rerenderFn: displayStockMarketContent });
console.log(stock);
console.log(res);
return res ? stock.price : 0;
},
sellStock: function(symbol, shares) {
@ -2684,6 +2710,47 @@ function NetscriptFunctions(workerScript) {
workerScript.log("purchaseProgram", `You have purchased the '${item.program}' program. The new program can be found on your home computer.`);
return true;
},
connect: function(hostname) {
if (!hostname) {
throw makeRuntimeErrorMsg("connect", `Invalid hostname: '${hostname}'`);
}
let target = getServer(hostname);
if (target == null) {
throw makeRuntimeErrorMsg("connect", `Invalid hostname: '${hostname}'`);
return;
}
if(hostname === 'home') {
Player.getCurrentServer().isConnectedTo = false;
Player.currentServer = Player.getHomeComputer().ip;
Player.getCurrentServer().isConnectedTo = true;
Terminal.currDir = "/";
Terminal.resetTerminalInput(true);
return true;
}
const server = Player.getCurrentServer();
for (let i = 0; i < server.serversOnNetwork.length; i++) {
const other = getServerOnNetwork(server, i);
if (other.ip == hostname || other.hostname == hostname) {
Player.getCurrentServer().isConnectedTo = false;
Player.currentServer = target.ip;
Player.getCurrentServer().isConnectedTo = true;
Terminal.currDir = "/";
Terminal.resetTerminalInput(true);
return true;
}
}
return false;
},
manualHack: function() {
updateDynamicRam("manualHack", getRamCost("manualHack"));
checkSingularityAccess("manualHack", 1);
const server = Player.getCurrentServer();
return hack(server.hostname, true);
},
getStats: function() {
updateDynamicRam("getStats", getRamCost("getStats"));
checkSingularityAccess("getStats", 1);

@ -163,7 +163,7 @@ function startNetscript1Script(workerScript) {
if (typeof entry === "function") {
//Async functions need to be wrapped. See JS-Interpreter documentation
if (name === "hack" || name === "grow" || name === "weaken" || name === "sleep" ||
name === "prompt") {
name === "prompt" || name === "manualHack") {
let tempWrapper = function() {
let fnArgs = [];

@ -1,16 +1,16 @@
import { Factions } from "../../Faction/Factions";
import { Gang } from "../../Gang";
import { SourceFileFlags } from "../../SourceFile/SourceFileFlags";
import { BitNodeMultipliers } from "../../BitNode/BitNodeMultipliers";
// Amount of negative karma needed to manage a gang in BitNodes other than 2
const GangKarmaRequirement = -54000;
export function canAccessGang() {
if (this.bitNodeN === 2) { return true; }
if (SourceFileFlags[2] <= 0) { return false; }
return (this.karma <= GangKarmaRequirement);
return (this.karma <= BitNodeMultipliers.GangKarmaRequirement*GangKarmaRequirement);
}
export function getGangFaction() {

@ -113,6 +113,10 @@ function isNumber(str) {
return !isNaN(str) && !isNaN(parseFloat(str));
}
function getTerminalInput() {
return document.getElementById("terminal-input-text-box").value;
}
// Defines key commands in terminal
$(document).keydown(function(event) {
// Terminal
@ -122,7 +126,7 @@ $(document).keydown(function(event) {
if (event.keyCode === KEY.ENTER) {
event.preventDefault(); // Prevent newline from being entered in Script Editor
const command = terminalInput.value;
const command = getTerminalInput();
const dir = Terminal.currDir;
post(
"<span class='prompt'>[" +
@ -344,22 +348,36 @@ let Terminal = {
// Excludes the trailing forward slash
currDir: "/",
resetTerminalInput: function() {
resetTerminalInput: function(keepInput=false) {
let input = "";
if(keepInput) {
input = getTerminalInput();
}
const dir = Terminal.currDir;
if (FconfSettings.WRAP_INPUT) {
document.getElementById("terminal-input-td").innerHTML =
`<div id='terminal-input-header' class='prompt'>[${Player.getCurrentServer().hostname} ~${dir}]$ </div>` +
'<textarea type="text" id="terminal-input-text-box" class="terminal-input" tabindex="1"/>';
`<textarea type="text" id="terminal-input-text-box" class="terminal-input" tabindex="1" value=\"${input}\"/>`;
// Auto re-size the line element as it wraps
autosize(document.getElementById("terminal-input-text-box"));
} else {
document.getElementById("terminal-input-td").innerHTML =
`<div id='terminal-input-header' class='prompt'>[${Player.getCurrentServer().hostname} ~${dir}]$ </div>` +
`<input type="text" id="terminal-input-text-box" class="terminal-input" tabindex="1"/>`;
`<input type="text" id="terminal-input-text-box" class="terminal-input" tabindex="1" value=\"${input}\"/>`;
}
var hdr = document.getElementById("terminal-input-header");
const hdr = document.getElementById("terminal-input-header");
hdr.style.display = "inline";
const terminalInput = document.getElementById("terminal-input-text-box");
if (typeof terminalInput.selectionStart == "number") {
terminalInput.selectionStart = terminalInput.selectionEnd = terminalInput.value.length;
} else if (typeof terminalInput.createTextRange != "undefined") {
terminalInput.focus();
var range = el.createTextRange();
range.collapse(false);
range.select();
}
},
modifyInput: function(mod) {

@ -134,7 +134,7 @@ $(document).keydown(function(e) {
} catch(e) {}
if (!Player.isWorking && !redPillFlag && !inMission && !cinematicTextFlag) {
if (e.keyCode == 84 && e.altKey) {
if (e.keyCode == KEY.T && e.altKey) {
e.preventDefault();
Engine.loadTerminalContent();
} else if (e.keyCode === KEY.C && e.altKey) {
@ -174,6 +174,12 @@ $(document).keydown(function(e) {
} else if (e.keyCode === KEY.U && e.altKey) {
e.preventDefault();
Engine.loadTutorialContent();
} else if (e.keyCode === KEY.B && e.altKey) {
e.preventDefault();
Engine.loadBladeburnerContent();
} else if (e.keyCode === KEY.G && e.altKey) {
e.preventDefault();
Engine.loadGangContent();
}
}

@ -4,30 +4,48 @@ import { IMap } from "../../src/types";
* Keyboard key codes
*/
export const KEY: IMap<number> = {
A: 65,
B: 66,
C: 67,
CTRL: 17,
D: 68,
DOWNARROW: 40,
E: 69,
ENTER: 13,
ESC: 27,
F: 70,
H: 72,
J: 74,
K: 75,
L: 76,
M: 77,
N: 78,
O: 79,
P: 80,
R: 82,
S: 83,
TAB: 9,
U: 85,
UPARROW: 38,
W: 87,
"1": 49,
"2": 50,
CTRL: 17,
DOWNARROW: 40,
ENTER: 13,
ESC: 27,
TAB: 9,
UPARROW: 38,
"0": 48,
"1": 49,
"2": 50,
"3": 51,
"4": 52,
"5": 53,
"6": 54,
"7": 55,
"8": 56,
"9": 57,
A: 65,
B: 66,
C: 67,
D: 68,
E: 69,
F: 70,
G: 71,
H: 72,
I: 73,
J: 74,
K: 75,
L: 76,
M: 77,
N: 78,
O: 79,
P: 80,
Q: 81,
R: 82,
S: 83,
T: 84,
U: 85,
V: 86,
W: 87,
X: 88,
Y: 89,
Z: 90,
};