From 1d2136da4b4439ee30d3181dfbdbc432b359a342 Mon Sep 17 00:00:00 2001 From: Olivier Gagnon Date: Sun, 7 Mar 2021 21:40:30 -0500 Subject: [PATCH 01/19] Minor space formatting in Hacking,Active Scripts --- src/Constants.ts | 40 ++--------------------- src/ui/ActiveScripts/ScriptProduction.tsx | 2 +- 2 files changed, 3 insertions(+), 39 deletions(-) diff --git a/src/Constants.ts b/src/Constants.ts index e78c1784d..fa34260f1 100644 --- a/src/Constants.ts +++ b/src/Constants.ts @@ -228,46 +228,10 @@ export let CONSTANTS: IMap = { LatestUpdate: ` - v0.48.0 - ASCII + v0.49.0 ------- - ASCII - * Travel Agency now displays a world map - * Cities are now top view of metro station maps - - Netscript - * 'softReset' is a new netscript function that performs a soft reset - regardless of if the player has bought augmentations or not. - * 'getAugmentationStats' is a new netscript function that returns the stats of - an augmentation. - * getCharacterInformation now additionally returns exp - * pid resets back to 1 when installing or destroying a BitNode. - * New '.ns' scripts start with a main function. - * 'hacknet.maxNumNodes' returns the maximum number of hacknet nodes. - - Bladeburner - * Current stamina will scale as max stamina increases, this prevents players - from having very high penalty when they gain huge amount of exp at the - start of a reset. - Misc. - * Fixed an issue where SF3 was listed as infinitly repeatable and SF12 as - having a limit of 3. - * Fixed an issue where the gang equipment screen would freeze the game if a - script installed augmentations while it is open. - * All BonusTime now displays in the 'H M S' format. - * Donation textbox style updated to match the rest of the game. - * Corporation name style updated to match the rest of the game. - * minor formatting under Hacking>Active Scripts - * typo in BN12 description - * BN12 now reduces contract money - * Character>Stats percentages are aligned, server and hacknet limit are - displayed, if the player has SF5 the reduces stats are shown. - * Character>Augmentations now displays by how much the player stats will - increase. - * Character>Augmentations has a badge indicating how many augs the player - has bought but not installed - * Character>Factions has a badge indicating how many factions have pending - invites. + * Minor formatting under Hacking>Active Scripts ` } diff --git a/src/ui/ActiveScripts/ScriptProduction.tsx b/src/ui/ActiveScripts/ScriptProduction.tsx index 7ee604dd6..68bef4152 100644 --- a/src/ui/ActiveScripts/ScriptProduction.tsx +++ b/src/ui/ActiveScripts/ScriptProduction.tsx @@ -36,7 +36,7 @@ export function ScriptProduction(props: IProps): React.ReactElement { {numeralWrapper.formatMoney(props.p.scriptProdSinceLastAug)} - ( +  ( {numeralWrapper.formatMoney(prodRateSinceLastAug)} / sec From 84423e63095065fd07f4bfbac2900c97381427e3 Mon Sep 17 00:00:00 2001 From: Olivier Gagnon Date: Sun, 7 Mar 2021 22:01:31 -0500 Subject: [PATCH 02/19] gang.getEquipmentStats added, returns equipment multipliers --- .../netscript/gangapi/getEquipmentStats.rst | 17 +++++++++++++++++ src/Constants.ts | 5 ++++- src/Gang.js | 2 +- src/Netscript/RamCostGenerator.ts | 1 + src/NetscriptFunctions.js | 12 +++++++++++- src/ScriptEditor/AceNetscriptMode.js | 2 +- 6 files changed, 35 insertions(+), 4 deletions(-) create mode 100644 doc/source/netscript/gangapi/getEquipmentStats.rst diff --git a/doc/source/netscript/gangapi/getEquipmentStats.rst b/doc/source/netscript/gangapi/getEquipmentStats.rst new file mode 100644 index 000000000..c9f7d2a8e --- /dev/null +++ b/doc/source/netscript/gangapi/getEquipmentStats.rst @@ -0,0 +1,17 @@ +getEquipmentStats() Netscript Function +===================================== + +.. js:function:: getEquipmentStats(equipName) + + :RAM cost: 2 GB + + :param string equipName: Name of equipment + + :returns: A dictionary containing the stats of the equipment. + + Get the specified equipment stats. + + { + "str":1.04, + "def":1.04 + } diff --git a/src/Constants.ts b/src/Constants.ts index fa34260f1..ca7ef195f 100644 --- a/src/Constants.ts +++ b/src/Constants.ts @@ -6,7 +6,7 @@ import { IMap } from "./types"; export let CONSTANTS: IMap = { - Version: "0.48.0", + Version: "0.49.0", /** 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 @@ -231,6 +231,9 @@ export let CONSTANTS: IMap = { v0.49.0 ------- + Netscript + * 'gang.getEquipmentStats' returns the stats of the equipment. + Misc. * Minor formatting under Hacking>Active Scripts ` diff --git a/src/Gang.js b/src/Gang.js index dd3cbc952..df4ed866d 100644 --- a/src/Gang.js +++ b/src/Gang.js @@ -981,7 +981,7 @@ GangMemberUpgrade.fromJSON = function(value) { Reviver.constructors.GangMemberUpgrade = GangMemberUpgrade; // Initialize Gang Member Upgrades -const GangMemberUpgrades = {} +export const GangMemberUpgrades = {} function addGangMemberUpgrade(name, cost, type, mults) { GangMemberUpgrades[name] = new GangMemberUpgrade(name, cost, type, mults); diff --git a/src/Netscript/RamCostGenerator.ts b/src/Netscript/RamCostGenerator.ts index a89a061bb..331d1a15a 100644 --- a/src/Netscript/RamCostGenerator.ts +++ b/src/Netscript/RamCostGenerator.ts @@ -220,6 +220,7 @@ export const RamCosts: IMap = { getEquipmentNames: () => RamCostConstants.ScriptGangApiBaseRamCost / 4, getEquipmentCost: () => RamCostConstants.ScriptGangApiBaseRamCost / 2, getEquipmentType: () => RamCostConstants.ScriptGangApiBaseRamCost / 2, + getEquipmentStats: () => RamCostConstants.ScriptGangApiBaseRamCost / 2, purchaseEquipment: () => RamCostConstants.ScriptGangApiBaseRamCost, ascendMember: () => RamCostConstants.ScriptGangApiBaseRamCost, setTerritoryWarfare: () => RamCostConstants.ScriptGangApiBaseRamCost / 2, diff --git a/src/NetscriptFunctions.js b/src/NetscriptFunctions.js index 285c1ee56..221c33f61 100644 --- a/src/NetscriptFunctions.js +++ b/src/NetscriptFunctions.js @@ -29,7 +29,7 @@ import { calculateGrowTime, calculateWeakenTime } from "./Hacking"; -import { AllGangs } from "./Gang"; +import { AllGangs, GangMemberUpgrades } from "./Gang"; import { Faction } from "./Faction/Faction"; import { Factions, factionExists } from "./Faction/Factions"; import { joinFaction, purchaseAugmentation } from "./Faction/FactionHelpers"; @@ -3742,6 +3742,16 @@ function NetscriptFunctions(workerScript) { throw makeRuntimeRejectMsg(workerScript, nsGang.unknownGangApiExceptionMessage("getEquipmentType", e)); } }, + getEquipmentStats: function(equipName) { + updateDynamicRam("getEquipmentStats", getRamCost("gang", "getEquipmentStats")); + nsGang.checkGangApiAccess(workerScript, "getEquipmentStats"); + + const equipment = GangMemberUpgrades[equipName]; + if (!equipment) { + throw makeRuntimeRejectMsg(workerScript, nsGang.unknownGangApiExceptionMessage("getEquipmentStats", `${equipName} does not exists`)); + } + return Object.assign({}, equipment.mults); + }, purchaseEquipment: function(memberName, equipName) { updateDynamicRam("purchaseEquipment", getRamCost("gang", "purchaseEquipment")); nsGang.checkGangApiAccess(workerScript, "purchaseEquipment"); diff --git a/src/ScriptEditor/AceNetscriptMode.js b/src/ScriptEditor/AceNetscriptMode.js index 06a4a818e..6eefec447 100644 --- a/src/ScriptEditor/AceNetscriptMode.js +++ b/src/ScriptEditor/AceNetscriptMode.js @@ -110,7 +110,7 @@ let NetscriptFunctions = "getMemberNames|getGangInformation|getMemberInformation|canRecruitMember|" + "recruitMember|getTaskNames|setMemberTask|getEquipmentNames|" + "getEquipmentCost|getEquipmentType|purchaseEquipment|ascendMember|" + - "setTerritoryWarfare|" + + "setTerritoryWarfare|getEquipmentStats|" + "getChanceToWinClash|getBonusTime|" + // Bladeburner API From 619db14622899b4bb628ad4d72fd71e7dcefb619 Mon Sep 17 00:00:00 2001 From: Olivier Gagnon Date: Sun, 7 Mar 2021 22:12:02 -0500 Subject: [PATCH 03/19] Added gang.getTaskStats which returns the stats of a gang task --- doc/source/netscript/gangapi/getTaskStats.rst | 33 +++++++++++++++++++ src/Gang.js | 2 +- src/Netscript/RamCostGenerator.ts | 1 + src/NetscriptFunctions.js | 17 +++++++++- src/ScriptEditor/AceNetscriptMode.js | 2 +- 5 files changed, 52 insertions(+), 3 deletions(-) create mode 100644 doc/source/netscript/gangapi/getTaskStats.rst diff --git a/doc/source/netscript/gangapi/getTaskStats.rst b/doc/source/netscript/gangapi/getTaskStats.rst new file mode 100644 index 000000000..067fda2d8 --- /dev/null +++ b/doc/source/netscript/gangapi/getTaskStats.rst @@ -0,0 +1,33 @@ +getTaskStats() Netscript Function +====================================== + +.. js:function:: getTaskStats() + + :RAM cost: 1 GB + + Get the stats of a gang member stats. This is typically used to evaluate + which action should be executed next. + + { + name: Terrorism, + desc: "Assign this gang member to commit acts of terrorism + + Greatly increases respect - Greatly increases wanted level - Scales heavily with territory", + isHacking: false, + isCombat: true, + baseRespect: 0.01, + baseWanted: 6, + baseMoney: 0, + hackWeight: 20, + strWeight: 20, + defWeight: 20, + dexWeight: 20, + agiWeight: 0, + chaWeight: 20, + difficulty: 36, + territory: { + money: 1, + respect: 2, + wanted: 2 + } + } diff --git a/src/Gang.js b/src/Gang.js index df4ed866d..b0fa2c82b 100644 --- a/src/Gang.js +++ b/src/Gang.js @@ -912,7 +912,7 @@ GangMemberTask.fromJSON = function(value) { Reviver.constructors.GangMemberTask = GangMemberTask; -const GangMemberTasks = {}; +export const GangMemberTasks = {}; function addGangMemberTask(name, desc, isHacking, isCombat, params) { GangMemberTasks[name] = new GangMemberTask(name, desc, isHacking, isCombat, params); diff --git a/src/Netscript/RamCostGenerator.ts b/src/Netscript/RamCostGenerator.ts index 331d1a15a..394ad35ea 100644 --- a/src/Netscript/RamCostGenerator.ts +++ b/src/Netscript/RamCostGenerator.ts @@ -216,6 +216,7 @@ export const RamCosts: IMap = { canRecruitMember: () => RamCostConstants.ScriptGangApiBaseRamCost / 4, recruitMember: () => RamCostConstants.ScriptGangApiBaseRamCost / 2, getTaskNames: () => RamCostConstants.ScriptGangApiBaseRamCost / 4, + getTaskStats: () => RamCostConstants.ScriptGangApiBaseRamCost / 4, setMemberTask: () => RamCostConstants.ScriptGangApiBaseRamCost / 2, getEquipmentNames: () => RamCostConstants.ScriptGangApiBaseRamCost / 4, getEquipmentCost: () => RamCostConstants.ScriptGangApiBaseRamCost / 2, diff --git a/src/NetscriptFunctions.js b/src/NetscriptFunctions.js index 221c33f61..c6a5e9ff7 100644 --- a/src/NetscriptFunctions.js +++ b/src/NetscriptFunctions.js @@ -29,7 +29,11 @@ import { calculateGrowTime, calculateWeakenTime } from "./Hacking"; -import { AllGangs, GangMemberUpgrades } from "./Gang"; +import { + AllGangs, + GangMemberUpgrades, + GangMemberTasks +} from "./Gang"; import { Faction } from "./Faction/Faction"; import { Factions, factionExists } from "./Faction/Factions"; import { joinFaction, purchaseAugmentation } from "./Faction/FactionHelpers"; @@ -3712,6 +3716,17 @@ function NetscriptFunctions(workerScript) { throw makeRuntimeRejectMsg(workerScript, nsGang.unknownGangApiExceptionMessage("setMemberTask", e)); } }, + getTaskStats: function(taskName) { + updateDynamicRam("getTaskStats", getRamCost("gang", "getTaskStats")); + nsGang.checkGangApiAccess(workerScript, "getTaskStats"); + const task = GangMemberTasks[taskName]; + if (!task) { + throw makeRuntimeRejectMsg(workerScript, nsGang.unknownGangApiExceptionMessage("getTaskStats", `${taskName} does not exists`)); + } + const copy = Object.assign({}, task); + copy.territory = Object.assign({}, task.territory) + return copy; + }, getEquipmentNames: function() { updateDynamicRam("getEquipmentNames", getRamCost("gang", "getEquipmentNames")); nsGang.checkGangApiAccess(workerScript, "getEquipmentNames"); diff --git a/src/ScriptEditor/AceNetscriptMode.js b/src/ScriptEditor/AceNetscriptMode.js index 6eefec447..e9c81dd98 100644 --- a/src/ScriptEditor/AceNetscriptMode.js +++ b/src/ScriptEditor/AceNetscriptMode.js @@ -110,7 +110,7 @@ let NetscriptFunctions = "getMemberNames|getGangInformation|getMemberInformation|canRecruitMember|" + "recruitMember|getTaskNames|setMemberTask|getEquipmentNames|" + "getEquipmentCost|getEquipmentType|purchaseEquipment|ascendMember|" + - "setTerritoryWarfare|getEquipmentStats|" + + "setTerritoryWarfare|getEquipmentStats|getTaskStats|" + "getChanceToWinClash|getBonusTime|" + // Bladeburner API From 381ea915f73bef5389f29bfc1a84cc9ddf360c16 Mon Sep 17 00:00:00 2001 From: Olivier Gagnon Date: Sun, 7 Mar 2021 22:13:04 -0500 Subject: [PATCH 04/19] update patch notes and getTaskStats documentation --- doc/source/netscript/gangapi/getTaskStats.rst | 4 +++- src/Constants.ts | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/doc/source/netscript/gangapi/getTaskStats.rst b/doc/source/netscript/gangapi/getTaskStats.rst index 067fda2d8..6b0b15d2f 100644 --- a/doc/source/netscript/gangapi/getTaskStats.rst +++ b/doc/source/netscript/gangapi/getTaskStats.rst @@ -1,10 +1,12 @@ getTaskStats() Netscript Function ====================================== -.. js:function:: getTaskStats() +.. js:function:: getTaskStats(taskName) :RAM cost: 1 GB + :param string name: Name of the task. + Get the stats of a gang member stats. This is typically used to evaluate which action should be executed next. diff --git a/src/Constants.ts b/src/Constants.ts index ca7ef195f..fc890907c 100644 --- a/src/Constants.ts +++ b/src/Constants.ts @@ -233,6 +233,7 @@ export let CONSTANTS: IMap = { Netscript * 'gang.getEquipmentStats' returns the stats of the equipment. + * 'gang.getTaskStats' returns the stats of a task. Misc. * Minor formatting under Hacking>Active Scripts From e1aec379c1f7301f0514145d7e8a8d04570e2aa5 Mon Sep 17 00:00:00 2001 From: Olivier Gagnon Date: Sun, 7 Mar 2021 22:22:23 -0500 Subject: [PATCH 05/19] getCrimeStats returns the inner stats of a crime --- .../singularityfunctions/getCrimeStats.rst | 37 +++++++++++++++++++ src/Netscript/RamCostGenerator.ts | 1 + src/NetscriptFunctions.js | 16 ++++++++ src/ScriptEditor/AceNetscriptMode.js | 4 +- 4 files changed, 56 insertions(+), 2 deletions(-) create mode 100644 doc/source/netscript/singularityfunctions/getCrimeStats.rst diff --git a/doc/source/netscript/singularityfunctions/getCrimeStats.rst b/doc/source/netscript/singularityfunctions/getCrimeStats.rst new file mode 100644 index 000000000..46a22d4b6 --- /dev/null +++ b/doc/source/netscript/singularityfunctions/getCrimeStats.rst @@ -0,0 +1,37 @@ +getCrimeStats() Netscript Function +=================================== + +.. js:function:: getCrimeStats(crime) + + :RAM cost: 5 GB + + :param string crime: + Name of crime. Not case-sensitive. This argument is fairlyn lenient in terms of what inputs it accepts. + Check the documentation for the *commitCrime()* function for a list of example inputs. + + If you are not in BitNode-4, then you must have Level 3 of Source-File 4 in order to use this function. + + :return The stats of the crime + + { + "difficulty": 0.2, + "karma": 0.25, + "kills": 0, + "money": 36000, + "name": "Mug", + "time": 4000, + "type": "mug someone", + "hacking_success_weight": 0, + "strength_success_weight": 1.5, + "defense_success_weight": 0.5, + "dexterity_success_weight": 1.5, + "agility_success_weight": 0.5, + "charisma_success_weight": 0, + "hacking_exp": 0, + "strength_exp": 3, + "defense_exp": 3, + "dexterity_exp": 3, + "agility_exp": 3, + "charisma_exp": 0, + "intelligence_exp": 0 + } diff --git a/src/Netscript/RamCostGenerator.ts b/src/Netscript/RamCostGenerator.ts index 394ad35ea..e40c06186 100644 --- a/src/Netscript/RamCostGenerator.ts +++ b/src/Netscript/RamCostGenerator.ts @@ -197,6 +197,7 @@ export const RamCosts: IMap = { createProgram: () => RamCostConstants.ScriptSingularityFn3RamCost, commitCrime: () => RamCostConstants.ScriptSingularityFn3RamCost, getCrimeChance: () => RamCostConstants.ScriptSingularityFn3RamCost, + getCrimeStats: () => RamCostConstants.ScriptSingularityFn3RamCost, getOwnedAugmentations: () => RamCostConstants.ScriptSingularityFn3RamCost, getOwnedSourceFiles: () => RamCostConstants.ScriptSingularityFn3RamCost, getAugmentationsFromFaction: () => RamCostConstants.ScriptSingularityFn3RamCost, diff --git a/src/NetscriptFunctions.js b/src/NetscriptFunctions.js index c6a5e9ff7..acec50ca4 100644 --- a/src/NetscriptFunctions.js +++ b/src/NetscriptFunctions.js @@ -3332,6 +3332,22 @@ function NetscriptFunctions(workerScript) { return crime.successRate(Player); }, + getCrimeStats: function(crimeRoughName) { + updateDynamicRam("getCrimeStats", getRamCost("getCrimeStats")); + if (Player.bitNodeN !== 4) { + if (SourceFileFlags[4] <= 2) { + throw makeRuntimeRejectMsg(workerScript, "Cannot run getCrimeStats(). It is a Singularity Function and requires SourceFile-4 (level 3) to run."); + return; + } + } + + const crime = findCrime(crimeRoughName.toLowerCase()); + if(crime == null) { + throw makeRuntimeRejectMsg(workerScript, "Invalid crime passed into getCrimeStats(): " + crime); + } + + return Object.assign({}, crime); + }, getOwnedAugmentations: function(purchased=false) { updateDynamicRam("getOwnedAugmentations", getRamCost("getOwnedAugmentations")); if (Player.bitNodeN !== 4) { diff --git a/src/ScriptEditor/AceNetscriptMode.js b/src/ScriptEditor/AceNetscriptMode.js index e9c81dd98..054d30314 100644 --- a/src/ScriptEditor/AceNetscriptMode.js +++ b/src/ScriptEditor/AceNetscriptMode.js @@ -87,11 +87,11 @@ let NetscriptFunctions = "getCompanyFavor|stopAction|getFactionFavor|" + "getFavorToDonate|getFactionFavorGain|getCompanyFavorGain|" + "checkFactionInvitations|joinFaction|workForFaction|getFactionRep|" + - "donateToFaction|" + + "donateToFaction|getCrimeStats|" + "createProgram|commitCrime|getCrimeChance|getOwnedAugmentations|" + "getOwnedSourceFiles|getAugmentationsFromFaction|" + "getAugmentationPrereq|getAugmentationCost|purchaseAugmentation|" + - "softReset|installAugmentations|getAugmentationStats|" + + "softReset|installAugmentations|getAugmentationStats|" + // TIX API "getStockPrice|getStockPosition|getStockSymbols|getStockMaxShares|" + From 56a3660d380d792b75d621731e8128226d09d0bd Mon Sep 17 00:00:00 2001 From: Olivier Gagnon Date: Sun, 7 Mar 2021 22:23:42 -0500 Subject: [PATCH 06/19] update patch notes --- src/Constants.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Constants.ts b/src/Constants.ts index fc890907c..f6b49e332 100644 --- a/src/Constants.ts +++ b/src/Constants.ts @@ -234,6 +234,7 @@ export let CONSTANTS: IMap = { Netscript * 'gang.getEquipmentStats' returns the stats of the equipment. * 'gang.getTaskStats' returns the stats of a task. + * 'getCrimeStats' returns the stats of a crime. Misc. * Minor formatting under Hacking>Active Scripts From 316a1aa475d33a1475eb3862478b5ebde2ac11be Mon Sep 17 00:00:00 2001 From: Olivier Gagnon Date: Sun, 7 Mar 2021 22:46:50 -0500 Subject: [PATCH 07/19] Most console.log have been changed to console.warn or removed if they were debug --- src/Augmentation/AugmentationHelpers.jsx | 2 +- src/BitNode/BitNode.ts | 2 +- src/Bladeburner.js | 12 +++--- src/Corporation/Corporation.jsx | 19 ++++---- src/Corporation/Product.ts | 3 +- .../ui/CorporationUIEventHandler.js | 4 +- src/Fconf/Fconf.js | 4 +- src/InteractiveTutorial.js | 5 +-- src/Missions.js | 43 ++++++++----------- src/Perk.js | 6 +-- .../Player/PlayerObjectGeneralMethods.js | 25 ++++++----- src/RedPill.js | 7 ++- src/SaveObject.js | 12 +++--- src/Script/RamCalculations.js | 2 +- src/Script/ScriptHelpers.js | 5 --- src/Server/ServerHelpers.ts | 2 +- src/SourceFile/applySourceFile.ts | 2 +- src/Terminal.js | 1 - src/engine.jsx | 3 -- 19 files changed, 64 insertions(+), 95 deletions(-) diff --git a/src/Augmentation/AugmentationHelpers.jsx b/src/Augmentation/AugmentationHelpers.jsx index cb8060da4..fe82cf539 100644 --- a/src/Augmentation/AugmentationHelpers.jsx +++ b/src/Augmentation/AugmentationHelpers.jsx @@ -2063,7 +2063,7 @@ function installAugmentations(cbScript=null) { for (var i = 0; i < Player.queuedAugmentations.length; ++i) { var aug = Augmentations[Player.queuedAugmentations[i].name]; if (aug == null) { - console.log("ERROR. Invalid augmentation"); + console.error(`Invalid augmentation: ${Player.queuedAugmentations[i].name}`); continue; } applyAugmentation(Player.queuedAugmentations[i]); diff --git a/src/BitNode/BitNode.ts b/src/BitNode/BitNode.ts index 3c4057619..b46e5b2fe 100644 --- a/src/BitNode/BitNode.ts +++ b/src/BitNode/BitNode.ts @@ -492,7 +492,7 @@ export function initBitNodeMultipliers(p: IPlayer) { BitNodeMultipliers.BladeburnerSkillCost = inc; break; default: - console.log("WARNING: Player.bitNodeN invalid"); + console.warn("Player.bitNodeN invalid"); break; } } diff --git a/src/Bladeburner.js b/src/Bladeburner.js index 270baec13..c3ca46202 100644 --- a/src/Bladeburner.js +++ b/src/Bladeburner.js @@ -495,7 +495,7 @@ Action.prototype.getSuccessChance = function(inst, params={}) { var key = "eff" + stat.charAt(0).toUpperCase() + stat.slice(1); var effMultiplier = inst.skillMultipliers[key]; if (effMultiplier == null) { - console.log("ERROR: Failed to find Bladeburner Skill multiplier for: " + stat); + console.error(`Failed to find Bladeburner Skill multiplier for: ${stat}`); effMultiplier = 1; } competence += (this.weights[stat] * Math.pow(effMultiplier*playerStatLvl, this.decays[stat])); @@ -1218,8 +1218,7 @@ Bladeburner.prototype.startAction = function(actionId) { Bladeburner.prototype.processAction = function(seconds) { if (this.action.type === ActionTypes["Idle"]) {return;} if (this.actionTimeToComplete <= 0) { - console.log("action.type: " + this.action.type); - throw new Error("Invalid actionTimeToComplete value: " + this.actionTimeToComplete); + throw new Error(`Invalid actionTimeToComplete value: ${this.actionTimeToComplete}, type; ${this.action.type}`); } if (!(this.action instanceof ActionIdentifier)) { throw new Error("Bladeburner.action is not an ActionIdentifier Object"); @@ -1720,7 +1719,7 @@ Bladeburner.prototype.randomEvent = function() { Bladeburner.prototype.triggerPotentialMigration = function(sourceCityName, chance) { if (chance == null || isNaN(chance)) { - console.log("ERROR: Invalid 'chance' parameter passed into Bladeburner.triggerPotentialMigration()"); + console.error("Invalid 'chance' parameter passed into Bladeburner.triggerPotentialMigration()"); } if (chance > 1) {chance /= 100;} if (Math.random() < chance) {this.triggerMigration(sourceCityName);} @@ -2310,7 +2309,7 @@ Bladeburner.prototype.createSkillsContent = function() { // TODO in the future if items are ever implemented break; default: - console.log("Warning: Unrecognized SkillMult Key: " + multKeys[i]); + console.warn(`Unrecognized SkillMult Key: ${multKeys[i]}`); break; } } @@ -3022,7 +3021,6 @@ Bladeburner.prototype.parseCommandArguments = function(command) { ++i; } if (start !== i) {args.push(command.substr(start, i-start));} - console.log("Bladeburner console command parsing returned: " + args); return args; } @@ -3286,7 +3284,7 @@ Bladeburner.prototype.executeSkillConsoleCommand = function(args) { // TODO if items are ever implemented break; default: - console.log("Warning: Unrecognized SkillMult Key: " + multKeys[i]); + console.warn(`Unrecognized SkillMult Key: ${multKeys[i]}`); break; } } diff --git a/src/Corporation/Corporation.jsx b/src/Corporation/Corporation.jsx index ef3f97d52..b19b8fea4 100644 --- a/src/Corporation/Corporation.jsx +++ b/src/Corporation/Corporation.jsx @@ -383,7 +383,7 @@ Industry.prototype.init = function() { this.makesProducts = true; break; default: - console.log("ERR: Invalid Industry Type passed into Industry.init(): " + this.type); + console.error(`Invalid Industry Type passed into Industry.init(): ${this.type}`); return; } } @@ -409,7 +409,7 @@ Industry.prototype.getProductDescriptionText = function() { case Industries.RealEstate: return "develop and manage real estate properties"; default: - console.log("ERROR: Invalid industry type in Industry.getProductDescriptionText"); + console.error("Invalid industry type in Industry.getProductDescriptionText"); return ""; } } @@ -477,9 +477,7 @@ Industry.prototype.process = function(marketCycles=1, state, company) { //Then calculate salaries and processs the markets if (state === "START") { if (isNaN(this.thisCycleRevenue) || isNaN(this.thisCycleExpenses)) { - console.log("ERROR: NaN in Corporation's computed revenue/expenses"); - console.log(this.thisCycleRevenue.toString()); - console.log(this.thisCycleExpenses.toString()); + console.error("NaN in Corporation's computed revenue/expenses"); dialogBoxCreate("Something went wrong when compting Corporation's revenue/expenses. This is a bug. Please report to game developer"); this.thisCycleRevenue = new Decimal(0); this.thisCycleExpenses = new Decimal(0); @@ -898,7 +896,7 @@ Industry.prototype.processMaterials = function(marketCycles=1, company) { var expIndustry = company.divisions[foo]; var expWarehouse = expIndustry.warehouses[exp.city]; if (!(expWarehouse instanceof Warehouse)) { - console.log("ERROR: Invalid export! " + expIndustry.name + " " + exp.city); + console.error(`Invalid export! ${expIndustry.name} ${exp.city}`); break; } @@ -931,7 +929,7 @@ Industry.prototype.processMaterials = function(marketCycles=1, company) { case "START": break; default: - console.log("ERROR: Invalid state: " + this.state); + console.error(`Invalid state: ${this.state}`); break; } //End switch(this.state) this.updateWarehouseSizeUsed(warehouse); @@ -1181,7 +1179,7 @@ Industry.prototype.processProduct = function(marketCycles=1, product, corporatio case "EXPORT": break; default: - console.log("ERROR: Invalid State: " + this.state); + console.error(`Invalid State: ${this.state}`); break; } //End switch(this.state) } @@ -1221,7 +1219,7 @@ Industry.prototype.upgrade = function(upgrade, refs) { this.popularity *= ((1 + getRandomInt(1, 3) / 100) * advMult); break; default: - console.log("ERROR: Un-implemented function index: " + upgN); + console.error(`Un-implemented function index: ${upgN}`); break; } } @@ -1287,7 +1285,6 @@ Industry.prototype.updateResearchTree = function() { // Since ResearchTree data isnt saved, we'll update the Research Tree data // based on the stored 'researched' property in the Industry object if (Object.keys(researchTree.researched).length !== Object.keys(this.researched).length) { - console.log("Updating Corporation Research Tree Data"); for (let research in this.researched) { researchTree.research(research); } @@ -1547,7 +1544,7 @@ Employee.prototype.calculateProductivity = function(corporation, industry) { prodMult = 0; break; default: - console.log("ERROR: Invalid employee position: " + this.pos); + console.error(`Invalid employee position: ${this.pos}`); break; } return prodBase * prodMult; diff --git a/src/Corporation/Product.ts b/src/Corporation/Product.ts index 18cc75e57..8d424e22c 100644 --- a/src/Corporation/Product.ts +++ b/src/Corporation/Product.ts @@ -153,7 +153,6 @@ export class Product { const opsRatio = employeeProd[EmployeePositions.Operations] / employeeProd["total"]; const busRatio = employeeProd[EmployeePositions.Business] / employeeProd["total"]; var designMult = 1 + (Math.pow(this.designCost, 0.1) / 100); - console.log("designMult: " + designMult); var balanceMult = (1.2 * engrRatio) + (0.9 * mgmtRatio) + (1.3 * rndRatio) + (1.5 * opsRatio) + (busRatio); var sciMult = 1 + (Math.pow(industry.sciResearch.qty, industry.sciFac) / 800); @@ -221,7 +220,7 @@ export class Product { calculateRating(industry: IIndustry): void { const weights: IProductRatingWeight = ProductRatingWeights[industry.type]; if (weights == null) { - console.log("ERROR: Could not find product rating weights for: " + industry); + console.error(`Could not find product rating weights for: ${industry}`); return; } this.rat = 0; diff --git a/src/Corporation/ui/CorporationUIEventHandler.js b/src/Corporation/ui/CorporationUIEventHandler.js index 39dc55886..0d1eaa336 100644 --- a/src/Corporation/ui/CorporationUIEventHandler.js +++ b/src/Corporation/ui/CorporationUIEventHandler.js @@ -110,7 +110,6 @@ export class CorporationEventHandler { } else { var totalAmount = money + (stockShares * stockPrice); var repGain = totalAmount / BribeToRepRatio; - console.log("repGain: " + repGain); repGainText.innerText = "You will gain " + numeralWrapper.format(repGain, "0,0") + " reputation with " + factionSelector.options[factionSelector.selectedIndex].value + @@ -1539,8 +1538,7 @@ export class CorporationEventHandler { this.corp.numShares -= shares; if (isNaN(this.corp.issuedShares)) { - console.log("ERROR: Corporation issuedShares is NaN: " + this.corp.issuedShares); - console.log("Converting to number now"); + console.error(`Corporation issuedShares is NaN: ${this.corp.issuedShares}`); var res = parseInt(this.corp.issuedShares); if (isNaN(res)) { this.corp.issuedShares = 0; diff --git a/src/Fconf/Fconf.js b/src/Fconf/Fconf.js index 7baa349a0..dbed7892a 100644 --- a/src/Fconf/Fconf.js +++ b/src/Fconf/Fconf.js @@ -91,7 +91,7 @@ function parseFconfSetting(setting, value) { setting = String(setting); value = String(value); if (setting == null || value == null || FconfSettings[setting] == null) { - console.log("WARNING: Invalid .fconf setting: " + setting); + console.warn(`Invalid .fconf setting: ${setting}`); return; } @@ -184,7 +184,7 @@ function setTheme() { FconfSettings.THEME_FONT_COLOR == null || FconfSettings.THEME_BACKGROUND_COLOR == null || FconfSettings.THEME_PROMPT_COLOR == null) { - console.log("ERROR: Cannot find Theme Settings"); + console.error("Cannot find Theme Settings"); return; } if (/^#[0-9a-f]{3}(?:[0-9a-f]{3})?$/i.test(FconfSettings.THEME_HIGHLIGHT_COLOR) && diff --git a/src/InteractiveTutorial.js b/src/InteractiveTutorial.js index da5543868..979d19227 100644 --- a/src/InteractiveTutorial.js +++ b/src/InteractiveTutorial.js @@ -69,7 +69,6 @@ function iTutorialStart() { // Don't autosave during this interactive tutorial Engine.Counters.autoSaveCounter = Infinity; - console.log("Interactive Tutorial started"); ITutorial.currStep = 0; ITutorial.isRunning = true; @@ -100,7 +99,7 @@ function iTutorialStart() { } function iTutorialEvaluateStep() { - if (!ITutorial.isRunning) {console.log("Interactive Tutorial not running"); return;} + if (!ITutorial.isRunning) {return;} // Disable and clear main menu var terminalMainMenu = clearEventListeners("terminal-menu-link"); @@ -476,8 +475,6 @@ function iTutorialEnd() { Engine.Counters.autoSaveCounter = Settings.AutosaveInterval * 5; } - 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() diff --git a/src/Missions.js b/src/Missions.js index 36c906146..e702ff579 100644 --- a/src/Missions.js +++ b/src/Missions.js @@ -165,7 +165,7 @@ Node.prototype.deselect = function(actionButtons) { Node.prototype.untarget = function() { if (this.targetedCount === 0) { - console.log("WARN: Node " + this.el.id + " is being 'untargeted' when it has no target count"); + console.warn(`Node ${this.el.id} is being 'untargeted' when it has no target count`); return; } --this.targetedCount; @@ -214,7 +214,6 @@ function HackingMission(rep, fac) { this.jsplumbinstance = null; this.difficulty = rep / CONSTANTS.HackingMissionRepToDiffConversion + 1; - console.log("difficulty: " + this.difficulty); this.reward = 250 + (rep / CONSTANTS.HackingMissionRepToRewardConversion); } @@ -408,7 +407,7 @@ HackingMission.prototype.createPageDom = function() { // Set Action Button event listeners this.actionButtons[0].addEventListener("click", ()=>{ if (!(this.selectedNode.length > 0)) { - console.log("ERR: Pressing Action button without selected node"); + console.error("Pressing Action button without selected node"); return; } if (this.selectedNode[0].type !== NodeTypes.Core) {return;} @@ -421,7 +420,7 @@ HackingMission.prototype.createPageDom = function() { this.actionButtons[1].addEventListener("click", ()=>{ if (!(this.selectedNode.length > 0)) { - console.log("ERR: Pressing Action button without selected node"); + console.error("Pressing Action button without selected node"); return; } var nodeType = this.selectedNode[0].type; // In a multiselect, every Node will have the same type @@ -435,7 +434,7 @@ HackingMission.prototype.createPageDom = function() { this.actionButtons[2].addEventListener("click", ()=>{ if (!(this.selectedNode.length > 0)) { - console.log("ERR: Pressing Action button without selected node"); + console.error("Pressing Action button without selected node"); return; } var nodeType = this.selectedNode[0].type; // In a multiselect, every Node will have the same type @@ -449,7 +448,7 @@ HackingMission.prototype.createPageDom = function() { this.actionButtons[3].addEventListener("click", ()=>{ if (!(this.selectedNode.length > 0)) { - console.log("ERR: Pressing Action button without selected node"); + console.error("Pressing Action button without selected node"); return; } this.setActionButtonsActive(this.selectedNode[0].type); @@ -461,7 +460,7 @@ HackingMission.prototype.createPageDom = function() { this.actionButtons[4].addEventListener("click", ()=>{ if (!(this.selectedNode.length > 0)) { - console.log("ERR: Pressing Action button without selected node"); + console.error("Pressing Action button without selected node"); return; } var nodeType = this.selectedNode[0].type; @@ -475,7 +474,7 @@ HackingMission.prototype.createPageDom = function() { this.actionButtons[5].addEventListener("click", ()=>{ if (!(this.selectedNode.length > 0)) { - console.log("ERR: Pressing Action button without selected node"); + console.error("Pressing Action button without selected node"); return; } this.selectedNode.forEach(function(node){ @@ -637,18 +636,16 @@ HackingMission.prototype.removeAvailablePosition = function(x, y) { return; } } - console.log("WARNING: removeAvailablePosition() did not remove " + x + ", " + y); + console.warn(`removeAvailablePosition() did not remove ${x}, ${y}`); } HackingMission.prototype.setNodePosition = function(nodeObj, x, y) { if (!(nodeObj instanceof Node)) { - console.log("WARNING: Non-Node object passed into setNodePOsition"); + console.warn("Non-Node object passed into setNodePOsition"); return; } if (isNaN(x) || isNaN(y)) { - console.log("ERR: Invalid values passed as x and y for setNodePosition"); - console.log(x); - console.log(y); + console.error(`Invalid values (${x}, ${y}) passed as (x, y) for setNodePosition`); return; } nodeObj.pos = [x, y]; @@ -725,7 +722,6 @@ HackingMission.prototype.createMap = function() { // Configure all Player CPUS for (var i = 0; i < this.playerCores.length; ++i) { - console.log("Configuring Player Node: " + this.playerCores[i].el.id); this.configurePlayerNodeElement(this.playerCores[i].el); } } @@ -793,7 +789,7 @@ HackingMission.prototype.createNodeDomElement = function(nodeObj) { HackingMission.prototype.updateNodeDomElement = function(nodeObj) { if (nodeObj.el == null) { - console.log("ERR: Calling updateNodeDomElement on a Node without an element"); + console.error("Calling updateNodeDomElement on a Node without an element"); return; } @@ -853,12 +849,12 @@ HackingMission.prototype.getNodeFromElement = function(el) { id = id.replace("hacking-mission-node-", ""); var res = id.split('-'); if (res.length != 2) { - console.log("ERROR Parsing Hacking Mission Node Id. Could not find coordinates"); + console.error("Parsing hacking mission node id. could not find coordinates"); return null; } var x = res[0], y = res[1]; if (isNaN(x) || isNaN(y) || x >= 8 || y >= 8 || x < 0 || y < 0) { - console.log("ERROR: Unexpected values for x and y: " + x + ", " + y); + console.error(`Unexpected values (${x}, ${y}) for (x, y)`); return null; } return this.map[x][y]; @@ -866,7 +862,7 @@ HackingMission.prototype.getNodeFromElement = function(el) { function selectNode(hackMissionInst, el) { var nodeObj = hackMissionInst.getNodeFromElement(el); - if (nodeObj == null) {console.log("Error getting Node object");} + if (nodeObj == null) {console.error("Failed getting Node object");} if (!nodeObj.plyrCtrl) {return;} clearAllSelectedNodes(hackMissionInst); @@ -876,7 +872,7 @@ function selectNode(hackMissionInst, el) { function multiselectNode(hackMissionInst, el) { var nodeObj = hackMissionInst.getNodeFromElement(el); - if (nodeObj == null) {console.log("ERROR: Getting Node Object in multiselectNode()");} + if (nodeObj == null) {console.error("Failed getting Node Object in multiselectNode()");} if (!nodeObj.plyrCtrl) {return;} clearAllSelectedNodes(hackMissionInst); @@ -912,7 +908,7 @@ function clearAllSelectedNodes(hackMissionInst) { */ HackingMission.prototype.configurePlayerNodeElement = function(el) { var nodeObj = this.getNodeFromElement(el); - if (nodeObj == null) {console.log("Error getting Node object");} + if (nodeObj == null) {console.error("Failed getting Node object");} // Add event listener var self = this; @@ -1239,7 +1235,7 @@ HackingMission.prototype.processNode = function(nodeObj, numCycles=1) { calcStats = true; break; default: - console.log("ERR: Invalid Node Action: " + nodeObj.action); + console.error(`Invalid Node Action: ${nodeObj.action}`); break; } @@ -1452,7 +1448,7 @@ HackingMission.prototype.enemyAISelectAction = function(nodeObj) { targetNode = this.getNodeFromElement(nodeObj.conn.targetId); } if (targetNode == null) { - console.log("Error getting Target node Object in enemyAISelectAction()"); + console.error("Error getting Target node Object in enemyAISelectAction()"); } if (targetNode.def > this.enemyAtk + 15) { @@ -1529,9 +1525,6 @@ HackingMission.prototype.finishMission = function(win) { if (win) { var favorMult = 1 + (this.faction.favor / 100); - console.log("Hacking mission base reward: " + this.reward); - console.log("favorMult: " + favorMult); - console.log("rep mult: " + Player.faction_rep_mult); var gain = this.reward * Player.faction_rep_mult * favorMult; dialogBoxCreate("Mission won! You earned " + formatNumber(gain, 3) + " reputation with " + this.faction.name); diff --git a/src/Perk.js b/src/Perk.js index 7cdd105cd..54685a335 100644 --- a/src/Perk.js +++ b/src/Perk.js @@ -62,7 +62,7 @@ function Perk(name, reqRep, info) { Perk.prototype.setCompany = function(companyName) { if (this.factionPerk) { - console.log("ERR: Perk cannot be both faction and company perk"); + console.error("Perk cannot be both faction and company perk"); return; } this.companyPerk = true; @@ -71,7 +71,7 @@ Perk.prototype.setCompany = function(companyName) { Perk.prototype.setFaction = function(factionName) { if (this.companyPerk) { - console.log("ERR: Perk cannot be both faction and company perk"); + console.error("Perk cannot be both faction and company perk"); return; } this.factionPerk = true; @@ -145,7 +145,7 @@ applyPerk = function(perk) { case PerkNames.InsiderKnowledgeFactionPerk: break; default: - console.log("WARNING: Unrecognized perk: " + perk.name); + console.warn(`Unrecognized perk: ${perk.name}`); return; } } diff --git a/src/PersonObjects/Player/PlayerObjectGeneralMethods.js b/src/PersonObjects/Player/PlayerObjectGeneralMethods.js index 322be8475..0441113ee 100644 --- a/src/PersonObjects/Player/PlayerObjectGeneralMethods.js +++ b/src/PersonObjects/Player/PlayerObjectGeneralMethods.js @@ -726,7 +726,7 @@ export function workPartTime(numCycles) { var comp = Companies[this.companyName], companyRep = "0"; if (comp == null || !(comp instanceof Company)) { - console.log("ERROR: Could not find Company: " + this.companyName); + console.error(`Could not find Company: ${this.companyName}`); } else { companyRep = comp.playerReputation; } @@ -1417,8 +1417,7 @@ export function finishCrime(cancelled) { } } if(crime == null) { - console.log(this.crimeType); - dialogBoxCreate("ERR: Unrecognized crime type. This is probably a bug please contact the developer"); + dialogBoxCreate(`ERR: Unrecognized crime type (${this.crimeType}). This is probably a bug please contact the developer`); } this.gainMoney(this.workMoneyGained); this.recordMoneySource(this.workMoneyGained, "crime"); @@ -1529,7 +1528,7 @@ export function singularityStopWork() { res = this.finishCrime(true); break; default: - console.log("ERROR: Unrecognized work type"); + console.error(`Unrecognized work type (${this.workType})`); return ""; } return res; @@ -1840,7 +1839,7 @@ export function reapplyAllAugmentations(resetMultipliers=true) { const augName = this.augmentations[i].name; var aug = Augmentations[augName]; if (aug == null) { - console.log(`WARNING: Invalid augmentation name in Player.reapplyAllAugmentations(). Aug ${augName} will be skipped`); + console.warn(`Invalid augmentation name in Player.reapplyAllAugmentations(). Aug ${augName} will be skipped`); continue; } aug.owned = true; @@ -1862,7 +1861,7 @@ export function reapplyAllSourceFiles() { var srcFileKey = "SourceFile" + this.sourceFiles[i].n; var sourceFileObject = SourceFiles[srcFileKey]; if (sourceFileObject == null) { - console.log("ERROR: Invalid source file number: " + this.sourceFiles[i].n); + console.error(`Invalid source file number: ${this.sourceFiles[i].n}`); continue; } applySourceFile(this.sourceFiles[i]); @@ -2003,7 +2002,7 @@ export function checkForFactionInvitations() { var fulcrumsecrettechonologiesFac = Factions["Fulcrum Secret Technologies"]; var fulcrumSecretServer = AllServers[SpecialServerIps[SpecialServerNames.FulcrumSecretTechnologies]]; if (fulcrumSecretServer == null) { - console.log("ERROR: Could not find Fulcrum Secret Technologies Server"); + console.error("Could not find Fulcrum Secret Technologies Server"); } else { if (!fulcrumsecrettechonologiesFac.isBanned && !fulcrumsecrettechonologiesFac.isMember && !fulcrumsecrettechonologiesFac.alreadyInvited && @@ -2018,7 +2017,7 @@ export function checkForFactionInvitations() { var homeComp = this.getHomeComputer(); var bitrunnersServer = AllServers[SpecialServerIps[SpecialServerNames.BitRunnersServer]]; if (bitrunnersServer == null) { - console.log("ERROR: Could not find BitRunners Server"); + console.error("Could not find BitRunners Server"); } else if (!bitrunnersFac.isBanned && !bitrunnersFac.isMember && bitrunnersServer.manuallyHacked && !bitrunnersFac.alreadyInvited && this.hacking_skill >= 500 && homeComp.maxRam >= 128) { invitedFactions.push(bitrunnersFac); @@ -2028,7 +2027,7 @@ export function checkForFactionInvitations() { var theblackhandFac = Factions["The Black Hand"]; var blackhandServer = AllServers[SpecialServerIps[SpecialServerNames.TheBlackHandServer]]; if (blackhandServer == null) { - console.log("ERROR: Could not find The Black Hand Server"); + console.error("Could not find The Black Hand Server"); } else if (!theblackhandFac.isBanned && !theblackhandFac.isMember && blackhandServer.manuallyHacked && !theblackhandFac.alreadyInvited && this.hacking_skill >= 350 && homeComp.maxRam >= 64) { invitedFactions.push(theblackhandFac); @@ -2038,7 +2037,7 @@ export function checkForFactionInvitations() { var nitesecFac = Factions["NiteSec"]; var nitesecServer = AllServers[SpecialServerIps[SpecialServerNames.NiteSecServer]]; if (nitesecServer == null) { - console.log("ERROR: Could not find NiteSec Server"); + console.error("Could not find NiteSec Server"); } else if (!nitesecFac.isBanned && !nitesecFac.isMember && nitesecServer.manuallyHacked && !nitesecFac.alreadyInvited && this.hacking_skill >= 200 && homeComp.maxRam >= 32) { invitedFactions.push(nitesecFac); @@ -2182,7 +2181,7 @@ export function checkForFactionInvitations() { var cybersecFac = Factions["CyberSec"]; var cybersecServer = AllServers[SpecialServerIps[SpecialServerNames.CyberSecServer]]; if (cybersecServer == null) { - console.log("ERROR: Could not find CyberSec Server"); + console.error("Could not find CyberSec Server"); } else if (!cybersecFac.isBanned && !cybersecFac.isMember && cybersecServer.manuallyHacked && !cybersecFac.alreadyInvited && this.hacking_skill >= 50) { invitedFactions.push(cybersecFac); @@ -2199,14 +2198,14 @@ export function setBitNodeNumber(n) { export function queueAugmentation(name) { for(const i in this.queuedAugmentations) { if(this.queuedAugmentations[i].name == name) { - console.log('tried to queue '+name+' twice, this may be a bug'); + console.warn(`tried to queue ${name} twice, this may be a bug`); return; } } for(const i in this.augmentations) { if(this.augmentations[i].name == name) { - console.log('tried to queue '+name+' but we already have that aug'); + console.warn(`tried to queue ${name} twice, this may be a bug`); return; } } diff --git a/src/RedPill.js b/src/RedPill.js index 2556e77ba..761db5f72 100644 --- a/src/RedPill.js +++ b/src/RedPill.js @@ -96,7 +96,7 @@ function hackWorldDaemon(currentNodeNumber, flume=false) { }).then(function() { return loadBitVerse(currentNodeNumber, flume); }).catch(function(e){ - console.log("ERROR: " + e.toString()); + console.error(e.toString()); }); } @@ -104,7 +104,7 @@ function giveSourceFile(bitNodeNumber) { var sourceFileKey = "SourceFile"+ bitNodeNumber.toString(); var sourceFile = SourceFiles[sourceFileKey]; if (sourceFile == null) { - console.log("ERROR: could not find source file for Bit node: " + bitNodeNumber); + console.error(`Could not find source file for Bit node: ${bitNodeNumber}`); return; } @@ -264,7 +264,7 @@ function loadBitVerse(destroyedBitNodeNum, flume=false) { }).then(function() { return Promise.resolve(true); }).catch(function(e){ - console.log("ERROR: " + e.toString()); + console.error(e.toString()); }); } @@ -308,7 +308,6 @@ function createBitNodeYesNoEventListener(newBitNode, destroyedBitNode, flume=fal // Set new Bit Node Player.bitNodeN = newBitNode; - console.log(`Entering Bit Node ${Player.bitNodeN}`); // Reenable terminal $("#hack-progress-bar").attr('id', "old-hack-progress-bar"); diff --git a/src/SaveObject.js b/src/SaveObject.js index c5e957627..811e9b4a5 100755 --- a/src/SaveObject.js +++ b/src/SaveObject.js @@ -322,7 +322,7 @@ function loadImportedGame(saveObj, saveString) { try { tempAliases = JSON.parse(tempSaveObj.AliasesSave, Reviver); } catch(e) { - console.log("Parsing Aliases save failed: " + e); + console.error(`Parsing Aliases save failed: ${e}`); tempAliases = {}; } } else { @@ -332,7 +332,7 @@ function loadImportedGame(saveObj, saveString) { try { tempGlobalAliases = JSON.parse(tempSaveObj.AliasesSave, Reviver); } catch(e) { - console.log("Parsing Global Aliases save failed: " + e); + console.error(`Parsing Global Aliases save failed: ${e}`); tempGlobalAliases = {}; } } else { @@ -342,7 +342,7 @@ function loadImportedGame(saveObj, saveString) { try { tempMessages = JSON.parse(tempSaveObj.MessagesSave, Reviver); } catch(e) { - console.log("Parsing Messages save failed: " + e); + console.error(`Parsing Messages save failed: ${e}`); initMessages(); } } else { @@ -352,7 +352,7 @@ function loadImportedGame(saveObj, saveString) { try { tempStockMarket = JSON.parse(tempSaveObj.StockMarketSave, Reviver); } catch(e) { - console.log("Parsing StockMarket save failed: " + e); + console.error(`Parsing StockMarket save failed: ${e}`); tempStockMarket = {}; } } else { @@ -479,7 +479,6 @@ function loadImportedGame(saveObj, saveString) { gameOptionsBoxClose(); // Re-start game - console.log("Importing game"); Engine.setDisplayElements(); // Sets variables for important DOM elements Engine.init(); // Initialize buttons, work, etc. @@ -491,7 +490,6 @@ function loadImportedGame(saveObj, saveString) { // Process offline progress var offlineProductionFromScripts = loadAllRunningScripts(); // This also takes care of offline production for those scripts if (Player.isWorking) { - console.log("work() called in load() for " + numCyclesOffline * Engine._idleSpeed + " milliseconds"); if (Player.workType == CONSTANTS.WorkTypeFaction) { Player.workForFaction(numCyclesOffline); } else if (Player.workType == CONSTANTS.WorkTypeCreateProgram) { @@ -588,7 +586,7 @@ BitburnerSaveObject.prototype.deleteGame = function(db) { console.log("Successfully deleted save from indexedDb"); } request.onerror = function(e) { - console.log("Failed to delete save from indexedDb: " + e); + console.error(`Failed to delete save from indexedDb: ${e}`); } createStatusText("Game deleted!"); } diff --git a/src/Script/RamCalculations.js b/src/Script/RamCalculations.js index 5d2792a3c..8bffd43b4 100644 --- a/src/Script/RamCalculations.js +++ b/src/Script/RamCalculations.js @@ -167,7 +167,7 @@ async function parseOnlyRamCalculate(otherScripts, code, workerScript) { } return 0; } catch(e) { - console.log("ERROR applying function: " + e); + console.error(`Error applying function: ${e}`); return 0; } } else { diff --git a/src/Script/ScriptHelpers.js b/src/Script/ScriptHelpers.js index c30c6170f..17e3f7bd2 100644 --- a/src/Script/ScriptHelpers.js +++ b/src/Script/ScriptHelpers.js @@ -167,7 +167,6 @@ export function getCurrentEditor() { case EditorSetting.CodeMirror: return CodeMirrorEditor; default: - console.log(`Invalid Editor Setting: ${Settings.Editor}`); throw new Error(`Invalid Editor Setting: ${Settings.Editor}`); return null; } @@ -334,7 +333,6 @@ export function scriptCalculateOfflineProduction(runningScriptObj) { var serv = AllServers[ip]; if (serv == null) {continue;} var timesGrown = Math.round(0.5 * runningScriptObj.dataMap[ip][2] / runningScriptObj.onlineRunningTime * timePassed); - console.log(runningScriptObj.filename + " called grow() on " + serv.hostname + " " + timesGrown + " times while offline"); runningScriptObj.log("Called grow() on " + serv.hostname + " " + timesGrown + " times while offline"); var growth = processSingleServerGrowth(serv, timesGrown * 450, Player); runningScriptObj.log(serv.hostname + " grown by " + numeralWrapper.format(growth * 100 - 100, '0.000000%') + " from grow() calls made while offline"); @@ -356,7 +354,6 @@ export function scriptCalculateOfflineProduction(runningScriptObj) { totalOfflineProduction += production; Player.gainMoney(production); Player.recordMoneySource(production, "hacking"); - console.log(runningScriptObj.filename + " generated $" + production + " while offline by hacking " + serv.hostname); runningScriptObj.log(runningScriptObj.filename + " generated $" + production + " while offline by hacking " + serv.hostname); serv.moneyAvailable -= production; if (serv.moneyAvailable < 0) {serv.moneyAvailable = 0;} @@ -383,7 +380,6 @@ export function scriptCalculateOfflineProduction(runningScriptObj) { var serv = AllServers[ip]; if (serv == null) {continue;} var timesHacked = Math.round(0.5 * runningScriptObj.dataMap[ip][1] / runningScriptObj.onlineRunningTime * timePassed); - console.log(runningScriptObj.filename + " hacked " + serv.hostname + " " + timesHacked + " times while offline"); runningScriptObj.log("Hacked " + serv.hostname + " " + timesHacked + " times while offline"); serv.fortify(CONSTANTS.ServerFortifyAmount * timesHacked); } @@ -396,7 +392,6 @@ export function scriptCalculateOfflineProduction(runningScriptObj) { var serv = AllServers[ip]; if (serv == null) {continue;} var timesWeakened = Math.round(0.5 * runningScriptObj.dataMap[ip][3] / runningScriptObj.onlineRunningTime * timePassed); - console.log(runningScriptObj.filename + " called weaken() on " + serv.hostname + " " + timesWeakened + " times while offline"); runningScriptObj.log("Called weaken() on " + serv.hostname + " " + timesWeakened + " times while offline"); serv.weaken(CONSTANTS.ServerWeakenAmount * timesWeakened); } diff --git a/src/Server/ServerHelpers.ts b/src/Server/ServerHelpers.ts index 6be47e424..dc690d378 100644 --- a/src/Server/ServerHelpers.ts +++ b/src/Server/ServerHelpers.ts @@ -74,7 +74,7 @@ export function processSingleServerGrowth(server: Server, numCycles: number, p: //Apply serverGrowth for the calculated number of growth cycles let serverGrowth = Math.pow(adjGrowthRate, numServerGrowthCyclesAdjusted * p.hacking_grow_mult); if (serverGrowth < 1) { - console.log("WARN: serverGrowth calculated to be less than 1"); + console.warn("serverGrowth calculated to be less than 1"); serverGrowth = 1; } diff --git a/src/SourceFile/applySourceFile.ts b/src/SourceFile/applySourceFile.ts index e38b014ec..45f4c839f 100644 --- a/src/SourceFile/applySourceFile.ts +++ b/src/SourceFile/applySourceFile.ts @@ -168,7 +168,7 @@ export function applySourceFile(srcFile: PlayerOwnedSourceFile) { Player.work_money_mult *= inc; break; default: - console.log("ERROR: Invalid source file number: " + srcFile.n); + console.error(`Invalid source file number: ${srcFile.n}`); break; } diff --git a/src/Terminal.js b/src/Terminal.js index 1a611086b..d52877d5c 100644 --- a/src/Terminal.js +++ b/src/Terminal.js @@ -1766,7 +1766,6 @@ let Terminal = { }`; } - console.log('default code'); Engine.loadScriptEditorContent(filepath, code); } else { Engine.loadScriptEditorContent(filepath, script.code); diff --git a/src/engine.jsx b/src/engine.jsx index 35f3c6966..8c9479e48 100644 --- a/src/engine.jsx +++ b/src/engine.jsx @@ -1079,7 +1079,6 @@ const Engine = { // Process offline progress var offlineProductionFromScripts = loadAllRunningScripts(); // This also takes care of offline production for those scripts if (Player.isWorking) { - console.log("work() called in load() for " + numCyclesOffline * Engine._idleSpeed + " milliseconds"); if (Player.workType == CONSTANTS.WorkTypeFaction) { Player.workForFaction(numCyclesOffline); } else if (Player.workType == CONSTANTS.WorkTypeCreateProgram) { @@ -1180,7 +1179,6 @@ const Engine = { Engine.closeMainMenuHeader(visibleMenuTabs); } else { // No save found, start new game - console.log("Initializing new game"); initBitNodeMultipliers(Player); initSpecialServerIps(); Engine.setDisplayElements(); // Sets variables for important DOM elements @@ -1525,7 +1523,6 @@ const Engine = { // DEBUG Delete active Scripts on home document.getElementById("debug-delete-scripts-link").addEventListener("click", function() { - console.log("Deleting running scripts on home computer"); Player.getHomeComputer().runningScripts = []; dialogBoxCreate("Forcefully deleted all running scripts on home computer. Please save and refresh page"); gameOptionsBoxClose(); From c285d494b9a82ffed490c9db744ba49a1203af3d Mon Sep 17 00:00:00 2001 From: Olivier Gagnon Date: Sun, 7 Mar 2021 22:49:55 -0500 Subject: [PATCH 08/19] update lodash --- package-lock.json | 190 +++++++++++++++++++++++++++++++++++++++++----- package.json | 2 +- 2 files changed, 170 insertions(+), 22 deletions(-) diff --git a/package-lock.json b/package-lock.json index 4de59b61a..83f71734c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,11 +1,11 @@ { "name": "bitburner", - "version": "0.47.0", + "version": "0.47.3", "lockfileVersion": 2, "requires": true, "packages": { "": { - "version": "0.47.0", + "version": "0.47.3", "hasInstallScript": true, "license": "SEE LICENSE IN license.txt", "dependencies": { @@ -67,7 +67,7 @@ "json5": "^1.0.1", "less": "^3.9.0", "less-loader": "^4.1.0", - "lodash": "^4.17.10", + "lodash": "^4.17.21", "mini-css-extract-plugin": "^0.4.1", "mkdirp": "^0.5.1", "mocha": "^6.1.4", @@ -1225,6 +1225,11 @@ "integrity": "sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg==", "dev": true }, + "node_modules/async/node_modules/lodash": { + "version": "4.17.10", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz", + "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==" + }, "node_modules/asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", @@ -1501,6 +1506,12 @@ "platform": "1.3.5" } }, + "node_modules/benchmark/node_modules/lodash": { + "version": "4.17.10", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz", + "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==", + "dev": true + }, "node_modules/big.js": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/big.js/-/big.js-3.2.0.tgz", @@ -4379,6 +4390,12 @@ "js-yaml": "bin/js-yaml.js" } }, + "node_modules/eslint/node_modules/lodash": { + "version": "4.17.10", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz", + "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==", + "dev": true + }, "node_modules/eslint/node_modules/strip-ansi": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", @@ -5607,6 +5624,12 @@ "node": "*" } }, + "node_modules/globule/node_modules/lodash": { + "version": "4.17.10", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz", + "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==", + "dev": true + }, "node_modules/gonzales-pe": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/gonzales-pe/-/gonzales-pe-4.2.3.tgz", @@ -6040,6 +6063,12 @@ "object-assign": "4.1.1" } }, + "node_modules/html-webpack-plugin/node_modules/lodash": { + "version": "4.17.10", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz", + "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==", + "dev": true + }, "node_modules/htmlparser2": { "version": "3.9.2", "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.9.2.tgz", @@ -6402,6 +6431,12 @@ "node": ">=4" } }, + "node_modules/inquirer/node_modules/lodash": { + "version": "4.17.10", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz", + "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==", + "dev": true + }, "node_modules/inquirer/node_modules/strip-ansi": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", @@ -7652,9 +7687,10 @@ } }, "node_modules/lodash": { - "version": "4.17.10", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz", - "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==" + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true }, "node_modules/lodash.camelcase": { "version": "4.3.0", @@ -8982,6 +9018,12 @@ "node": ">=4" } }, + "node_modules/mochapack/node_modules/lodash": { + "version": "4.17.10", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz", + "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==", + "dev": true + }, "node_modules/mochapack/node_modules/pify": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", @@ -9507,12 +9549,6 @@ "node": "*" } }, - "node_modules/node-sass/node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "dev": true - }, "node_modules/node-sass/node_modules/path-key": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", @@ -11029,6 +11065,12 @@ "node": ">=4" } }, + "node_modules/postcss-reporter/node_modules/lodash": { + "version": "4.17.10", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz", + "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==", + "dev": true + }, "node_modules/postcss-reporter/node_modules/postcss": { "version": "6.0.23", "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", @@ -11283,6 +11325,12 @@ "node": ">=4" } }, + "node_modules/postcss-sorting/node_modules/lodash": { + "version": "4.17.10", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz", + "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==", + "dev": true + }, "node_modules/postcss-sorting/node_modules/postcss": { "version": "6.0.23", "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", @@ -14079,6 +14127,12 @@ "node": ">=4" } }, + "node_modules/stylelint-order/node_modules/lodash": { + "version": "4.17.10", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz", + "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==", + "dev": true + }, "node_modules/stylelint-order/node_modules/postcss": { "version": "6.0.23", "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", @@ -14335,6 +14389,12 @@ "node": ">=4" } }, + "node_modules/stylelint/node_modules/lodash": { + "version": "4.17.10", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz", + "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==", + "dev": true + }, "node_modules/stylelint/node_modules/map-obj": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-2.0.0.tgz", @@ -14724,6 +14784,12 @@ "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", "dev": true }, + "node_modules/table/node_modules/lodash": { + "version": "4.17.10", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz", + "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==", + "dev": true + }, "node_modules/tapable": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.0.0.tgz", @@ -16144,6 +16210,12 @@ "node": ">=6.0.0" } }, + "node_modules/webpack-cli/node_modules/lodash": { + "version": "4.17.10", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz", + "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==", + "dev": true + }, "node_modules/webpack-cli/node_modules/strip-ansi": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", @@ -18457,6 +18529,13 @@ "integrity": "sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ==", "requires": { "lodash": "4.17.10" + }, + "dependencies": { + "lodash": { + "version": "4.17.10", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz", + "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==" + } } }, "async-each": { @@ -18711,6 +18790,14 @@ "requires": { "lodash": "4.17.10", "platform": "1.3.5" + }, + "dependencies": { + "lodash": { + "version": "4.17.10", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz", + "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==", + "dev": true + } } }, "big.js": { @@ -21164,6 +21251,12 @@ "esprima": "4.0.0" } }, + "lodash": { + "version": "4.17.10", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz", + "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==", + "dev": true + }, "strip-ansi": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", @@ -22223,6 +22316,12 @@ "once": "1.4.0", "path-is-absolute": "1.0.1" } + }, + "lodash": { + "version": "4.17.10", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz", + "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==", + "dev": true } } }, @@ -22580,6 +22679,12 @@ "json5": "0.5.1", "object-assign": "4.1.1" } + }, + "lodash": { + "version": "4.17.10", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz", + "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==", + "dev": true } } }, @@ -22882,6 +22987,12 @@ "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", "dev": true }, + "lodash": { + "version": "4.17.10", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz", + "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==", + "dev": true + }, "strip-ansi": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", @@ -23908,9 +24019,10 @@ } }, "lodash": { - "version": "4.17.10", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz", - "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==" + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true }, "lodash.camelcase": { "version": "4.3.0", @@ -24999,6 +25111,12 @@ "slash": "1.0.0" } }, + "lodash": { + "version": "4.17.10", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz", + "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==", + "dev": true + }, "pify": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", @@ -25416,12 +25534,6 @@ "path-is-absolute": "1.0.1" } }, - "lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "dev": true - }, "path-key": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", @@ -26731,6 +26843,12 @@ "supports-color": "5.4.0" } }, + "lodash": { + "version": "4.17.10", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz", + "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==", + "dev": true + }, "postcss": { "version": "6.0.23", "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", @@ -26942,6 +27060,12 @@ "supports-color": "5.4.0" } }, + "lodash": { + "version": "4.17.10", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz", + "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==", + "dev": true + }, "postcss": { "version": "6.0.23", "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", @@ -29479,6 +29603,12 @@ "strip-bom": "3.0.0" } }, + "lodash": { + "version": "4.17.10", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz", + "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==", + "dev": true + }, "map-obj": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-2.0.0.tgz", @@ -29676,6 +29806,12 @@ "supports-color": "5.4.0" } }, + "lodash": { + "version": "4.17.10", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz", + "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==", + "dev": true + }, "postcss": { "version": "6.0.23", "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", @@ -29854,6 +29990,12 @@ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", "dev": true + }, + "lodash": { + "version": "4.17.10", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz", + "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==", + "dev": true } } }, @@ -31120,6 +31262,12 @@ "through": "2.3.8" } }, + "lodash": { + "version": "4.17.10", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz", + "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==", + "dev": true + }, "strip-ansi": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", diff --git a/package.json b/package.json index da9769668..f6b40fdfe 100644 --- a/package.json +++ b/package.json @@ -65,7 +65,7 @@ "json5": "^1.0.1", "less": "^3.9.0", "less-loader": "^4.1.0", - "lodash": "^4.17.10", + "lodash": "^4.17.21", "mini-css-extract-plugin": "^0.4.1", "mkdirp": "^0.5.1", "mocha": "^6.1.4", From d9aef91ea3fc69c0804bf9ca5bcd6f46347674b5 Mon Sep 17 00:00:00 2001 From: Olivier Gagnon Date: Mon, 8 Mar 2021 15:30:05 -0500 Subject: [PATCH 09/19] Fix changelog --- doc/source/changelog.rst | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/doc/source/changelog.rst b/doc/source/changelog.rst index 0a11ebd0a..2301f7b4a 100644 --- a/doc/source/changelog.rst +++ b/doc/source/changelog.rst @@ -4,14 +4,16 @@ Changelog ========= -v0.48.0 - ASCII - 2020-03-07 +v0.48.0 - ASCII - 2020-03-07 (hydroflame) ------- **ASCII** + * Travel Agency now displays a world map * Cities are now top view of metro station maps **Netscript** + * 'softReset' is a new netscript function that performs a soft reset regardless of if the player has bought augmentations or not. * 'getAugmentationStats' is a new netscript function that returns the stats of @@ -22,11 +24,13 @@ v0.48.0 - ASCII - 2020-03-07 * 'hacknet.maxNumNodes' returns the maximum number of hacknet nodes. **Bladeburner** + * Current stamina will scale as max stamina increases, this prevents players from having very high penalty when they gain huge amount of exp at the start of a reset. **Misc.** + * Fixed an issue where SF3 was listed as infinitly repeatable and SF12 as having a limit of 3. * Fixed an issue where the gang equipment screen would freeze the game if a From 250841df6671ef5aaca867ecd07b84a71aa125fa Mon Sep 17 00:00:00 2001 From: Olivier Gagnon Date: Mon, 8 Mar 2021 20:31:34 -0500 Subject: [PATCH 10/19] Added sf minus 1, exploits --- .../InstalledAugmentationsAndSourceFiles.tsx | 2 + src/Augmentation/ui/SourceFileMinus1.tsx | 44 +++++++++++++++++++ src/Exploits/Exploit.ts | 25 +++++++++++ src/Exploits/applyExploits.ts | 42 ++++++++++++++++++ src/Exploits/tampering.ts | 11 +++++ src/NetscriptFunctions.js | 4 ++ src/PersonObjects/IPlayer.ts | 3 ++ src/PersonObjects/Player/PlayerObject.js | 2 + .../Player/PlayerObjectGeneralMethods.js | 8 ++++ src/Player.js | 3 ++ src/engine.jsx | 1 + 11 files changed, 145 insertions(+) create mode 100644 src/Augmentation/ui/SourceFileMinus1.tsx create mode 100644 src/Exploits/Exploit.ts create mode 100644 src/Exploits/applyExploits.ts create mode 100644 src/Exploits/tampering.ts diff --git a/src/Augmentation/ui/InstalledAugmentationsAndSourceFiles.tsx b/src/Augmentation/ui/InstalledAugmentationsAndSourceFiles.tsx index 7246ed6a8..35bf07ba8 100644 --- a/src/Augmentation/ui/InstalledAugmentationsAndSourceFiles.tsx +++ b/src/Augmentation/ui/InstalledAugmentationsAndSourceFiles.tsx @@ -10,6 +10,7 @@ import * as React from "react"; import { InstalledAugmentations } from "./InstalledAugmentations"; import { ListConfiguration } from "./ListConfiguration"; import { OwnedSourceFiles } from "./OwnedSourceFiles"; +import { SourceFileMinus1 } from "./SourceFileMinus1"; import { Settings } from "../../Settings/Settings"; import { OwnedAugmentationsOrderSetting } from "../../Settings/SettingEnums"; @@ -98,6 +99,7 @@ export class InstalledAugmentationsAndSourceFiles extends React.Component
    +
diff --git a/src/Augmentation/ui/SourceFileMinus1.tsx b/src/Augmentation/ui/SourceFileMinus1.tsx new file mode 100644 index 000000000..b97bcbf40 --- /dev/null +++ b/src/Augmentation/ui/SourceFileMinus1.tsx @@ -0,0 +1,44 @@ +/** + * React Component for displaying a list of the player's Source-Files + * on the Augmentations UI + */ +import * as React from "react"; + +import { Player } from "../../Player"; +import { Settings } from "../../Settings/Settings"; +import { OwnedAugmentationsOrderSetting } from "../../Settings/SettingEnums"; +import { SourceFiles } from "../../SourceFile/SourceFiles"; +import { Exploit, ExploitName } from "../../Exploits/Exploit"; + +import { Accordion } from "../../ui/React/Accordion"; + +export function SourceFileMinus1(): React.ReactElement { + let exploits = Player.exploits; + + if(exploits.length === 0) { + return <> + } + + return (
  • + + Source-File -1: Exploits in the BitNodes +
    + Level {exploits.length} / ? + + } + panelContent={ + <> +

    This Source-File can only be acquired with obscure knowledge of the game, javascript, and the web ecosystem.

    +

    It increases all of the player's multipliers by 0.1%


    + +

    You have found the following exploits:

    +
      + {exploits.map((c: Exploit) =>
    • * {ExploitName(c)}
    • )} +
    + + } + /> +
  • ) +} diff --git a/src/Exploits/Exploit.ts b/src/Exploits/Exploit.ts new file mode 100644 index 000000000..9df93e339 --- /dev/null +++ b/src/Exploits/Exploit.ts @@ -0,0 +1,25 @@ +/* +*/ + +export enum Exploit { + UndocumentedFunctionCall = 'UndocumentedFunctionCall', + EditSaveFile = 'EditSaveFile', + PrototypeTampering = 'PrototypeTampering' +} + +const names: { + [key: string]: string; +} = { + 'UndocumentedFunctionCall': 'by looking beyond the documentation.', + 'EditSaveFile': 'by editing your save file.', + 'PrototypeTampering': 'by tampering with Numbers prototype.', +} + + +export function ExploitName(exploit: string): string { + return names[exploit]; +} + +export function sanitizeExploits(exploits: string[]): string[] { + return exploits.filter((e: string) => Object.keys(Exploit).includes(e)); +} \ No newline at end of file diff --git a/src/Exploits/applyExploits.ts b/src/Exploits/applyExploits.ts new file mode 100644 index 000000000..c2671b025 --- /dev/null +++ b/src/Exploits/applyExploits.ts @@ -0,0 +1,42 @@ +import { Player } from "../Player"; + +export function applyExploit() { + if (Player.exploits && Player.exploits.length === 0) { + return; + } + const inc = Math.pow(1.0001, Player.exploits.length); + const dec = Math.pow(0.9999, Player.exploits.length); + + Player.hacking_chance_mult *= inc; + Player.hacking_speed_mult *= inc; + Player.hacking_money_mult *= inc; + Player.hacking_grow_mult *= inc; + Player.hacking_mult *= inc; + + Player.strength_mult *= inc; + Player.defense_mult *= inc; + Player.dexterity_mult *= inc; + Player.agility_mult *= inc; + Player.charisma_mult *= inc; + + Player.hacking_exp_mult *= inc; + Player.strength_exp_mult *= inc; + Player.defense_exp_mult *= inc; + Player.dexterity_exp_mult *= inc; + Player.agility_exp_mult *= inc; + Player.charisma_exp_mult *= inc; + + Player.company_rep_mult *= inc; + Player.faction_rep_mult *= inc; + + Player.crime_money_mult *= inc; + Player.crime_success_mult *= inc; + + Player.hacknet_node_money_mult *= inc; + Player.hacknet_node_purchase_cost_mult *= dec; + Player.hacknet_node_ram_cost_mult *= dec; + Player.hacknet_node_core_cost_mult *= dec; + Player.hacknet_node_level_cost_mult *= dec; + + Player.work_money_mult *= inc; +} diff --git a/src/Exploits/tampering.ts b/src/Exploits/tampering.ts new file mode 100644 index 000000000..23a20ed3b --- /dev/null +++ b/src/Exploits/tampering.ts @@ -0,0 +1,11 @@ +import { Player } from "../Player"; +import { Exploit } from "./Exploit"; + +(function() { + const a = 55; + setInterval(function() { + if (a.toExponential() !== "5.5e+1") { + Player.giveExploit(Exploit.PrototypeTampering); + } + }, 15*60*1000); // 15 minutes +})() \ No newline at end of file diff --git a/src/NetscriptFunctions.js b/src/NetscriptFunctions.js index acec50ca4..01b5bff19 100644 --- a/src/NetscriptFunctions.js +++ b/src/NetscriptFunctions.js @@ -142,6 +142,7 @@ import { import { NetscriptPort } from "./NetscriptPort"; import { SleeveTaskType } from "./PersonObjects/Sleeve/SleeveTaskTypesEnum"; import { findSleevePurchasableAugs } from "./PersonObjects/Sleeve/SleeveHelpers"; +import { Exploit } from './Exploits/Exploit.ts'; import { Page, routing } from "./ui/navigationTracking"; import { numeralWrapper } from "./ui/numeralFormat"; @@ -4713,6 +4714,9 @@ function NetscriptFunctions(workerScript) { break: function() { return Player.karma; } + }, + exploit: function() { + Player.giveExploit(Exploit.UndocumentedFunctionCall); } } // End return } // End NetscriptFunction() diff --git a/src/PersonObjects/IPlayer.ts b/src/PersonObjects/IPlayer.ts index eb1a853ca..361ed2212 100644 --- a/src/PersonObjects/IPlayer.ts +++ b/src/PersonObjects/IPlayer.ts @@ -19,6 +19,7 @@ import { LocationName } from "../Locations/data/LocationNames"; import { Server } from "../Server/Server"; import { IPlayerOwnedSourceFile } from "../SourceFile/PlayerOwnedSourceFile"; import { MoneySourceTracker } from "../utils/MoneySourceTracker"; +import { Exploit } from "../Exploits/Exploit"; export interface IPlayer { // Class members @@ -56,6 +57,7 @@ export interface IPlayer { sleeves: Sleeve[]; sleevesFromCovenant: number; sourceFiles: IPlayerOwnedSourceFile[]; + exploits: Exploit[]; totalPlaytime: number; // Stats @@ -173,4 +175,5 @@ export interface IPlayer { startWork(companyName: string): void; startWorkPartTime(companyName: string): void; travel(to: CityName): boolean; + giveExploit(exploit: Exploit): void; } diff --git a/src/PersonObjects/Player/PlayerObject.js b/src/PersonObjects/Player/PlayerObject.js index fd3044bf5..c3b736719 100644 --- a/src/PersonObjects/Player/PlayerObject.js +++ b/src/PersonObjects/Player/PlayerObject.js @@ -201,6 +201,8 @@ export function PlayerObject() { // Production since last Augmentation installation this.scriptProdSinceLastAug = 0; + + this.exploits = []; }; // Apply player methods to the prototype using Object.assign() diff --git a/src/PersonObjects/Player/PlayerObjectGeneralMethods.js b/src/PersonObjects/Player/PlayerObjectGeneralMethods.js index 0441113ee..2cf3d7ac1 100644 --- a/src/PersonObjects/Player/PlayerObjectGeneralMethods.js +++ b/src/PersonObjects/Player/PlayerObjectGeneralMethods.js @@ -37,6 +37,7 @@ import { safetlyCreateUniqueServer } from "../../Server/ServerHelpers"; import { Settings } from "../../Settings/Settings"; import { SpecialServerIps, SpecialServerNames } from "../../Server/SpecialServerIps"; import { applySourceFile } from "../../SourceFile/applySourceFile"; +import { applyExploit } from "../../Exploits/applyExploits"; import { SourceFiles } from "../../SourceFile/SourceFiles"; import { SourceFileFlags } from "../../SourceFile/SourceFileFlags"; import { influenceStockThroughCompanyWork } from "../../StockMarket/PlayerInfluencing"; @@ -1866,6 +1867,7 @@ export function reapplyAllSourceFiles() { } applySourceFile(this.sourceFiles[i]); } + applyExploit(); } /*************** Check for Faction Invitations *************/ @@ -2298,3 +2300,9 @@ export function gotoLocation(to) { export function canAccessResleeving() { return this.bitNodeN === 10 || (SourceFileFlags[10] > 0); } + +export function giveExploit(exploit) { + if(!this.exploits.includes(exploit)) { + this.exploits.push(exploit); + } +} \ No newline at end of file diff --git a/src/Player.js b/src/Player.js index afa0d53af..1353d9081 100644 --- a/src/Player.js +++ b/src/Player.js @@ -1,5 +1,6 @@ import { Corporation } from "./Corporation/Corporation"; import { PlayerObject } from "./PersonObjects/Player/PlayerObject"; +import { sanitizeExploits } from "./Exploits/Exploit"; import { Reviver } from "../utils/JSONReviver"; @@ -26,4 +27,6 @@ export function loadPlayer(saveString) { ind.thisCycleExpenses = new Decimal(ind.thisCycleExpenses); } } + + Player.exploits = sanitizeExploits(Player.exploits); } diff --git a/src/engine.jsx b/src/engine.jsx index 8c9479e48..c76521969 100644 --- a/src/engine.jsx +++ b/src/engine.jsx @@ -102,6 +102,7 @@ import { createElement } from "../utils/uiHelpers/createElement"; import { exceptionAlert } from "../utils/helpers/exceptionAlert"; import { removeLoadingScreen } from "../utils/uiHelpers/removeLoadingScreen"; import { KEY } from "../utils/helpers/keyCodes"; +import "./Exploits/tampering"; import React from "react"; import ReactDOM from "react-dom"; From af584e8c873601e6f1b0820430be3ee8e30c10ea Mon Sep 17 00:00:00 2001 From: Olivier Gagnon Date: Tue, 9 Mar 2021 23:22:05 -0500 Subject: [PATCH 11/19] Removed CharacterInfo maximum hacknet, styling in the options, comments in exploits --- css/styles.scss | 35 ++++++++++++++++++++++++++++ src/Exploits/Exploit.ts | 16 +++++++++++-- src/Hacknet/HacknetHelpers.jsx | 2 +- src/index.html | 28 +++++++++++------------ src/ui/CharacterInfo.tsx | 3 +-- src/ui/setSettingsLabels.js | 42 ++++++++++++++++++++-------------- 6 files changed, 90 insertions(+), 36 deletions(-) diff --git a/css/styles.scss b/css/styles.scss index ea543e3e9..b6b876b1d 100644 --- a/css/styles.scss +++ b/css/styles.scss @@ -359,3 +359,38 @@ a:visited { .smallfont { font-size: $defaultFontSize * 0.8125; } + + +.optionCheckbox { + filter: invert(100%) hue-rotate(0deg) brightness(1.7); + margin: 5px; + float: right; +} + +.optionRange { + -webkit-appearance: none; + background: #777; + outline: none; + opacity: 0.7; + height: 10px; + -webkit-transition: .2s; + transition: opacity .2s; + margin: 3px; +} + + +.optionRange::-webkit-slider-thumb { + -webkit-appearance: none; + appearance: none; + width: 10px; + height: 10px; + background: var(--my-font-color); + cursor: pointer; +} + +.optionRange::-moz-range-thumb { + width: 10px; + height: 10px; + background: var(--my-font-color); + cursor: pointer; +} \ No newline at end of file diff --git a/src/Exploits/Exploit.ts b/src/Exploits/Exploit.ts index 9df93e339..2e687b862 100644 --- a/src/Exploits/Exploit.ts +++ b/src/Exploits/Exploit.ts @@ -1,10 +1,22 @@ /* +The game cannot block every possible exploits. Specially since one of them is +that you can just edit your save file and that's impragmatic to prevent. + +So instead we have source file minus 1. It is not obtained by destroying a +BitNode but instead it is awarded when the player finds innovative ways to break +the game, this serves 2 purpose, [one] the developpers don't have to spend time +trying to implement anti-cheat measures and [two] finding ways to break a +hacking game is very much in the spirit of the game. +Source-File minus 1 is extremely weak because it can be fully level up quickly. */ export enum Exploit { UndocumentedFunctionCall = 'UndocumentedFunctionCall', - EditSaveFile = 'EditSaveFile', - PrototypeTampering = 'PrototypeTampering' + PrototypeTampering = 'PrototypeTampering', + // To the players reading this. Yes you're supposed to add EditSaveFile by + // editing your save file, yes you could add them all, no we don't care + // that's not the point + EditSaveFile = 'EditSaveFile' } const names: { diff --git a/src/Hacknet/HacknetHelpers.jsx b/src/Hacknet/HacknetHelpers.jsx index 6172593e2..b16021858 100644 --- a/src/Hacknet/HacknetHelpers.jsx +++ b/src/Hacknet/HacknetHelpers.jsx @@ -120,7 +120,7 @@ export function getCostOfNextHacknetServer() { const numOwned = Player.hacknetNodes.length; const mult = HacknetServerPurchaseMult; - if (numOwned > MaxNumberHacknetServers) { return Infinity; } + if (numOwned >= MaxNumberHacknetServers) { return Infinity; } return BaseCostForHacknetServer * Math.pow(mult, numOwned) * Player.hacknet_node_purchase_cost_mult; } diff --git a/src/index.html b/src/index.html index 2bf3f9991..fb7af1c5c 100644 --- a/src/index.html +++ b/src/index.html @@ -406,7 +406,7 @@ if (htmlWebpackPlugin.options.googleAnalytics.trackingId) { %>
    -
    -
    -
    -
    @@ -467,7 +467,7 @@ if (htmlWebpackPlugin.options.googleAnalytics.trackingId) { %> and can be viewed with the 'cat' Terminal command. - + @@ -478,7 +478,7 @@ if (htmlWebpackPlugin.options.googleAnalytics.trackingId) { %> on the screen. Your outstanding faction invites can be viewed in the 'Factions' page. - + @@ -488,7 +488,7 @@ if (htmlWebpackPlugin.options.googleAnalytics.trackingId) { %> If this is set, the confirmation message before traveling will not show up. You will automatically be deducted the travel cost as soon as you click. - + @@ -499,7 +499,7 @@ if (htmlWebpackPlugin.options.googleAnalytics.trackingId) { %> If this is set, the confirmation message before buying augmentation will not show up. - + @@ -509,7 +509,7 @@ if (htmlWebpackPlugin.options.googleAnalytics.trackingId) { %> If this is set, a popup message will no longer be shown when you are hospitalized after taking too much damage. - + @@ -521,7 +521,7 @@ if (htmlWebpackPlugin.options.googleAnalytics.trackingId) { %> and the "Save and Close (Ctrl + b)" hotkey in the Text Editor. - + diff --git a/src/ui/CharacterInfo.tsx b/src/ui/CharacterInfo.tsx index b50dc5607..4383f24ba 100644 --- a/src/ui/CharacterInfo.tsx +++ b/src/ui/CharacterInfo.tsx @@ -11,7 +11,6 @@ import { SourceFileFlags } from "../SourceFile/SourceFileFlags"; import { getPurchaseServerLimit } from "../Server/ServerPurchases"; import { MaxNumberHacknetServers } from "../Hacknet/HacknetServer"; - export function CharacterInfo(p: IPlayer): React.ReactElement { function LastEmployer(): React.ReactElement { if (p.companyName) { @@ -225,7 +224,7 @@ export function CharacterInfo(p: IPlayer): React.ReactElement { Misc.

    Servers owned: {p.purchasedServers.length} / {getPurchaseServerLimit()}
    - Hacknet Nodes owned: {p.hacknetNodes.length} / {MaxNumberHacknetServers}
    + Hacknet Nodes owned: {p.hacknetNodes.length}
    Augmentations installed: {p.augmentations.length}
    Time played since last Augmentation: {convertTimeMsToTimeElapsedString(p.playtimeSinceLastAug)}
    diff --git a/src/ui/setSettingsLabels.js b/src/ui/setSettingsLabels.js index 64010fddb..f3b96de1a 100644 --- a/src/ui/setSettingsLabels.js +++ b/src/ui/setSettingsLabels.js @@ -5,17 +5,25 @@ import {numeralWrapper} from "./numeralFormat"; function setSettingsLabels() { - var nsExecTime = document.getElementById("settingsNSExecTimeRangeValLabel"); - var nsLogLimit = document.getElementById("settingsNSLogRangeValLabel"); - var nsPortLimit = document.getElementById("settingsNSPortRangeValLabel"); - var suppressMsgs = document.getElementById("settingsSuppressMessages"); - var suppressFactionInv = document.getElementById("settingsSuppressFactionInvites") - var suppressTravelConfirmation = document.getElementById("settingsSuppressTravelConfirmation"); - var suppressBuyAugmentationConfirmation = document.getElementById("settingsSuppressBuyAugmentationConfirmation"); - var suppressHospitalizationPopup = document.getElementById("settingsSuppressHospitalizationPopup"); - var autosaveInterval = document.getElementById("settingsAutosaveIntervalValLabel"); - var disableHotkeys = document.getElementById("settingsDisableHotkeys"); - var locale = document.getElementById("settingsLocale"); + function setAutosaveLabel(elem) { + if(Settings.AutosaveInterval === 0) { + elem.innerHTML = `disabled`; + } else { + elem.innerHTML = `every ${Settings.AutosaveInterval}s`; + } + } + + const nsExecTime = document.getElementById("settingsNSExecTimeRangeValLabel"); + const nsLogLimit = document.getElementById("settingsNSLogRangeValLabel"); + const nsPortLimit = document.getElementById("settingsNSPortRangeValLabel"); + const suppressMsgs = document.getElementById("settingsSuppressMessages"); + const suppressFactionInv = document.getElementById("settingsSuppressFactionInvites") + const suppressTravelConfirmation = document.getElementById("settingsSuppressTravelConfirmation"); + const suppressBuyAugmentationConfirmation = document.getElementById("settingsSuppressBuyAugmentationConfirmation"); + const suppressHospitalizationPopup = document.getElementById("settingsSuppressHospitalizationPopup"); + const autosaveInterval = document.getElementById("settingsAutosaveIntervalValLabel"); + const disableHotkeys = document.getElementById("settingsDisableHotkeys"); + const locale = document.getElementById("settingsLocale"); //Initialize values on labels nsExecTime.innerHTML = Settings.CodeInstructionRunTime + "ms"; @@ -26,16 +34,16 @@ function setSettingsLabels() { suppressTravelConfirmation.checked = Settings.SuppressTravelConfirmation; suppressBuyAugmentationConfirmation.checked = Settings.SuppressBuyAugmentationConfirmation; suppressHospitalizationPopup.checked = Settings.SuppressHospitalizationPopup; - autosaveInterval.innerHTML = Settings.AutosaveInterval; + setAutosaveLabel(autosaveInterval); disableHotkeys.checked = Settings.DisableHotkeys; locale.value = Settings.Locale; numeralWrapper.updateLocale(Settings.Locale); //Initialize locale //Set handlers for when input changes for sliders - var nsExecTimeInput = document.getElementById("settingsNSExecTimeRangeVal"); - var nsLogRangeInput = document.getElementById("settingsNSLogRangeVal"); - var nsPortRangeInput = document.getElementById("settingsNSPortRangeVal"); - var nsAutosaveIntervalInput = document.getElementById("settingsAutosaveIntervalVal"); + const nsExecTimeInput = document.getElementById("settingsNSExecTimeRangeVal"); + const nsLogRangeInput = document.getElementById("settingsNSLogRangeVal"); + const nsPortRangeInput = document.getElementById("settingsNSPortRangeVal"); + const nsAutosaveIntervalInput = document.getElementById("settingsAutosaveIntervalVal"); nsExecTimeInput.value = Settings.CodeInstructionRunTime; nsLogRangeInput.value = Settings.MaxLogCapacity; nsPortRangeInput.value = Settings.MaxPortCapacity; @@ -57,8 +65,8 @@ function setSettingsLabels() { }; nsAutosaveIntervalInput.oninput = function() { - autosaveInterval.innerHTML = this.value; Settings.AutosaveInterval = Number(this.value); + setAutosaveLabel(autosaveInterval) if (Number(this.value) === 0) { Engine.Counters.autoSaveCounter = Infinity; } else { From 1b8214b6fa8dd97a0496f6196fed46ec1823af47 Mon Sep 17 00:00:00 2001 From: Olivier Gagnon Date: Tue, 9 Mar 2021 23:40:33 -0500 Subject: [PATCH 12/19] removed filter from checkbox, update changelog to say 2021 instead of 2020 --- css/styles.scss | 1 - doc/source/changelog.rst | 2 +- src/Constants.ts | 9 ++++++++- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/css/styles.scss b/css/styles.scss index b6b876b1d..3fc008714 100644 --- a/css/styles.scss +++ b/css/styles.scss @@ -362,7 +362,6 @@ a:visited { .optionCheckbox { - filter: invert(100%) hue-rotate(0deg) brightness(1.7); margin: 5px; float: right; } diff --git a/doc/source/changelog.rst b/doc/source/changelog.rst index 2301f7b4a..a7a6bc8c9 100644 --- a/doc/source/changelog.rst +++ b/doc/source/changelog.rst @@ -4,7 +4,7 @@ Changelog ========= -v0.48.0 - ASCII - 2020-03-07 (hydroflame) +v0.48.0 - ASCII - 2021-03-07 (hydroflame) ------- **ASCII** diff --git a/src/Constants.ts b/src/Constants.ts index f6b49e332..dc4267738 100644 --- a/src/Constants.ts +++ b/src/Constants.ts @@ -228,9 +228,16 @@ export let CONSTANTS: IMap = { LatestUpdate: ` - v0.49.0 + v0.49.0 - 2021-XX-XX Source-File -1 ------- + Source-File -1 + * For advanced players: The game now embraces exploits and will reward + players for doing so. + + + + Netscript * 'gang.getEquipmentStats' returns the stats of the equipment. * 'gang.getTaskStats' returns the stats of a task. From e2a353fc8a9e44402880bc18c2ecebbd32b661dd Mon Sep 17 00:00:00 2001 From: Olivier Gagnon Date: Wed, 10 Mar 2021 01:27:14 -0500 Subject: [PATCH 13/19] Attempt at logging line number on netscript error --- css/styles.scss | 1 + src/NetscriptFunctions.js | 123 ++++++++++++++++++++++-------------- src/NetscriptJSEvaluator.js | 1 + src/Script/Script.ts | 3 + 4 files changed, 80 insertions(+), 48 deletions(-) diff --git a/css/styles.scss b/css/styles.scss index 3fc008714..44fb8fe6b 100644 --- a/css/styles.scss +++ b/css/styles.scss @@ -362,6 +362,7 @@ a:visited { .optionCheckbox { + filter: invert(1) sepia(1) hue-rotate(41deg) brightness(100%) saturate(10); margin: 5px; float: right; } diff --git a/src/NetscriptFunctions.js b/src/NetscriptFunctions.js index 01b5bff19..947cc5fbe 100644 --- a/src/NetscriptFunctions.js +++ b/src/NetscriptFunctions.js @@ -68,6 +68,7 @@ import { Programs } from "./Programs/Programs"; import { Script } from "./Script/Script"; import { findRunningScript } from "./Script/ScriptHelpers"; import { isScriptFilename } from "./Script/ScriptHelpersTS"; +import { _getScriptUrls } from "./NetscriptJSEvaluator"; import { AllServers, AddToAllServers, @@ -392,6 +393,23 @@ function NetscriptFunctions(workerScript) { return server.getContract(fn); } + const lineNumber = function() { + // exactly 5 function call parent from this one, so index 4 + const fileline = (new Error()).stack.split('\n')[4]; + const scripts = workerScript.getServer().scripts; + + let problem; + for(const script of scripts) { + if (script.url && fileline.includes(script.url)) { + problem = script.filename; + } + } + + const re = /.*:(\d+):\d+.*/; + const match = fileline.match(re); + return `${problem}#${match[1]}`; + } + return { hacknet : { numNodes : function() { @@ -531,7 +549,7 @@ function NetscriptFunctions(workerScript) { } if (workerScript.disableLogs.ALL == null && workerScript.disableLogs.hack == null) { - workerScript.scriptRef.log("Attempting to hack " + ip + " in " + hackingTime.toFixed(3) + " seconds (t=" + threads + ")"); + workerScript.scriptRef.log(`Executing hack ${ip} in ${hackingTime.toFixed(3)} seconds (t=${threads})`); } return netscriptDelay(hackingTime * 1000, workerScript).then(function() { @@ -567,7 +585,7 @@ function NetscriptFunctions(workerScript) { Player.gainHackingExp(expGainedOnSuccess); workerScript.scriptRef.onlineExpGained += expGainedOnSuccess; if (workerScript.disableLogs.ALL == null && workerScript.disableLogs.hack == null) { - workerScript.scriptRef.log("Script SUCCESSFULLY hacked " + server.hostname + " for $" + formatNumber(moneyGained, 2) + " and " + formatNumber(expGainedOnSuccess, 4) + " exp (t=" + threads + ")"); + workerScript.scriptRef.log(`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) { @@ -579,7 +597,7 @@ function NetscriptFunctions(workerScript) { Player.gainHackingExp(expGainedOnFailure); workerScript.scriptRef.onlineExpGained += expGainedOnFailure; if (workerScript.disableLogs.ALL == null && workerScript.disableLogs.hack == null) { - workerScript.scriptRef.log("Script FAILED to hack " + server.hostname + ". Gained " + formatNumber(expGainedOnFailure, 4) + " exp (t=" + threads + ")"); + workerScript.scriptRef.log(`Failed to hack ${server.hostname}. Gained ${numeralWrapper.format(expGainedOnFailure, '0.000a')} exp (t=${threads})`); } return Promise.resolve(0); } @@ -635,8 +653,8 @@ function NetscriptFunctions(workerScript) { } var server = getServer(ip); if (server == null) { - workerScript.scriptRef.log("Cannot grow(). Invalid IP or hostname passed in: " + ip); - throw makeRuntimeRejectMsg(workerScript, "Cannot grow(). Invalid IP or hostname passed in: " + ip); + workerScript.scriptRef.log(`Cannot grow(). Invalid IP or hostname passed in: ${ip}`); + throw makeRuntimeRejectMsg(workerScript, `Cannot grow(). Invalid IP or hostname passed in: ${ip}`); } // No root access or skill level too low @@ -648,7 +666,7 @@ function NetscriptFunctions(workerScript) { var growTime = calculateGrowTime(server); if (workerScript.disableLogs.ALL == null && workerScript.disableLogs.grow == null) { - workerScript.scriptRef.log("Executing grow() on server " + server.hostname + " in " + formatNumber(growTime, 3) + " seconds (t=" + threads + ")"); + workerScript.scriptRef.log(`Executing grow('${server.hostname}') in ${formatNumber(growTime, 3)} seconds (t=${threads})`); } return netscriptDelay(growTime * 1000, workerScript).then(function() { if (workerScript.env.stopFlag) {return Promise.reject(workerScript);} @@ -661,10 +679,9 @@ function NetscriptFunctions(workerScript) { if (growthPercentage == 1) { expGain = 0; } + const logGrowPercent = (moneyAfter/moneyBefore)*100 - 100; if (workerScript.shouldLog("grow")) { - workerScript.log("Available money on " + server.hostname + " grown by " + - formatNumber((moneyAfter/moneyBefore)*100 - 100, 6) + "%. Gained " + - formatNumber(expGain, 4) + " hacking exp (t=" + threads +")"); + workerScript.log(`Available money on ${server.hostname} grown by ${formatNumber(logGrowPercent, 6)}%. Gained ${numeralWrapper.format(expGain, '0.000a')} hacking exp (t=${threads})`); } workerScript.scriptRef.onlineExpGained += expGain; Player.gainHackingExp(expGain); @@ -706,8 +723,7 @@ function NetscriptFunctions(workerScript) { var weakenTime = calculateWeakenTime(server); if (workerScript.disableLogs.ALL == null && workerScript.disableLogs.weaken == null) { - workerScript.scriptRef.log("Executing weaken() on server " + server.hostname + " in " + - formatNumber(weakenTime, 3) + " seconds (t=" + threads + ")"); + workerScript.scriptRef.log(`Executing weaken('${server.hostname}') in ${formatNumber(weakenTime, 3)} seconds (t=${threads})`); } return netscriptDelay(weakenTime * 1000, workerScript).then(function() { if (workerScript.env.stopFlag) {return Promise.reject(workerScript);} @@ -715,8 +731,7 @@ function NetscriptFunctions(workerScript) { workerScript.scriptRef.recordWeaken(server.ip, threads); var expGain = calculateHackingExpGain(server) * threads; if (workerScript.disableLogs.ALL == null && workerScript.disableLogs.weaken == null) { - workerScript.scriptRef.log("Server security level on " + server.hostname + " weakened to " + server.hackDifficulty + - ". Gained " + formatNumber(expGain, 4) + " hacking exp (t=" + threads + ")"); + workerScript.scriptRef.log(`${server.hostname} security level weakened to ${server.hackDifficulty}. Gained ${numeralWrapper.format(expGain, '0.000a')} hacking exp (t=${threads})`); } workerScript.scriptRef.onlineExpGained += expGain; Player.gainHackingExp(expGain); @@ -734,32 +749,32 @@ function NetscriptFunctions(workerScript) { throw makeRuntimeRejectMsg(workerScript, "tprint() call has incorrect number of arguments. Takes 1 argument"); } var x = args.toString(); - post(workerScript.scriptRef.filename + ": " + args.toString()); + post(`${workerScript.scriptRef.filename}: ${args.toString()}`); }, clearLog: function() { workerScript.scriptRef.clearLog(); }, disableLog: function(fn) { if (possibleLogs[fn]===undefined) { - throw makeRuntimeRejectMsg(workerScript, "Invalid argument to disableLog: "+fn); + throw makeRuntimeRejectMsg(workerScript, `Invalid argument to disableLog: ${fn}`); } workerScript.disableLogs[fn] = true; if (workerScript.disableLogs.ALL == null && workerScript.disableLogs.disableLog == null) { - workerScript.scriptRef.log("Disabled logging for " + fn); + workerScript.scriptRef.log(`Disabled logging for ${fn}`); } }, enableLog: function(fn) { if (possibleLogs[fn]===undefined) { - throw makeRuntimeRejectMsg(workerScript, "Invalid argument to enableLog: "+fn); + throw makeRuntimeRejectMsg(workerScript, `Invalid argument to enableLog: ${fn}`); } delete workerScript.disableLogs[fn]; if (workerScript.disableLogs.ALL == null && workerScript.disableLogs.enableLog == null) { - workerScript.scriptRef.log("Enabled logging for " + fn); + workerScript.scriptRef.log(`Enabled logging for ${fn}`); } }, isLogEnabled : function(fn) { if (possibleLogs[fn] === undefined) { - throw makeRuntimeRejectMsg(workerScript, "Invalid argument to isLogEnabled: " + fn); + throw makeRuntimeRejectMsg(workerScript, `Invalid argument to isLogEnabled: ${fn}`); } return workerScript.disableLogs[fn] ? false : true; }, @@ -784,12 +799,13 @@ function NetscriptFunctions(workerScript) { nuke: function(ip){ updateDynamicRam("nuke", getRamCost("nuke")); if (ip === undefined) { - throw makeRuntimeRejectMsg(workerScript, "Program call has incorrect number of arguments. Takes 1 argument"); + throw makeRuntimeRejectMsg(workerScript, "nuke call has incorrect number of arguments. Takes 1 argument"); } var server = getServer(ip); if (server == null) { - workerScript.scriptRef.log("Cannot call nuke(). Invalid IP or hostname passed in: " + ip); - throw makeRuntimeRejectMsg(workerScript, "Cannot call nuke(). Invalid IP or hostname passed in: " + ip); + const msg = `Cannot call nuke('${ip}'). Invalid IP/hostname.`; + workerScript.scriptRef.log(msg); + throw makeRuntimeRejectMsg(workerScript, msg); } if (!Player.hasProgram(Programs.NukeProgram.name)) { throw makeRuntimeRejectMsg(workerScript, "You do not have the NUKE.exe virus!"); @@ -799,12 +815,12 @@ function NetscriptFunctions(workerScript) { } if (server.hasAdminRights) { if (workerScript.disableLogs.ALL == null && workerScript.disableLogs.nuke == null) { - workerScript.scriptRef.log("Already have root access to " + server.hostname); + workerScript.scriptRef.log(`Already have root access to ${server.hostname}`); } } else { server.hasAdminRights = true; if (workerScript.disableLogs.ALL == null && workerScript.disableLogs.nuke == null) { - workerScript.scriptRef.log("Executed NUKE.exe virus on " + server.hostname + " to gain root access"); + workerScript.scriptRef.log(`Executed NUKE.exe virus on ${server.hostname} to gain root access`); } } return true; @@ -812,12 +828,13 @@ function NetscriptFunctions(workerScript) { brutessh: function(ip){ updateDynamicRam("brutessh", getRamCost("brutessh")); if (ip === undefined) { - throw makeRuntimeRejectMsg(workerScript, "Program call has incorrect number of arguments. Takes 1 argument"); + throw makeRuntimeRejectMsg(workerScript, "brutessh call has incorrect number of arguments. Takes 1 argument"); } var server = getServer(ip); if (server == null) { - workerScript.scriptRef.log("Cannot call brutessh(). Invalid IP or hostname passed in: " + ip); - throw makeRuntimeRejectMsg(workerScript, "Cannot call brutessh(). Invalid IP or hostname passed in: " + ip); + const msg = `Cannot call brutessh('${ip}'). Invalid IP/hostname.`; + workerScript.scriptRef.log(msg); + throw makeRuntimeRejectMsg(workerScript, msg); } if (!Player.hasProgram(Programs.BruteSSHProgram.name)) { workerScript.scriptRef.log("You do not have the BruteSSH.exe program!"); @@ -825,13 +842,13 @@ function NetscriptFunctions(workerScript) { } if (!server.sshPortOpen) { if (workerScript.disableLogs.ALL == null && workerScript.disableLogs.brutessh == null) { - workerScript.scriptRef.log("Executed BruteSSH.exe on " + server.hostname + " to open SSH port (22)"); + workerScript.scriptRef.log(`Executed BruteSSH.exe on ${server.hostname} to open SSH port (22)`); } server.sshPortOpen = true; ++server.openPortCount; } else { if (workerScript.disableLogs.ALL == null && workerScript.disableLogs.brutessh == null) { - workerScript.scriptRef.log("SSH Port (22) already opened on " + server.hostname); + workerScript.scriptRef.log(`SSH Port (22) already opened on ${server.hostname}`); } } return true; @@ -843,21 +860,22 @@ function NetscriptFunctions(workerScript) { } var server = getServer(ip); if (server == null) { - workerScript.scriptRef.log("Cannot call ftpcrack(). Invalid IP or hostname passed in: " + ip); - throw makeRuntimeRejectMsg(workerScript, "Cannot call ftpcrack(). Invalid IP or hostname passed in: " + ip); + const msg = `Cannot call ftpcrack('${ip}'). Invalid IP/hostname.` + workerScript.scriptRef.log(msg); + throw makeRuntimeRejectMsg(workerScript, msg); } if (!Player.hasProgram(Programs.FTPCrackProgram.name)) { throw makeRuntimeRejectMsg(workerScript, "You do not have the FTPCrack.exe program!"); } if (!server.ftpPortOpen) { if (workerScript.disableLogs.ALL == null && workerScript.disableLogs.ftpcrack == null) { - workerScript.scriptRef.log("Executed FTPCrack.exe on " + server.hostname + " to open FTP port (21)"); + workerScript.scriptRef.log(`Executed FTPCrack.exe on ${server.hostname} to open FTP port (21)`); } server.ftpPortOpen = true; ++server.openPortCount; } else { if (workerScript.disableLogs.ALL == null && workerScript.disableLogs.ftpcrack == null) { - workerScript.scriptRef.log("FTP Port (21) already opened on " + server.hostname); + workerScript.scriptRef.log(`FTP Port (21) already opened on ${server.hostname}`); } } return true; @@ -869,21 +887,22 @@ function NetscriptFunctions(workerScript) { } var server = getServer(ip); if (server == null) { - workerScript.scriptRef.log("Cannot call relaysmtp(). Invalid IP or hostname passed in: " + ip); - throw makeRuntimeRejectMsg(workerScript, "Cannot call relaysmtp(). Invalid IP or hostname passed in: " + ip); + const msg = `Cannot call relaysmtp('${ip}'). Invalid IP/hostname.` + workerScript.scriptRef.log(msg); + throw makeRuntimeRejectMsg(workerScript, msg); } if (!Player.hasProgram(Programs.RelaySMTPProgram.name)) { throw makeRuntimeRejectMsg(workerScript, "You do not have the relaySMTP.exe program!"); } if (!server.smtpPortOpen) { if (workerScript.disableLogs.ALL == null && workerScript.disableLogs.relaysmtp == null) { - workerScript.scriptRef.log("Executed relaySMTP.exe on " + server.hostname + " to open SMTP port (25)"); + workerScript.scriptRef.log(`Executed relaySMTP.exe on ${server.hostname} to open SMTP port (25)`); } server.smtpPortOpen = true; ++server.openPortCount; } else { if (workerScript.disableLogs.ALL == null && workerScript.disableLogs.relaysmtp == null) { - workerScript.scriptRef.log("SMTP Port (25) already opened on " + server.hostname); + workerScript.scriptRef.log(`SMTP Port (25) already opened on ${server.hostname}`); } } return true; @@ -895,21 +914,22 @@ function NetscriptFunctions(workerScript) { } var server = getServer(ip); if (server == null) { - workerScript.scriptRef.log("Cannot call httpworm(). Invalid IP or hostname passed in: " + ip); - throw makeRuntimeRejectMsg(workerScript, "Cannot call httpworm(). Invalid IP or hostname passed in: " + ip); + const msg = `Cannot call httpworm('${ip}'). Invalid IP/hostname.` + workerScript.scriptRef.log(msg); + throw makeRuntimeRejectMsg(workerScript, msg); } if (!Player.hasProgram(Programs.HTTPWormProgram.name)) { throw makeRuntimeRejectMsg(workerScript, "You do not have the HTTPWorm.exe program!"); } if (!server.httpPortOpen) { if (workerScript.disableLogs.ALL == null && workerScript.disableLogs.httpworm == null) { - workerScript.scriptRef.log("Executed HTTPWorm.exe on " + server.hostname + " to open HTTP port (80)"); + workerScript.scriptRef.log(`Executed HTTPWorm.exe on ${server.hostname} to open HTTP port (80)`); } server.httpPortOpen = true; ++server.openPortCount; } else { if (workerScript.disableLogs.ALL == null && workerScript.disableLogs.httpworm == null) { - workerScript.scriptRef.log("HTTP Port (80) already opened on " + server.hostname); + workerScript.scriptRef.log(`HTTP Port (80) already opened on ${server.hostname}`); } } return true; @@ -921,21 +941,22 @@ function NetscriptFunctions(workerScript) { } var server = getServer(ip); if (server == null) { - workerScript.scriptRef.log("Cannot call sqlinject(). Invalid IP or hostname passed in: " + ip); - throw makeRuntimeRejectMsg(workerScript, "Cannot call sqlinject(). Invalid IP or hostname passed in: " + ip); + const msg = `Cannot call sqlinject('${ip}'). Invalid IP/hostname.` + workerScript.scriptRef.log(msg); + throw makeRuntimeRejectMsg(workerScript, msg); } if (!Player.hasProgram(Programs.SQLInjectProgram.name)) { throw makeRuntimeRejectMsg(workerScript, "You do not have the SQLInject.exe program!"); } if (!server.sqlPortOpen) { if (workerScript.disableLogs.ALL == null && workerScript.disableLogs.sqlinject == null) { - workerScript.scriptRef.log("Executed SQLInject.exe on " + server.hostname + " to open SQL port (1433)"); + workerScript.scriptRef.log(`Executed SQLInject.exe on ${server.hostname} to open SQL port (1433)`); } server.sqlPortOpen = true; ++server.openPortCount; } else { if (workerScript.disableLogs.ALL == null && workerScript.disableLogs.sqlinject == null) { - workerScript.scriptRef.log("SQL Port (1433) already opened on " + server.hostname); + workerScript.scriptRef.log(`SQL Port (1433) already opened on ${server.hostname}`); } } return true; @@ -1154,21 +1175,21 @@ function NetscriptFunctions(workerScript) { } if (!found) { - workerScript.scriptRef.log(scriptname + " does not exist. scp() failed"); + workerScript.scriptRef.log(`${scriptname} does not exist. scp() failed`); return false; } for (var i = 0; i < destServer.messages.length; ++i) { if (destServer.messages[i] === scriptname) { if (workerScript.disableLogs.ALL == null && workerScript.disableLogs.scp == null) { - workerScript.scriptRef.log(scriptname + " copied over to " + destServer.hostname); + workerScript.scriptRef.log(`${scriptname} copied over to ${destServer.hostname}`); } return true; // Already exists } } destServer.messages.push(scriptname); if (workerScript.disableLogs.ALL == null && workerScript.disableLogs.scp == null) { - workerScript.scriptRef.log(scriptname + " copied over to " + destServer.hostname); + workerScript.scriptRef.log(`${scriptname} copied over to ${destServer.hostname}`); } return true; } @@ -4717,6 +4738,12 @@ function NetscriptFunctions(workerScript) { }, exploit: function() { Player.giveExploit(Exploit.UndocumentedFunctionCall); + }, + whatever: function(ip) { + const server = getServer(ip); + if (server == null) { + throw makeRuntimeRejectMsg(workerScript, `${lineNumber()}: hack('${ip}'): Invalid IP/hostname.`); + } } } // End return } // End NetscriptFunction() diff --git a/src/NetscriptJSEvaluator.js b/src/NetscriptJSEvaluator.js index 5325911a3..1f8a9e255 100644 --- a/src/NetscriptJSEvaluator.js +++ b/src/NetscriptJSEvaluator.js @@ -38,6 +38,7 @@ export async function executeJSScript(scripts = [], workerScript) { // load fully dynamic content. So we hide the import from webpack // by placing it inside an eval call. urls = _getScriptUrls(script, scripts, []); + script.url = urls[urls.length - 1].url; script.module = new Promise(resolve => resolve(eval('import(urls[urls.length - 1].url)'))); script.dependencies = urls.map(u => u.filename); } diff --git a/src/Script/Script.ts b/src/Script/Script.ts index 7436e93a5..4b4f8ea07 100644 --- a/src/Script/Script.ts +++ b/src/Script/Script.ts @@ -29,6 +29,9 @@ export class Script { // Filename for the script file filename: string = ""; + // url of the script if any, only for NS2. + url: string = ""; + // The dynamic module generated for this script when it is run. // This is only applicable for NetscriptJS module: any = ""; From cd972dabe322cafba6c29b5f3f4704a484902191 Mon Sep 17 00:00:00 2001 From: Olivier Gagnon Date: Thu, 11 Mar 2021 03:02:05 -0500 Subject: [PATCH 14/19] crash now prints ns stack trace, workerscript now does the shouldLog check on its own, many ns function are way simpler. --- src/Bladeburner.js | 37 - src/Netscript/WorkerScript.ts | 12 +- src/NetscriptBladeburner.js | 11 - src/NetscriptEvaluator.js | 11 +- src/NetscriptFunctions.js | 2312 +++++++++------------------ src/NetscriptGang.js | 7 - src/NetscriptJSEvaluator.js | 15 +- src/NetscriptWorker.js | 43 +- src/Script/Script.ts | 3 +- src/Script/ScriptUrl.ts | 9 + src/StockMarket/BuyingAndSelling.ts | 26 +- src/StockMarket/StockMarket.tsx | 4 +- 12 files changed, 853 insertions(+), 1637 deletions(-) create mode 100644 src/Script/ScriptUrl.ts diff --git a/src/Bladeburner.js b/src/Bladeburner.js index c3ca46202..75b5b1688 100644 --- a/src/Bladeburner.js +++ b/src/Bladeburner.js @@ -3827,43 +3827,6 @@ Bladeburner.prototype.setTeamSizeNetscriptFn = function(type, name, size, worker return sanitizedSize; } -Bladeburner.prototype.getCityEstimatedPopulationNetscriptFn = function(cityName, workerScript) { - if (!this.cities.hasOwnProperty(cityName)) { - workerScript.log("ERROR: bladeburner.getCityEstimatedPopulation() failed because the specified " + - "city was invalid: " + cityName + ". Note that this city argument is case-sensitive"); - return -1; - } - return this.cities[cityName].popEst; -} - -Bladeburner.prototype.getCityEstimatedCommunitiesNetscriptFn = function(cityName, workerScript) { - if (!this.cities.hasOwnProperty(cityName)) { - workerScript.log("ERROR: bladeburner.getCityEstimatedCommunities() failed because the specified " + - "city was invalid: " + cityName + ". Note that this city argument is case-sensitive"); - return -1; - } - return this.cities[cityName].commsEst; -} - -Bladeburner.prototype.getCityChaosNetscriptFn = function(cityName, workerScript) { - if (!this.cities.hasOwnProperty(cityName)) { - workerScript.log("ERROR: bladeburner.getCityChaos() failed because the specified " + - "city was invalid: " + cityName + ". Note that this city argument is case-sensitive"); - return -1; - } - return this.cities[cityName].chaos; -} - -Bladeburner.prototype.switchCityNetscriptFn = function(cityName, workerScript) { - if (!this.cities.hasOwnProperty(cityName)) { - workerScript.log("ERROR: bladeburner.switchCity() failed because the specified " + - "city was invalid: " + cityName + ". Note that this city argument is case-sensitive"); - return false; - } - this.city = cityName; - return true; -} - Bladeburner.prototype.joinBladeburnerFactionNetscriptFn = function(workerScript) { var bladeburnerFac = Factions["Bladeburners"]; if (bladeburnerFac.isMember) { diff --git a/src/Netscript/WorkerScript.ts b/src/Netscript/WorkerScript.ts index 726af7c84..13ba99d57 100644 --- a/src/Netscript/WorkerScript.ts +++ b/src/Netscript/WorkerScript.ts @@ -188,7 +188,17 @@ export class WorkerScript { return (this.disableLogs.ALL == null && this.disableLogs[fn] == null); } - log(txt: string): void { + log(func: string, txt: string): void { + if(this.shouldLog(func)) { + if(func !== "" && txt !== ""){ + this.scriptRef.log(`${func}: ${txt}`); + } else { + this.scriptRef.log(func+txt); + } + } + } + + print(txt: string): void { this.scriptRef.log(txt); } } diff --git a/src/NetscriptBladeburner.js b/src/NetscriptBladeburner.js index 61daa782f..1ac7d7eb3 100644 --- a/src/NetscriptBladeburner.js +++ b/src/NetscriptBladeburner.js @@ -12,15 +12,4 @@ function unknownBladeburnerExceptionMessage(functionName, err) { return `bladeburner.${functionName}() failed with exception: ` + err; } -function checkBladeburnerAccess(workerScript, functionName) { - const accessDenied = `${functionName}() failed because you do not ` + - "currently have access to the Bladeburner API. To access the Bladeburner API" + - "you must be employed at the Bladeburner division, AND you must either be in " + - "BitNode-7 or have Source-File 7."; - const hasAccess = Player.bladeburner instanceof Bladeburner && (Player.bitNodeN === 7 || Player.sourceFiles.some(a=>{return a.n === 7})); - if(!hasAccess) { - throw makeRuntimeRejectMsg(workerScript, accessDenied); - } -} - export {unknownBladeburnerActionErrorMessage, unknownBladeburnerExceptionMessage, checkBladeburnerAccess}; diff --git a/src/NetscriptEvaluator.js b/src/NetscriptEvaluator.js index cdd0c5636..b61b217c2 100644 --- a/src/NetscriptEvaluator.js +++ b/src/NetscriptEvaluator.js @@ -2,6 +2,7 @@ import { setTimeoutRef } from "./utils/SetTimeoutRef"; import { isValidIPAddress } from "../utils/helpers/isValidIPAddress"; import { isString } from "../utils/helpers/isString"; +import { AllServers } from "./Server/AllServers"; export function netscriptDelay(time, workerScript) { return new Promise(function(resolve, reject) { @@ -19,7 +20,12 @@ export function makeRuntimeRejectMsg(workerScript, msg, exp=null) { var num = getErrorLineNumber(exp, workerScript); lineNum = " (Line " + num + ")" } - return "|"+workerScript.serverIp+"|"+workerScript.name+"|" + msg + lineNum; + const server = AllServers[workerScript.serverIp]; + if (server == null) { + throw new Error(`WorkerScript constructed with invalid server ip: ${this.serverIp}`); + } + + return "|"+server.hostname+"|"+workerScript.name+"|" + msg + lineNum; } export function resolveNetscriptRequestedThreads(workerScript, functionName, requestedThreads) { @@ -57,8 +63,5 @@ export function isScriptErrorMessage(msg) { return false; } var ip = splitMsg[1]; - if (!isValidIPAddress(ip)) { - return false; - } return true; } diff --git a/src/NetscriptFunctions.js b/src/NetscriptFunctions.js index 947cc5fbe..aae87c2f9 100644 --- a/src/NetscriptFunctions.js +++ b/src/NetscriptFunctions.js @@ -124,11 +124,10 @@ import { isValidFilePath } from "./Terminal/DirectoryHelpers"; import { TextFile, getTextFile, createTextFile } from "./TextFile"; import { - unknownBladeburnerActionErrorMessage, - unknownBladeburnerExceptionMessage, - checkBladeburnerAccess -} from "./NetscriptBladeburner"; + unknownBladeburnerActionErrorMessage +} from"./NetscriptBladeburner"; import * as nsGang from "./NetscriptGang"; +import { Gang } from "./Gang"; import { NetscriptPorts, runScriptFromScript, @@ -233,7 +232,6 @@ const possibleLogs = { setTerritoryWarfare: true, } - function NetscriptFunctions(workerScript) { const updateDynamicRam = function(fnName, ramCost) { if (workerScript.dynamicLoadedFns[fnName]) { return; } @@ -266,8 +264,7 @@ function NetscriptFunctions(workerScript) { const safeGetServer = function(ip, callingFnName="") { var server = getServer(ip); if (server == null) { - workerScript.log(`ERROR: Invalid IP or hostname passed into ${callingFnName}()`); - throw makeRuntimeRejectMsg(workerScript, `Invalid IP or hostname passed into ${callingFnName}() function`); + throw makeRuntimeErrorMsg(callingFnName, `Invalid IP/hostname: ${ip}`); } return server; } @@ -360,7 +357,7 @@ function NetscriptFunctions(workerScript) { */ const failOnHacknetServer = function(server, callingFn="") { if (server instanceof HacknetServer) { - workerScript.log(`ERROR: ${callingFn}() failed because it does not work on Hacknet Servers`); + workerScript.log(callingFn, `Does not work on Hacknet Servers`); return true; } else { return false; @@ -388,26 +385,148 @@ function NetscriptFunctions(workerScript) { } }; - const getCodingContract = function(fn, ip) { - var server = safeGetServer(ip, "getCodingContract"); - return server.getContract(fn); - } - - const lineNumber = function() { - // exactly 5 function call parent from this one, so index 4 - const fileline = (new Error()).stack.split('\n')[4]; + const makeRuntimeErrorMsg = function(caller, msg) { + const stack = (new Error()).stack.split('\n').slice(1); const scripts = workerScript.getServer().scripts; - - let problem; - for(const script of scripts) { - if (script.url && fileline.includes(script.url)) { - problem = script.filename; + let userstack = []; + for(const stackline of stack) { + let filename; + for(const script of scripts) { + if (script.url && stackline.includes(script.url)) { + filename = script.filename; + } + for (const dependency of script.dependencies) { + if (stackline.includes(dependency.url)) { + filename = dependency.filename; + } + } } + if(!filename) continue + + const lineRe = /.*:(\d+):\d+.*/; + const lineMatch = stackline.match(lineRe); + + + const funcRe = /.*at (.+) \(.*/; + const funcMatch = stackline.match(funcRe); + let func = funcMatch[1]; + if(func.includes('.')) func = func.split('.')[1]; + + userstack.push(`${filename}:L${lineMatch[1]}@${func}`); } - const re = /.*:(\d+):\d+.*/; - const match = fileline.match(re); - return `${problem}#${match[1]}`; + workerScript.log(caller, msg); + const rejectMsg = `${caller}: ${msg}

    Stack:
    ${userstack.join('
    ')}` + return makeRuntimeRejectMsg(workerScript, rejectMsg); + } + + const checkSingularityAccess = function(func, n) { + if (Player.bitNodeN !== 4) { + if (SourceFileFlags[4] < n) { + throw makeRuntimeErrorMsg(func, `This singularity function requires Source-File 4-${n} to run.`); + } + } + } + + const checkBladeburnerAccess = function(func) { + const accessDenied = `You do not ` + + "currently have access to the Bladeburner API. To access the Bladeburner API " + + "you must be employed at the Bladeburner division, AND you must either be in " + + "BitNode-7 or have Source-File 7."; + const hasAccess = Player.bladeburner instanceof Bladeburner && (Player.bitNodeN === 7 || Player.sourceFiles.some(a=>{return a.n === 7})); + if(!hasAccess) { + throw makeRuntimeErrorMsg(`bladeburner.${func}`, accessDenied); + } + } + + const checkBladeburnerCity = function(func, city) { + if (!Player.bladeburner.cities.hasOwnProperty(city)) { + throw makeRuntimeErrorMsg(`bladeburner.${func}`, `Invalid city: ${city}`); + } + } + + const checkSleeveAPIAccess = function(func) { + if (Player.bitNodeN !== 10 && !SourceFileFlags[10]) { + throw makeRuntimeErrorMsg(`sleeve.${func}`, "You do not currently have access to the Sleeve API. This is either because you are not in BitNode-10 or because you do not have Source-File 10"); + } + } + + const checkSleeveNumber = function(func, sleeveNumber) { + if (sleeveNumber >= Player.sleeves.length || sleeveNumber < 0) { + const msg = `Invalid sleeve number: ${sleeveNumber}`; + workerScript.log(func, msg); + throw makeRuntimeErrorMsg(`sleeve.${func}`, msg); + } + } + + const getCodingContract = function(func, ip, fn) { + const server = safeGetServer(ip, func); + const contract = server.getContract(fn); + if (contract == null) { + throw makeRuntimeErrorMsg(`codingcontract.${func}`, `Cannot find contract '${fn}' on server '${ip}'`) + } + + return contract; + } + + const checkGangApiAccess = function(func) { + const hasAccess = Player.gang instanceof Gang; + if (!hasAccess) { + throw makeRuntimeErrorMsg(`gang.${func}`, `You do not currently have a Gang`); + } + } + + const getGangMember = function(func, name) { + for (const member of Player.gang.members) + if (member.name === name) + return member; + throw makeRuntimeErrorMsg(`gang.${func}`, `Invalid gang member: '${name}'`) + } + + const getGangTask = function(func, name) { + const task = GangMemberTasks[taskName]; + if (!task) { + throw makeRuntimeErrorMsg(`gang.${func}`, `Invalid task: '${taskName}'`); + } + + return task; + } + + const getBladeburnerActionObject = function(func, type, name) { + const actionId = Player.bladeburner.getActionIdFromTypeAndName(type, name) + if (!actionId) { + throw makeRuntimeErrorMsg(`bladeburner.${func}`, `Invalid action type='${type}', name='${name}'`); + } + const actionObj = Player.bladeburner.getActionObject(actionId); + if (!actionObj) { + throw makeRuntimeErrorMsg(`bladeburner.${func}`, `Invalid action type='${type}', name='${name}'`); + } + + return actionObj; + } + + const getCompany = function(func, name) { + const company = Companies[name]; + if (company == null || !(company instanceof Company)) { + throw makeRuntimeErrorMsg(func, `Invalid company name: '${name}'`) + } + return company; + } + + const getFaction = function(func, name) { + if (!factionExists(name)) { + throw makeRuntimeErrorMsg(func, `Invalid faction name: '${name}`) + } + + return Factions[name]; + } + + const getAugmentation = function(func, name) { + if (!augmentationExists(name)) { + throw makeRuntimeErrorMsg(func, `Invalid augmentation: '${name}'`); + } + + return Augmentations[name]; } return { @@ -506,7 +625,7 @@ function NetscriptFunctions(workerScript) { updateDynamicRam("scan", getRamCost("scan")); var server = getServer(ip); if (server == null) { - throw makeRuntimeRejectMsg(workerScript, 'Invalid IP or hostname passed into scan() command'); + throw makeRuntimeErrorMsg('scan', `Invalid IP/hostname: ${ip}.`); } var out = []; for (var i = 0; i < server.serversOnNetwork.length; i++) { @@ -521,21 +640,18 @@ function NetscriptFunctions(workerScript) { } out.push(entry); } - if (workerScript.disableLogs.ALL == null && workerScript.disableLogs.scan == null) { - workerScript.scriptRef.log('scan() returned ' + server.serversOnNetwork.length + ' connections for ' + server.hostname); - } + workerScript.log("scan", `returned ${server.serversOnNetwork.length} connections for ${server.hostname}`); return out; }, hack : function(ip, { threads: requestedThreads, stock } = {}){ updateDynamicRam("hack", getRamCost("hack")); if (ip === undefined) { - throw makeRuntimeRejectMsg(workerScript, "Hack() call has incorrect number of arguments. Takes 1 argument"); + throw makeRuntimeErrorMsg("hack", "Takes 1 argument."); } const threads = resolveNetscriptRequestedThreads(workerScript, "hack", requestedThreads); const server = getServer(ip); if (server == null) { - workerScript.scriptRef.log("hack() error. Invalid IP or hostname passed in: " + ip + ". Stopping..."); - throw makeRuntimeRejectMsg(workerScript, "hack() error. Invalid IP or hostname passed in: " + ip + ". Stopping..."); + throw makeRuntimeErrorMsg("hack", `Invalid IP/hostname: ${ip}.`); } // Calculate the hacking time @@ -544,13 +660,10 @@ function NetscriptFunctions(workerScript) { // No root access or skill level too low const canHack = netscriptCanHack(server, Player); if (!canHack.res) { - workerScript.scriptRef.log(`ERROR: ${canHack.msg}`); - throw makeRuntimeRejectMsg(workerScript, canHack.msg); + throw makeRuntimeErrorMsg('hack', canHack.msg); } - if (workerScript.disableLogs.ALL == null && workerScript.disableLogs.hack == null) { - workerScript.scriptRef.log(`Executing hack ${ip} in ${hackingTime.toFixed(3)} seconds (t=${threads})`); - } + 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);} @@ -584,9 +697,7 @@ function NetscriptFunctions(workerScript) { workerScript.scriptRef.recordHack(server.ip, moneyGained, threads); Player.gainHackingExp(expGainedOnSuccess); workerScript.scriptRef.onlineExpGained += expGainedOnSuccess; - if (workerScript.disableLogs.ALL == null && workerScript.disableLogs.hack == null) { - workerScript.scriptRef.log(`Successfully hacked ${server.hostname} for ${numeralWrapper.format(moneyGained, '$0.000a')} and ${numeralWrapper.format(expGainedOnSuccess, '0.000a')} exp (t=${threads})`); - } + 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); @@ -596,9 +707,7 @@ function NetscriptFunctions(workerScript) { // Player only gains 25% exp for failure? Player.gainHackingExp(expGainedOnFailure); workerScript.scriptRef.onlineExpGained += expGainedOnFailure; - if (workerScript.disableLogs.ALL == null && workerScript.disableLogs.hack == null) { - workerScript.scriptRef.log(`Failed to hack ${server.hostname}. Gained ${numeralWrapper.format(expGainedOnFailure, '0.000a')} exp (t=${threads})`); - } + workerScript.log("hack", `Failed to hack '${server.hostname}'. Gained ${numeralWrapper.format(expGainedOnFailure, '0.000a')} exp (t=${threads})`); return Promise.resolve(0); } }); @@ -609,7 +718,7 @@ function NetscriptFunctions(workerScript) { // Check argument validity const server = safeGetServer(ip, 'hackAnalyzeThreads'); if (isNaN(hackAmount)) { - throw makeRuntimeRejectMsg(workerScript, `Invalid growth argument passed into hackAnalyzeThreads: ${hackAmount}. Must be numeric`); + throw makeRuntimeErrorMsg(workerScript, `Invalid growth argument passed into hackAnalyzeThreads: ${hackAmount}. Must be numeric.`); } if (hackAmount < 0 || hackAmount > server.moneyAvailable) { @@ -636,11 +745,9 @@ function NetscriptFunctions(workerScript) { }, sleep : function(time){ if (time === undefined) { - throw makeRuntimeRejectMsg(workerScript, "sleep() call has incorrect number of arguments. Takes 1 argument"); - } - if (workerScript.shouldLog("sleep")) { - workerScript.log(`Sleeping for ${time} milliseconds`); + throw makeRuntimeErrorMsg("sleep", "Takes 1 argument."); } + workerScript.log("sleep", `Sleeping for ${time} milliseconds`); return netscriptDelay(time, workerScript).then(function() { return Promise.resolve(true); }); @@ -649,25 +756,21 @@ function NetscriptFunctions(workerScript) { updateDynamicRam("grow", getRamCost("grow")); const threads = resolveNetscriptRequestedThreads(workerScript, "grow", requestedThreads); if (ip === undefined) { - throw makeRuntimeRejectMsg(workerScript, "grow() call has incorrect number of arguments. Takes 1 argument"); + throw makeRuntimeErrorMsg("grow", "Takes 1 argument."); } var server = getServer(ip); if (server == null) { - workerScript.scriptRef.log(`Cannot grow(). Invalid IP or hostname passed in: ${ip}`); - throw makeRuntimeRejectMsg(workerScript, `Cannot grow(). Invalid IP or hostname passed in: ${ip}`); + throw makeRuntimeErrorMsg("grow", `Invalid IP/hostname: ${ip}.`); } // No root access or skill level too low const canHack = netscriptCanGrow(server); if (!canHack.res) { - workerScript.scriptRef.log(`ERROR: ${canHack.msg}`); - throw makeRuntimeRejectMsg(workerScript, canHack.msg); + throw makeRuntimeErrorMsg("grow", canHack.msg); } var growTime = calculateGrowTime(server); - if (workerScript.disableLogs.ALL == null && workerScript.disableLogs.grow == null) { - workerScript.scriptRef.log(`Executing grow('${server.hostname}') in ${formatNumber(growTime, 3)} seconds (t=${threads})`); - } + workerScript.log("grow", `Executing on '${server.hostname}' in ${formatNumber(growTime, 3)} seconds (t=${threads}).`); return netscriptDelay(growTime * 1000, workerScript).then(function() { if (workerScript.env.stopFlag) {return Promise.reject(workerScript);} const moneyBefore = server.moneyAvailable <= 0 ? 1 : server.moneyAvailable; @@ -680,9 +783,7 @@ function NetscriptFunctions(workerScript) { expGain = 0; } const logGrowPercent = (moneyAfter/moneyBefore)*100 - 100; - if (workerScript.shouldLog("grow")) { - workerScript.log(`Available money on ${server.hostname} grown by ${formatNumber(logGrowPercent, 6)}%. Gained ${numeralWrapper.format(expGain, '0.000a')} hacking exp (t=${threads})`); - } + workerScript.log("grow", `Available money on '${server.hostname}' grown by ${formatNumber(logGrowPercent, 6)}%. Gained ${numeralWrapper.format(expGain, '0.000a')} hacking exp (t=${threads}).`); workerScript.scriptRef.onlineExpGained += expGain; Player.gainHackingExp(expGain); if (stock) { @@ -697,7 +798,7 @@ function NetscriptFunctions(workerScript) { // Check argument validity const server = safeGetServer(ip, 'growthAnalyze'); if (typeof growth !== "number" || isNaN(growth) || growth < 1) { - throw makeRuntimeRejectMsg(workerScript, `Invalid growth argument passed into growthAnalyze: ${growth}. Must be numeric and >= 1`); + throw makeRuntimeErrorMsg("growthAnalyze", `Invalid argument: growth must be numeric and >= 1, is ${growth}.`); } return numCycleForGrowth(server, Number(growth), Player); @@ -706,33 +807,27 @@ function NetscriptFunctions(workerScript) { updateDynamicRam("weaken", getRamCost("weaken")); var threads = resolveNetscriptRequestedThreads(workerScript, "weaken", requestedThreads) if (ip === undefined) { - throw makeRuntimeRejectMsg(workerScript, "weaken() call has incorrect number of arguments. Takes 1 argument"); + throw makeRuntimeErrorMsg("weaken", "Takes 1 argument."); } var server = getServer(ip); if (server == null) { - workerScript.scriptRef.log("Cannot weaken(). Invalid IP or hostname passed in: " + ip); - throw makeRuntimeRejectMsg(workerScript, "Cannot weaken(). Invalid IP or hostname passed in: " + ip); + throw makeRuntimeErrorMsg("weaken", `Invalid IP/hostname: ${ip}`); } // No root access or skill level too low const canHack = netscriptCanWeaken(server); if (!canHack.res) { - workerScript.scriptRef.log(`ERROR: ${canHack.msg}`); - throw makeRuntimeRejectMsg(workerScript, canHack.msg); + throw makeRuntimeErrorMsg("weaken", canHack.msg); } var weakenTime = calculateWeakenTime(server); - if (workerScript.disableLogs.ALL == null && workerScript.disableLogs.weaken == null) { - workerScript.scriptRef.log(`Executing weaken('${server.hostname}') in ${formatNumber(weakenTime, 3)} seconds (t=${threads})`); - } + workerScript.log("weaken", `Executing on '${server.hostname}' in ${formatNumber(weakenTime, 3)} seconds (t=${threads})`); return netscriptDelay(weakenTime * 1000, workerScript).then(function() { if (workerScript.env.stopFlag) {return Promise.reject(workerScript);} server.weaken(CONSTANTS.ServerWeakenAmount * threads); workerScript.scriptRef.recordWeaken(server.ip, threads); var expGain = calculateHackingExpGain(server) * threads; - if (workerScript.disableLogs.ALL == null && workerScript.disableLogs.weaken == null) { - workerScript.scriptRef.log(`${server.hostname} security level weakened to ${server.hackDifficulty}. Gained ${numeralWrapper.format(expGain, '0.000a')} hacking exp (t=${threads})`); - } + workerScript.log("weaken", `'${server.hostname}' security level weakened to ${server.hackDifficulty}. Gained ${numeralWrapper.format(expGain, '0.000a')} hacking exp (t=${threads})`); workerScript.scriptRef.onlineExpGained += expGain; Player.gainHackingExp(expGain); return Promise.resolve(CONSTANTS.ServerWeakenAmount * threads); @@ -740,13 +835,13 @@ function NetscriptFunctions(workerScript) { }, print: function(args){ if (args === undefined) { - throw makeRuntimeRejectMsg(workerScript, "print() call has incorrect number of arguments. Takes 1 argument"); + throw makeRuntimeErrorMsg("print", "Takes 1 argument."); } - workerScript.scriptRef.log(args.toString()); + workerScript.print("print", args.toString()); }, tprint: function(args) { if (args === undefined || args == null) { - throw makeRuntimeRejectMsg(workerScript, "tprint() call has incorrect number of arguments. Takes 1 argument"); + throw makeRuntimeErrorMsg("tprint", "Takes 1 argument."); } var x = args.toString(); post(`${workerScript.scriptRef.filename}: ${args.toString()}`); @@ -756,32 +851,28 @@ function NetscriptFunctions(workerScript) { }, disableLog: function(fn) { if (possibleLogs[fn]===undefined) { - throw makeRuntimeRejectMsg(workerScript, `Invalid argument to disableLog: ${fn}`); + throw makeRuntimeErrorMsg("disableLog", `Invalid argument: ${fn}.`); } workerScript.disableLogs[fn] = true; - if (workerScript.disableLogs.ALL == null && workerScript.disableLogs.disableLog == null) { - workerScript.scriptRef.log(`Disabled logging for ${fn}`); - } + workerScript.log("disableLog", `Disabled logging for ${fn}`); }, enableLog: function(fn) { if (possibleLogs[fn]===undefined) { - throw makeRuntimeRejectMsg(workerScript, `Invalid argument to enableLog: ${fn}`); + throw makeRuntimeErrorMsg("enableLog", `Invalid argument: ${fn}.`); } delete workerScript.disableLogs[fn]; - if (workerScript.disableLogs.ALL == null && workerScript.disableLogs.enableLog == null) { - workerScript.scriptRef.log(`Enabled logging for ${fn}`); - } + workerScript.log("enableLog", `Enabled logging for ${fn}`); }, isLogEnabled : function(fn) { if (possibleLogs[fn] === undefined) { - throw makeRuntimeRejectMsg(workerScript, `Invalid argument to isLogEnabled: ${fn}`); + throw makeRuntimeErrorMsg("isLogEnabled", `Invalid argument: ${fn}.`); } return workerScript.disableLogs[fn] ? false : true; }, getScriptLogs: function(fn, ip, ...scriptArgs) { const runningScriptObj = getRunningScript(fn, ip, "getScriptLogs", scriptArgs); if (runningScriptObj == null) { - workerScript.log(`getScriptLogs() failed. ${getCannotFindRunningScriptErrorMessage(fn, ip, scriptArgs)}`); + workerScript.log("getScriptLogs", getCannotFindRunningScriptErrorMessage(fn, ip, scriptArgs)); return ""; } @@ -790,7 +881,7 @@ function NetscriptFunctions(workerScript) { tail: function(fn, ip, ...scriptArgs) { const runningScriptObj = getRunningScript(fn, ip, "tail", scriptArgs); if (runningScriptObj == null) { - workerScript.log(`tail() failed. ${getCannotFindRunningScriptErrorMessage(fn, ip, scriptArgs)} `); + workerScript.log("tail", getCannotFindRunningScriptErrorMessage(fn, ip, scriptArgs)); return; } @@ -799,175 +890,138 @@ function NetscriptFunctions(workerScript) { nuke: function(ip){ updateDynamicRam("nuke", getRamCost("nuke")); if (ip === undefined) { - throw makeRuntimeRejectMsg(workerScript, "nuke call has incorrect number of arguments. Takes 1 argument"); + throw makeRuntimeErrorMsg("nuke", "Takes 1 argument."); } var server = getServer(ip); if (server == null) { - const msg = `Cannot call nuke('${ip}'). Invalid IP/hostname.`; - workerScript.scriptRef.log(msg); - throw makeRuntimeRejectMsg(workerScript, msg); + throw makeRuntimeErrorMsg("nuke", `Invalid IP/hostname: ${ip}.`); } if (!Player.hasProgram(Programs.NukeProgram.name)) { - throw makeRuntimeRejectMsg(workerScript, "You do not have the NUKE.exe virus!"); + throw makeRuntimeErrorMsg("nuke", "You do not have the NUKE.exe virus!"); } if (server.openPortCount < server.numOpenPortsRequired) { - throw makeRuntimeRejectMsg(workerScript, "Not enough ports opened to use NUKE.exe virus"); + throw makeRuntimeErrorMsg("nuke", "Not enough ports opened to use NUKE.exe virus."); } if (server.hasAdminRights) { - if (workerScript.disableLogs.ALL == null && workerScript.disableLogs.nuke == null) { - workerScript.scriptRef.log(`Already have root access to ${server.hostname}`); - } + workerScript.log("nuke", `Already have root access to '${server.hostname}'.`); } else { server.hasAdminRights = true; - if (workerScript.disableLogs.ALL == null && workerScript.disableLogs.nuke == null) { - workerScript.scriptRef.log(`Executed NUKE.exe virus on ${server.hostname} to gain root access`); - } + workerScript.log("nuke", `Executed NUKE.exe virus on '${server.hostname}' to gain root access.`); } return true; }, brutessh: function(ip){ updateDynamicRam("brutessh", getRamCost("brutessh")); if (ip === undefined) { - throw makeRuntimeRejectMsg(workerScript, "brutessh call has incorrect number of arguments. Takes 1 argument"); + throw makeRuntimeErrorMsg("brutessh", "Takes 1 argument."); } var server = getServer(ip); if (server == null) { - const msg = `Cannot call brutessh('${ip}'). Invalid IP/hostname.`; - workerScript.scriptRef.log(msg); - throw makeRuntimeRejectMsg(workerScript, msg); + throw makeRuntimeErrorMsg("brutessh", `Invalid IP/hostname: ${ip}.`); } if (!Player.hasProgram(Programs.BruteSSHProgram.name)) { - workerScript.scriptRef.log("You do not have the BruteSSH.exe program!"); - throw makeRuntimeRejectMsg(workerScript, "You do not have the BruteSSH.exe program!"); + throw makeRuntimeErrorMsg("brutessh", "You do not have the BruteSSH.exe program!"); } if (!server.sshPortOpen) { - if (workerScript.disableLogs.ALL == null && workerScript.disableLogs.brutessh == null) { - workerScript.scriptRef.log(`Executed BruteSSH.exe on ${server.hostname} to open SSH port (22)`); - } + workerScript.log("brutessh", `Executed BruteSSH.exe on '${server.hostname}' to open SSH port (22).`); server.sshPortOpen = true; ++server.openPortCount; } else { - if (workerScript.disableLogs.ALL == null && workerScript.disableLogs.brutessh == null) { - workerScript.scriptRef.log(`SSH Port (22) already opened on ${server.hostname}`); - } + workerScript.log("brutessh", `SSH Port (22) already opened on '${server.hostname}'.`); } return true; }, ftpcrack: function(ip) { updateDynamicRam("ftpcrack", getRamCost("ftpcrack")); if (ip === undefined) { - throw makeRuntimeRejectMsg(workerScript, "Program call has incorrect number of arguments. Takes 1 argument"); + throw makeRuntimeErrorMsg("ftpcrack", "Takes 1 argument."); } var server = getServer(ip); if (server == null) { - const msg = `Cannot call ftpcrack('${ip}'). Invalid IP/hostname.` - workerScript.scriptRef.log(msg); - throw makeRuntimeRejectMsg(workerScript, msg); + throw makeRuntimeErrorMsg("ftpcrack", `Invalid IP/hostname: ${ip}.`); } if (!Player.hasProgram(Programs.FTPCrackProgram.name)) { - throw makeRuntimeRejectMsg(workerScript, "You do not have the FTPCrack.exe program!"); + throw makeRuntimeErrorMsg("ftpcrack", "You do not have the FTPCrack.exe program!"); } if (!server.ftpPortOpen) { - if (workerScript.disableLogs.ALL == null && workerScript.disableLogs.ftpcrack == null) { - workerScript.scriptRef.log(`Executed FTPCrack.exe on ${server.hostname} to open FTP port (21)`); - } + workerScript.log("ftpcrack", `Executed FTPCrack.exe on '${server.hostname}' to open FTP port (21).`); server.ftpPortOpen = true; ++server.openPortCount; } else { - if (workerScript.disableLogs.ALL == null && workerScript.disableLogs.ftpcrack == null) { - workerScript.scriptRef.log(`FTP Port (21) already opened on ${server.hostname}`); - } + workerScript.log("ftpcrack", `FTP Port (21) already opened on '${server.hostname}'.`); } return true; }, relaysmtp: function(ip) { updateDynamicRam("relaysmtp", getRamCost("relaysmtp")); if (ip === undefined) { - throw makeRuntimeRejectMsg(workerScript, "Program call has incorrect number of arguments. Takes 1 argument"); + throw makeRuntimeErrorMsg("relaysmtp", "Takes 1 argument."); } var server = getServer(ip); if (server == null) { - const msg = `Cannot call relaysmtp('${ip}'). Invalid IP/hostname.` - workerScript.scriptRef.log(msg); - throw makeRuntimeRejectMsg(workerScript, msg); + throw makeRuntimeErrorMsg("relaysmtp", `Invalid IP/hostname: ${ip}.`); } if (!Player.hasProgram(Programs.RelaySMTPProgram.name)) { - throw makeRuntimeRejectMsg(workerScript, "You do not have the relaySMTP.exe program!"); + throw makeRuntimeErrorMsg("relaysmtp", "You do not have the relaySMTP.exe program!"); } if (!server.smtpPortOpen) { - if (workerScript.disableLogs.ALL == null && workerScript.disableLogs.relaysmtp == null) { - workerScript.scriptRef.log(`Executed relaySMTP.exe on ${server.hostname} to open SMTP port (25)`); - } + workerScript.log("relaysmtp", `Executed relaySMTP.exe on '${server.hostname}' to open SMTP port (25).`); server.smtpPortOpen = true; ++server.openPortCount; } else { - if (workerScript.disableLogs.ALL == null && workerScript.disableLogs.relaysmtp == null) { - workerScript.scriptRef.log(`SMTP Port (25) already opened on ${server.hostname}`); - } + workerScript.log("relaysmtp", `SMTP Port (25) already opened on '${server.hostname}'.`); } return true; }, httpworm: function(ip) { updateDynamicRam("httpworm", getRamCost("httpworm")); if (ip === undefined) { - throw makeRuntimeRejectMsg(workerScript, "Program call has incorrect number of arguments. Takes 1 argument"); + throw makeRuntimeErrorMsg("httpworm", "Takes 1 argument"); } var server = getServer(ip); if (server == null) { - const msg = `Cannot call httpworm('${ip}'). Invalid IP/hostname.` - workerScript.scriptRef.log(msg); - throw makeRuntimeRejectMsg(workerScript, msg); + throw makeRuntimeErrorMsg("httpworm", `Invalid IP/hostname: ${ip}`); } if (!Player.hasProgram(Programs.HTTPWormProgram.name)) { - throw makeRuntimeRejectMsg(workerScript, "You do not have the HTTPWorm.exe program!"); + throw makeRuntimeErrorMsg("httpworm", "You do not have the HTTPWorm.exe program!"); } if (!server.httpPortOpen) { - if (workerScript.disableLogs.ALL == null && workerScript.disableLogs.httpworm == null) { - workerScript.scriptRef.log(`Executed HTTPWorm.exe on ${server.hostname} to open HTTP port (80)`); - } + workerScript.log("httpworm", `Executed HTTPWorm.exe on '${server.hostname}' to open HTTP port (80).`); server.httpPortOpen = true; ++server.openPortCount; } else { - if (workerScript.disableLogs.ALL == null && workerScript.disableLogs.httpworm == null) { - workerScript.scriptRef.log(`HTTP Port (80) already opened on ${server.hostname}`); - } + workerScript.log("httpworm", `HTTP Port (80) already opened on '${server.hostname}'.`); } return true; }, sqlinject: function(ip) { updateDynamicRam("sqlinject", getRamCost("sqlinject")); if (ip === undefined) { - throw makeRuntimeRejectMsg(workerScript, "Program call has incorrect number of arguments. Takes 1 argument"); + throw makeRuntimeErrorMsg("sqlinject", "Takes 1 argument."); } var server = getServer(ip); if (server == null) { - const msg = `Cannot call sqlinject('${ip}'). Invalid IP/hostname.` - workerScript.scriptRef.log(msg); - throw makeRuntimeRejectMsg(workerScript, msg); + throw makeRuntimeErrorMsg("sqlinject", `Invalid IP/hostname: ${ip}`); } if (!Player.hasProgram(Programs.SQLInjectProgram.name)) { - throw makeRuntimeRejectMsg(workerScript, "You do not have the SQLInject.exe program!"); + throw makeRuntimeErrorMsg("sqlinject", "You do not have the SQLInject.exe program!"); } if (!server.sqlPortOpen) { - if (workerScript.disableLogs.ALL == null && workerScript.disableLogs.sqlinject == null) { - workerScript.scriptRef.log(`Executed SQLInject.exe on ${server.hostname} to open SQL port (1433)`); - } + workerScript.log("sqlinject", `Executed SQLInject.exe on '${server.hostname}' to open SQL port (1433).`); server.sqlPortOpen = true; ++server.openPortCount; } else { - if (workerScript.disableLogs.ALL == null && workerScript.disableLogs.sqlinject == null) { - workerScript.scriptRef.log(`SQL Port (1433) already opened on ${server.hostname}`); - } + workerScript.log("sqlinject", `SQL Port (1433) already opened on '${server.hostname}'.`); } return true; }, - run: function(scriptname,threads = 1) { + run: function(scriptname, threads=1) { updateDynamicRam("run", getRamCost("run")); if (scriptname === undefined) { - throw makeRuntimeRejectMsg(workerScript, "run() call has incorrect number of arguments. Usage: run(scriptname, [numThreads], [arg1], [arg2]...)"); + throw makeRuntimeErrorMsg("run", "Usage: run(scriptname, [numThreads], [arg1], [arg2]...)"); } if (isNaN(threads) || threads <= 0) { - throw makeRuntimeRejectMsg(workerScript, "Invalid argument for thread count passed into run(). Must be numeric and greater than 0"); + throw makeRuntimeErrorMsg("run", `Invalid thread count. Must be numeric and > 0, is ${thread}`); } var argsForNewScript = []; for (var i = 2; i < arguments.length; ++i) { @@ -975,18 +1029,18 @@ function NetscriptFunctions(workerScript) { } var scriptServer = getServer(workerScript.serverIp); if (scriptServer == null) { - throw makeRuntimeRejectMsg(workerScript, "Could not find server. This is a bug in the game. Report to game dev"); + throw makeRuntimeErrorMsg("run", "Could not find server. This is a bug. Report to dev."); } - return runScriptFromScript(scriptServer, scriptname, argsForNewScript, workerScript, threads); + return runScriptFromScript("run", scriptServer, scriptname, argsForNewScript, workerScript, threads); }, exec: function(scriptname, ip, threads = 1) { updateDynamicRam("exec", getRamCost("exec")); if (scriptname === undefined || ip === undefined) { - throw makeRuntimeRejectMsg(workerScript, "exec() call has incorrect number of arguments. Usage: exec(scriptname, server, [numThreads], [arg1], [arg2]...)"); + throw makeRuntimeErrorMsg("exec", "Usage: exec(scriptname, server, [numThreads], [arg1], [arg2]...)"); } if (isNaN(threads) || threads <= 0) { - throw makeRuntimeRejectMsg(workerScript, "Invalid argument for thread count passed into exec(). Must be numeric and greater than 0"); + throw makeRuntimeErrorMsg("exec", `Invalid thread count. Must be numeric and > 0, is ${threads}`); } var argsForNewScript = []; for (var i = 3; i < arguments.length; ++i) { @@ -994,23 +1048,20 @@ function NetscriptFunctions(workerScript) { } var server = getServer(ip); if (server == null) { - throw makeRuntimeRejectMsg(workerScript, "Invalid hostname/ip passed into exec() command: " + ip); + throw makeRuntimeErrorMsg("exec", `Invalid IP/hostname: ${ip}`); } - return runScriptFromScript(server, scriptname, argsForNewScript, workerScript, threads); + return runScriptFromScript("exec", server, scriptname, argsForNewScript, workerScript, threads); }, spawn: function(scriptname, threads) { updateDynamicRam("spawn", getRamCost("spawn")); - if (scriptname == null || threads == null) { - throw makeRuntimeRejectMsg(workerScript, "Invalid scriptname or numThreads argument passed to spawn()"); + if (!scriptname || !threads) { + throw makeRuntimeErrorMsg("spawn", "Usage: spawn(scriptname, threads)"); } const spawnDelay = 10; setTimeoutRef(() => { - if (scriptname === undefined) { - throw makeRuntimeRejectMsg(workerScript, "spawn() call has incorrect number of arguments. Usage: spawn(scriptname, numThreads, [arg1], [arg2]...)"); - } if (isNaN(threads) || threads <= 0) { - throw makeRuntimeRejectMsg(workerScript, "Invalid argument for thread count passed into run(). Must be numeric and greater than 0"); + throw makeRuntimeErrorMsg("spawn", `Invalid thread count. Must be numeric and > 0, is ${threads}`); } var argsForNewScript = []; for (var i = 2; i < arguments.length; ++i) { @@ -1018,19 +1069,17 @@ function NetscriptFunctions(workerScript) { } var scriptServer = getServer(workerScript.serverIp); if (scriptServer == null) { - throw makeRuntimeRejectMsg(workerScript, "Could not find server. This is a bug in the game. Report to game dev"); + throw makeRuntimeErrorMsg("spawn", "Could not find server. This is a bug. Report to dev"); } - return runScriptFromScript(scriptServer, scriptname, argsForNewScript, workerScript, threads); + return runScriptFromScript("spawn", scriptServer, scriptname, argsForNewScript, workerScript, threads); }, spawnDelay * 1e3); - if (workerScript.shouldLog("spawn")) { - workerScript.log(`spawn() will execute ${scriptname} in ${spawnDelay} seconds`); - } + workerScript.log("spawn", `Will execute '${scriptname}' in ${spawnDelay} seconds`); workerScript.running = false; // Prevent workerScript from "finishing execution naturally" if (killWorkerScript(workerScript)) { - workerScript.log("Exiting..."); + workerScript.log("spawn", "Exiting..."); } }, kill: function(filename, ip, ...scriptArgs) { @@ -1044,13 +1093,13 @@ function NetscriptFunctions(workerScript) { } else { // Kill by filename/ip if (filename === undefined || ip === undefined) { - throw makeRuntimeRejectMsg(workerScript, "kill() call has incorrect number of arguments. Usage: kill(scriptname, server, [arg1], [arg2]...)"); + throw makeRuntimeErrorMsg("kill", "Usage: kill(scriptname, server, [arg1], [arg2]...)"); } const server = safeGetServer(ip); const runningScriptObj = getRunningScript(filename, ip, "kill", scriptArgs); if (runningScriptObj == null) { - workerScript.log(`kill() failed. ${getCannotFindRunningScriptErrorMessage(filename, ip, scriptArgs)}`) + workerScript.log("kill", getCannotFindRunningScriptErrorMessage(filename, ip, scriptArgs)); return false; } @@ -1060,19 +1109,17 @@ function NetscriptFunctions(workerScript) { if (res) { if (workerScript.shouldLog("kill")) { if (killByPid) { - workerScript.log(`Killing script with PID ${filename}`); + workerScript.log("kill", `Killing script with PID ${filename}`); } else { - workerScript.log(`Killing ${filename} on ${ip} with args: ${arrayToString(scriptArgs)}.`); + workerScript.log("kill", `Killing ${filename} on ${ip} with args: ${arrayToString(scriptArgs)}.`); } } return true; } else { - if (workerScript.shouldLog("kill")) { - if (killByPid) { - workerScript.log(`kill() failed. No such script with PID ${filename}`); - } else { - workerScript.log(`kill() failed. No such script ${filename} on ${ip} with args: ${arrayToString(scriptArgs)}`); - } + if (killByPid) { + workerScript.log("kill", `No script with PID ${filename}`); + } else { + workerScript.log("kill", `No such script '${filename}' on '${ip}' with args: ${arrayToString(scriptArgs)}`); } return false; } @@ -1080,36 +1127,33 @@ function NetscriptFunctions(workerScript) { killall: function(ip=workerScript.serverIp) { updateDynamicRam("killall", getRamCost("killall")); if (ip === undefined) { - throw makeRuntimeRejectMsg(workerScript, "killall() call has incorrect number of arguments. Takes 1 argument"); + throw makeRuntimeErrorMsg("killall", "Takes 1 argument"); } const server = getServer(ip); if (server == null) { - workerScript.scriptRef.log("killall() failed. Invalid IP or hostname passed in: " + ip); - throw makeRuntimeRejectMsg(workerScript, "killall() failed. Invalid IP or hostname passed in: " + ip); + throw makeRuntimeErrorMsg("killall", `Invalid IP/hostname: ${ip}`); } const scriptsRunning = (server.runningScripts.length > 0); for (let i = server.runningScripts.length-1; i >= 0; --i) { killWorkerScript(server.runningScripts[i], server.ip, false); } WorkerScriptStartStopEventEmitter.emitEvent(); - if (workerScript.disableLogs.ALL == null && workerScript.disableLogs.killall == null) { - workerScript.scriptRef.log("killall(): Killing all scripts on " + server.hostname + ". May take a few minutes for the scripts to die"); - } + workerScript.log("killall", `Killing all scripts on ${server.hostname}. May take a few minutes for the scripts to die.`); return scriptsRunning; }, exit : function() { workerScript.running = false; // Prevent workerScript from "finishing execution naturally" if (killWorkerScript(workerScript)) { - workerScript.log("Exiting..."); + workerScript.log("exit", "Exiting..."); } else { - workerScript.log("Exit failed(). This is a bug please contact game developer"); + workerScript.log("exit", "Failed. This is a bug. Report to dev."); } }, scp: function(scriptname, ip1, ip2) { updateDynamicRam("scp", getRamCost("scp")); if (arguments.length !== 2 && arguments.length !== 3) { - throw makeRuntimeRejectMsg(workerScript, "ERROR: scp() call has incorrect number of arguments. Takes 2 or 3 arguments"); + throw makeRuntimeErrorMsg("scp", "Takes 2 or 3 arguments"); } if (scriptname && scriptname.constructor === Array) { // Recursively call scp on all elements of array @@ -1124,44 +1168,44 @@ function NetscriptFunctions(workerScript) { // Invalid file type if (!isValidFilePath(scriptname)) { - throw makeRuntimeRejectMsg(workerScript, `Error: scp() failed due to invalid filename: ${scriptname}`); + throw makeRuntimeErrorMsg("scp", `Invalid filename: ${scriptname}`); } // Invalid file name if (!scriptname.endsWith(".lit") && !isScriptFilename(scriptname) && !scriptname.endsWith("txt")) { - throw makeRuntimeRejectMsg(workerScript, "ERROR: scp() does not work with this file type. It only works for .script, .lit, and .txt files"); + throw makeRuntimeErrorMsg("scp", "Only works for .script, .lit, and .txt files"); } var destServer, currServ; if (ip2 != null) { // 3 Argument version: scriptname, source, destination if (scriptname === undefined || ip1 === undefined || ip2 === undefined) { - throw makeRuntimeRejectMsg(workerScript, "ERROR: scp() call has incorrect number of arguments. Takes 2 or 3 arguments"); + throw makeRuntimeErrorMsg("scp", "Takes 2 or 3 arguments"); } destServer = getServer(ip2); if (destServer == null) { - throw makeRuntimeRejectMsg(workerScript, `ERROR: Invalid hostname/ip passed into scp() command: ${ip2}`); + throw makeRuntimeErrorMsg("scp", `Invalid IP/hostname: ${ip2}`); } currServ = getServer(ip1); if (currServ == null) { - throw makeRuntimeRejectMsg(workerScript, `ERROR: Invalid hostname/ip passed into scp() command: ${ip1}`); + throw makeRuntimeErrorMsg("scp", `Invalid IP/hostname: ${ip1}`); } } else if (ip1 != null) { // 2 Argument version: scriptname, destination if (scriptname === undefined || ip1 === undefined) { - throw makeRuntimeRejectMsg(workerScript, "ERROR: scp() call has incorrect number of arguments. Takes 2 or 3 arguments"); + throw makeRuntimeErrorMsg("scp", "Takes 2 or 3 arguments"); } destServer = getServer(ip1); if (destServer == null) { - throw makeRuntimeRejectMsg(workerScript, `ERROR: Invalid hostname/ip passed into scp() command: ${ip1}`); + throw makeRuntimeErrorMsg("scp", `Invalid IP/hostname: ${ip1}`); } currServ = getServer(workerScript.serverIp); if (currServ == null) { - throw makeRuntimeRejectMsg(workerScript, "Could not find server ip for this script. This is a bug please contact game developer"); + throw makeRuntimeErrorMsg("scp", "Could not find server ip for this script. This is a bug. Report to dev."); } } else { - throw makeRuntimeRejectMsg(workerScript, "ERROR: scp() call has incorrect number of arguments. Takes 2 or 3 arguments"); + throw makeRuntimeErrorMsg("scp", "Takes 2 or 3 arguments"); } // Scp for lit files @@ -1175,22 +1219,18 @@ function NetscriptFunctions(workerScript) { } if (!found) { - workerScript.scriptRef.log(`${scriptname} does not exist. scp() failed`); + workerScript.log("scp", `File '${scriptname}' does not exist.`); return false; } for (var i = 0; i < destServer.messages.length; ++i) { if (destServer.messages[i] === scriptname) { - if (workerScript.disableLogs.ALL == null && workerScript.disableLogs.scp == null) { - workerScript.scriptRef.log(`${scriptname} copied over to ${destServer.hostname}`); - } + workerScript.log("scp", `File '${scriptname}' copied over to '${destServer.hostname}'.`); return true; // Already exists } } destServer.messages.push(scriptname); - if (workerScript.disableLogs.ALL == null && workerScript.disableLogs.scp == null) { - workerScript.scriptRef.log(`${scriptname} copied over to ${destServer.hostname}`); - } + workerScript.log("scp", `File '${scriptname}' copied over to '${destServer.hostname}'.`); return true; } @@ -1206,7 +1246,7 @@ function NetscriptFunctions(workerScript) { } if (!found) { - workerScript.scriptRef.log(scriptname + " does not exist. scp() failed"); + workerScript.log("scp", `File '${scriptname}' does not exist.`); return false; } @@ -1214,41 +1254,34 @@ function NetscriptFunctions(workerScript) { if (destServer.textFiles[i].fn === scriptname) { // Overwrite destServer.textFiles[i].text = txtFile.text; - if (workerScript.disableLogs.ALL == null && workerScript.disableLogs.scp == null) { - workerScript.scriptRef.log(scriptname + " copied over to " + destServer.hostname); - } + workerScript.log("scp", `File '${scriptname}' copied over to '${destServer.hostname}'.`); return true; } } var newFile = new TextFile(txtFile.fn, txtFile.text); destServer.textFiles.push(newFile); - if (workerScript.disableLogs.ALL == null && workerScript.disableLogs.scp == null) { - workerScript.scriptRef.log(scriptname + " copied over to " + destServer.hostname); - } + workerScript.log("scp", `File '${scriptname}' copied over to '${destServer.hostname}'.`); return true; } // Scp for script files - var sourceScript = null; - for (var i = 0; i < currServ.scripts.length; ++i) { + let sourceScript = null; + for (let i = 0; i < currServ.scripts.length; ++i) { if (scriptname == currServ.scripts[i].filename) { sourceScript = currServ.scripts[i]; break; } } if (sourceScript == null) { - workerScript.scriptRef.log(scriptname + " does not exist. scp() failed"); + workerScript.log("scp", `File '${scriptname}' does not exist.`); return false; } // Overwrite script if it already exists - for (var i = 0; i < destServer.scripts.length; ++i) { + for (let i = 0; i < destServer.scripts.length; ++i) { if (scriptname == destServer.scripts[i].filename) { - if (workerScript.disableLogs.ALL == null && workerScript.disableLogs.scp == null) { - workerScript.scriptRef.log("WARNING: " + scriptname + " already exists on " + destServer.hostname + " and it will be overwritten."); - workerScript.scriptRef.log(scriptname + " overwritten on " + destServer.hostname); - } - var oldScript = destServer.scripts[i]; + workerScript.log("scp", `WARNING: File '${scriptname}' overwritten on '${destServer.hostname}'`); + const oldScript = destServer.scripts[i]; oldScript.code = sourceScript.code; oldScript.ramUsage = sourceScript.ramUsage; oldScript.markUpdated(); @@ -1257,35 +1290,32 @@ function NetscriptFunctions(workerScript) { } // Create new script if it does not already exist - var newScript = new Script(scriptname); + const newScript = new Script(scriptname); newScript.code = sourceScript.code; newScript.ramUsage = sourceScript.ramUsage; newScript.server = destServer.ip; destServer.scripts.push(newScript); - if (workerScript.disableLogs.ALL == null && workerScript.disableLogs.scp == null) { - workerScript.scriptRef.log(scriptname + " copied over to " + destServer.hostname); - } + workerScript.log("scp", `File '${scriptname}' copied over to '${destServer.hostname}'.`); return true; }, ls: function(ip, grep) { updateDynamicRam("ls", getRamCost("ls")); if (ip === undefined) { - throw makeRuntimeRejectMsg(workerScript, "ls() failed because of invalid arguments. Usage: ls(ip/hostname, [grep filter])"); + throw makeRuntimeErrorMsg("ls", "Usage: ls(ip/hostname, [grep filter])"); } - var server = getServer(ip); + const server = getServer(ip); if (server == null) { - workerScript.scriptRef.log("ls() failed. Invalid IP or hostname passed in: " + ip); - throw makeRuntimeRejectMsg(workerScript, "ls() failed. Invalid IP or hostname passed in: " + ip); + throw makeRuntimeErrorMsg("ls", `Invalid IP/hostname: ${ip}`); } // Get the grep filter, if one exists - var filter = false; + let filter = false; if (arguments.length >= 2) { filter = grep.toString(); } - var allFiles = []; - for (var i = 0; i < server.programs.length; i++) { + const allFiles = []; + for (let i = 0; i < server.programs.length; i++) { if (filter) { if (server.programs[i].includes(filter)) { allFiles.push(server.programs[i]); @@ -1294,7 +1324,7 @@ function NetscriptFunctions(workerScript) { allFiles.push(server.programs[i]); } } - for (var i = 0; i < server.scripts.length; i++) { + for (let i = 0; i < server.scripts.length; i++) { if (filter) { if (server.scripts[i].filename.includes(filter)) { allFiles.push(server.scripts[i].filename); @@ -1304,7 +1334,7 @@ function NetscriptFunctions(workerScript) { } } - for (var i = 0; i < server.messages.length; i++) { + for (let i = 0; i < server.messages.length; i++) { if (filter) { if (server.messages[i] instanceof Message) { if (server.messages[i].filename.includes(filter)) { @@ -1350,8 +1380,7 @@ function NetscriptFunctions(workerScript) { updateDynamicRam("ps", getRamCost("ps")); var server = getServer(ip); if (server == null){ - workerScript.scriptRef.log("ps() failed. Invalid IP or hostname passed in: " + ip); - throw makeRuntimeRejectMsg(workerScript, "ps() failed. Invalid IP or hostname passed in: " + ip); + throw makeRuntimeErrorMsg("ps", `Invalid IP/hostname: ${ip}`); } const processes = []; for (const i in server.runningScripts) { @@ -1363,12 +1392,11 @@ function NetscriptFunctions(workerScript) { hasRootAccess: function(ip) { updateDynamicRam("hasRootAccess", getRamCost("hasRootAccess")); if (ip===undefined){ - throw makeRuntimeRejectMsg(workerScript, "hasRootAccess() call has incorrect number of arguments. Takes 1 argument"); + throw makeRuntimeErrorMsg("hasRootAccess", "Takes 1 argument"); } var server = getServer(ip); if (server == null){ - workerScript.scriptRef.log("hasRootAccess() failed. Invalid IP or hostname passed in: " + ip); - throw makeRuntimeRejectMsg(workerScript, "hasRootAccess() failed. Invalid IP or hostname passed in: " + ip); + throw makeRuntimeErrorMsg("hasRootAccess", `Invalid IP/hostname: ${ip}`); } return server.hasAdminRights; }, @@ -1376,7 +1404,7 @@ function NetscriptFunctions(workerScript) { updateDynamicRam("getIp", getRamCost("getIp")); var scriptServer = getServer(workerScript.serverIp); if (scriptServer == null) { - throw makeRuntimeRejectMsg(workerScript, "Could not find server. This is a bug in the game. Report to game dev"); + throw makeRuntimeErrorMsg("getIp", "Could not find server. This is a bug. Report to dev."); } return scriptServer.ip; }, @@ -1384,16 +1412,14 @@ function NetscriptFunctions(workerScript) { updateDynamicRam("getHostname", getRamCost("getHostname")); var scriptServer = getServer(workerScript.serverIp); if (scriptServer == null) { - throw makeRuntimeRejectMsg(workerScript, "Could not find server. This is a bug in the game. Report to game dev"); + throw makeRuntimeErrorMsg(workerScript, "Could not find server. This is a bug. Report to dev."); } return scriptServer.hostname; }, getHackingLevel: function() { updateDynamicRam("getHackingLevel", getRamCost("getHackingLevel")); Player.updateSkillLevels(); - if (workerScript.disableLogs.ALL == null && workerScript.disableLogs.getHackingLevel == null) { - workerScript.scriptRef.log("getHackingLevel() returned " + Player.hacking_skill); - } + workerScript.log("getHackingLevel", `returned ${Player.hacking_skill}`); return Player.hacking_skill; }, getHackingMultipliers: function() { @@ -1418,7 +1444,7 @@ function NetscriptFunctions(workerScript) { getBitNodeMultipliers: function() { updateDynamicRam("getBitNodeMultipliers", getRamCost("getBitNodeMultipliers")); if (SourceFileFlags[5] <= 0) { - throw makeRuntimeRejectMsg(workerScript, "Cannot run getBitNodeMultipliers(). It requires Source-File 5 to run."); + throw makeRuntimeErrorMsg("getBitNodeMultipliers", "Requires Source-File 5 to run."); } let copy = Object.assign({}, BitNodeMultipliers); return copy; @@ -1429,85 +1455,65 @@ function NetscriptFunctions(workerScript) { if (failOnHacknetServer(server, "getServerMoneyAvailable")) { return 0; } if (server.hostname == "home") { // Return player's money - if (workerScript.shouldLog("getServerMoneyAvailable")) { - workerScript.log("getServerMoneyAvailable('home') returned player's money: $" + formatNumber(Player.money.toNumber(), 2)); - } + workerScript.log("getServerMoneyAvailable", `returned player's money: $${formatNumber(Player.money.toNumber(), 2)}`); return Player.money.toNumber(); } - if (workerScript.shouldLog("getServerMoneyAvailable")) { - workerScript.log("getServerMoneyAvailable() returned " + formatNumber(server.moneyAvailable, 2) + " for " + server.hostname); - } + workerScript.log("getServerMoneyAvailable", `returned ${formatNumber(server.moneyAvailable, 2)} for '${server.hostname}`); return server.moneyAvailable; }, getServerSecurityLevel: function(ip) { updateDynamicRam("getServerSecurityLevel", getRamCost("getServerSecurityLevel")); const server = safeGetServer(ip, "getServerSecurityLevel"); if (failOnHacknetServer(server, "getServerSecurityLevel")) { return 1; } - if (workerScript.shouldLog("getServerSecurityLevel")) { - workerScript.log("getServerSecurityLevel() returned " + formatNumber(server.hackDifficulty, 3) + " for " + server.hostname); - } + workerScript.log("getServerSecurityLevel", `returned ${formatNumber(server.hackDifficulty, 3)} for '${server.hostname}'`); return server.hackDifficulty; }, getServerBaseSecurityLevel: function(ip) { updateDynamicRam("getServerBaseSecurityLevel", getRamCost("getServerBaseSecurityLevel")); const server = safeGetServer(ip, "getServerBaseSecurityLevel"); if (failOnHacknetServer(server, "getServerBaseSecurityLevel")) { return 1; } - if (workerScript.shouldLog("getServerBaseSecurityLevel")) { - workerScript.log("getServerBaseSecurityLevel() returned " + formatNumber(server.baseDifficulty, 3) + " for " + server.hostname); - } + workerScript.log("getServerBaseSecurityLevel", `returned ${formatNumber(server.baseDifficulty, 3)} for '${server.hostname}'`); return server.baseDifficulty; }, getServerMinSecurityLevel: function(ip) { updateDynamicRam("getServerMinSecurityLevel", getRamCost("getServerMinSecurityLevel")); const server = safeGetServer(ip, "getServerMinSecurityLevel"); if (failOnHacknetServer(server, "getServerMinSecurityLevel")) { return 1; } - if (workerScript.shouldLog("getServerMinSecurityLevel")) { - workerScript.log("getServerMinSecurityLevel() returned " + formatNumber(server.minDifficulty, 3) + " for " + server.hostname); - } + workerScript.log("getServerMinSecurityLevel", `returned ${formatNumber(server.minDifficulty, 3)} for ${server.hostname}`); return server.minDifficulty; }, getServerRequiredHackingLevel: function(ip) { updateDynamicRam("getServerRequiredHackingLevel", getRamCost("getServerRequiredHackingLevel")); const server = safeGetServer(ip, "getServerRequiredHackingLevel"); if (failOnHacknetServer(server, "getServerRequiredHackingLevel")) { return 1; } - if (workerScript.shouldLog("getServerRequiredHackingLevel")) { - workerScript.log("getServerRequiredHackingLevel returned " + formatNumber(server.requiredHackingSkill, 0) + " for " + server.hostname); - } + workerScript.log("getServerRequiredHackingLevel", `returned ${formatNumber(server.requiredHackingSkill, 0)} for '${server.hostname}'`); return server.requiredHackingSkill; }, getServerMaxMoney: function(ip) { updateDynamicRam("getServerMaxMoney", getRamCost("getServerMaxMoney")); const server = safeGetServer(ip, "getServerMaxMoney"); if (failOnHacknetServer(server, "getServerMaxMoney")) { return 0; } - if (workerScript.shouldLog("getServerMaxMoney")) { - workerScript.log("getServerMaxMoney() returned " + formatNumber(server.moneyMax, 0) + " for " + server.hostname); - } + workerScript.log("getServerMaxMoney", `returned ${formatNumber(server.moneyMax, 0)} for '${server.hostname}'`); return server.moneyMax; }, getServerGrowth: function(ip) { updateDynamicRam("getServerGrowth", getRamCost("getServerGrowth")); const server = safeGetServer(ip, "getServerGrowth"); if (failOnHacknetServer(server, "getServerGrowth")) { return 1; } - if (workerScript.shouldLog("getServerGrowth")) { - workerScript.log("getServerGrowth() returned " + formatNumber(server.serverGrowth, 0) + " for " + server.hostname); - } + workerScript.log("getServerGrowth", `returned ${formatNumber(server.serverGrowth, 0)} for '${server.hostname}'`); return server.serverGrowth; }, getServerNumPortsRequired: function(ip) { updateDynamicRam("getServerNumPortsRequired", getRamCost("getServerNumPortsRequired")); const server = safeGetServer(ip, "getServerNumPortsRequired"); if (failOnHacknetServer(server, "getServerNumPortsRequired")) { return 5; } - if (workerScript.shouldLog("getServerNumPortsRequired")) { - workerScript.log("getServerNumPortsRequired() returned " + formatNumber(server.numOpenPortsRequired, 0) + " for " + server.hostname); - } + workerScript.log("getServerNumPortsRequired", `returned ${formatNumber(server.numOpenPortsRequired, 0)} for '${server.hostname}'`); return server.numOpenPortsRequired; }, getServerRam: function(ip) { updateDynamicRam("getServerRam", getRamCost("getServerRam")); const server = safeGetServer(ip, "getServerRam"); - if (workerScript.shouldLog("getServerRam")) { - workerScript.log("getServerRam() returned [" + formatNumber(server.maxRam, 2) + "GB, " + formatNumber(server.ramUsed, 2) + "GB]"); - } + workerScript.log("getServerRam", `returned [${formatNumber(server.maxRam, 2)}GB, ${formatNumber(server.ramUsed, 2)}GB]`); return [server.maxRam, server.ramUsed]; }, serverExists: function(ip) { @@ -1517,12 +1523,11 @@ function NetscriptFunctions(workerScript) { fileExists: function(filename,ip=workerScript.serverIp) { updateDynamicRam("fileExists", getRamCost("fileExists")); if (filename === undefined) { - throw makeRuntimeRejectMsg(workerScript, "fileExists() call has incorrect number of arguments. Usage: fileExists(scriptname, [server])"); + throw makeRuntimeErrorMsg("fileExists", "Usage: fileExists(scriptname, [server])"); } var server = getServer(ip); if (server == null) { - workerScript.scriptRef.log("fileExists() failed. Invalid IP or hostname passed in: " + ip); - throw makeRuntimeRejectMsg(workerScript, "fileExists() failed. Invalid IP or hostname passed in: " + ip); + throw makeRuntimeErrorMsg("fileExists", `Invalid IP/hostname: ${ip}`); } for (var i = 0; i < server.scripts.length; ++i) { if (filename == server.scripts[i].filename) { @@ -1549,12 +1554,11 @@ function NetscriptFunctions(workerScript) { isRunning: function(filename,ip) { updateDynamicRam("isRunning", getRamCost("isRunning")); if (filename === undefined || ip === undefined) { - throw makeRuntimeRejectMsg(workerScript, "isRunning() call has incorrect number of arguments. Usage: isRunning(scriptname, server, [arg1], [arg2]...)"); + throw makeRuntimeErrorMsg("isRunning", "Usage: isRunning(scriptname, server, [arg1], [arg2]...)"); } var server = getServer(ip); if (server == null) { - workerScript.scriptRef.log("isRunning() failed. Invalid IP or hostname passed in: " + ip); - throw makeRuntimeRejectMsg(workerScript, "isRunning() failed. Invalid IP or hostname passed in: " + ip); + throw makeRuntimeErrorMsg("isRunning", `Invalid IP/hostname: ${ip}`); } var argsForTargetScript = []; for (var i = 2; i < arguments.length; ++i) { @@ -1593,7 +1597,7 @@ function NetscriptFunctions(workerScript) { checkTixApiAccess("getStockPosition"); var stock = SymbolToStockMap[symbol]; if (stock == null) { - throw makeRuntimeRejectMsg(workerScript, "Invalid stock symbol passed into getStockPosition()"); + throw makeRuntimeErrorMsg("getStockPosition", `Invalid stock symbol: ${symbol}`); } return [stock.playerShares, stock.playerAvgPx, stock.playerShortShares, stock.playerAvgShortPx]; }, @@ -1667,7 +1671,7 @@ function NetscriptFunctions(workerScript) { checkTixApiAccess("shortStock"); if (Player.bitNodeN !== 8) { if (SourceFileFlags[8] <= 1) { - throw makeRuntimeRejectMsg(workerScript, "ERROR: Cannot use shortStock(). You must either be in BitNode-8 or you must have Level 2 of Source-File 8"); + throw makeRuntimeErrorMsg(shortStock, "You must either be in BitNode-8 or you must have Source-File 8 Level 2."); } } const stock = getStockFromSymbol(symbol, "shortStock"); @@ -1680,7 +1684,7 @@ function NetscriptFunctions(workerScript) { checkTixApiAccess("sellShort"); if (Player.bitNodeN !== 8) { if (SourceFileFlags[8] <= 1) { - throw makeRuntimeRejectMsg(workerScript, "ERROR: Cannot use sellShort(). You must either be in BitNode-8 or you must have Level 2 of Source-File 8"); + throw makeRuntimeErrorMsg("sellShort", "You must either be in BitNode-8 or you must have Source-File 8 Level 2."); } } const stock = getStockFromSymbol(symbol, "sellShort"); @@ -1693,32 +1697,32 @@ function NetscriptFunctions(workerScript) { checkTixApiAccess("placeOrder"); if (Player.bitNodeN !== 8) { if (SourceFileFlags[8] <= 2) { - throw makeRuntimeRejectMsg(workerScript, "ERROR: Cannot use placeOrder(). You must either be in BitNode-8 or have Level 3 of Source-File 8"); + throw makeRuntimeErrorMsg("placeOrder", "You must either be in BitNode-8 or you must have Source-File 8 Level 3."); } } const stock = getStockFromSymbol(symbol, "placeOrder"); - var orderType, orderPos; - type = type.toLowerCase(); - if (type.includes("limit") && type.includes("buy")) { + let orderType, orderPos; + ltype = type.toLowerCase(); + if (ltype.includes("limit") && ltype.includes("buy")) { orderType = OrderTypes.LimitBuy; - } else if (type.includes("limit") && type.includes("sell")) { + } else if (ltype.includes("limit") && ltype.includes("sell")) { orderType = OrderTypes.LimitSell; - } else if (type.includes("stop") && type.includes("buy")) { + } else if (ltype.includes("stop") && ltype.includes("buy")) { orderType = OrderTypes.StopBuy; - } else if (type.includes("stop") && type.includes("sell")) { + } else if (ltype.includes("stop") && ltype.includes("sell")) { orderType = OrderTypes.StopSell; } else { - throw makeRuntimeRejectMsg(workerScript, "ERROR: Invalid Order Type passed into placeOrder()"); + throw makeRuntimeErrorMsg("placeOrder", `Invalid order type: ${type}`); } - pos = pos.toLowerCase(); - if (pos.includes("l")) { + lpos = pos.toLowerCase(); + if (lpos.includes("l")) { orderPos = PositionTypes.Long; - } else if (pos.includes('s')) { + } else if (lpos.includes('s')) { orderPos = PositionTypes.Short; } else { - throw makeRuntimeRejectMsg(workerScript, "ERROR: Invalid Position Type passed into placeOrder()"); + throw makeRuntimeErrorMsg("placeOrder", `Invalid position type: ${pos}`); } return placeOrder(stock, shares, price, orderType, orderPos, workerScript); @@ -1728,34 +1732,34 @@ function NetscriptFunctions(workerScript) { checkTixApiAccess("cancelOrder"); if (Player.bitNodeN !== 8) { if (SourceFileFlags[8] <= 2) { - throw makeRuntimeRejectMsg(workerScript, "ERROR: Cannot use cancelOrder(). You must either be in BitNode-8 or have Level 3 of Source-File 8"); + throw makeRuntimeErrorMsg("cancelOrder", "You must either be in BitNode-8 or you must have Source-File 8 Level 3."); } } const stock = getStockFrom(symbol, "cancelOrder"); if (isNaN(shares) || isNaN(price)) { - throw makeRuntimeRejectMsg(workerScript, "ERROR: Invalid shares or price argument passed into cancelOrder(). Must be numeric"); + throw makeRuntimeErrorMsg("cancelOrder", `Invalid shares or price. Must be numeric. shares=${shares}, price=${price}`); } var orderType, orderPos; - type = type.toLowerCase(); - if (type.includes("limit") && type.includes("buy")) { + ltype = type.toLowerCase(); + if (ltype.includes("limit") && ltype.includes("buy")) { orderType = OrderTypes.LimitBuy; - } else if (type.includes("limit") && type.includes("sell")) { + } else if (ltype.includes("limit") && ltype.includes("sell")) { orderType = OrderTypes.LimitSell; - } else if (type.includes("stop") && type.includes("buy")) { + } else if (ltype.includes("stop") && ltype.includes("buy")) { orderType = OrderTypes.StopBuy; - } else if (type.includes("stop") && type.includes("sell")) { + } else if (ltype.includes("stop") && ltype.includes("sell")) { orderType = OrderTypes.StopSell; } else { - throw makeRuntimeRejectMsg(workerScript, "ERROR: Invalid Order Type passed into placeOrder()"); + throw makeRuntimeErrorMsg("cancelOrder", `Invalid order type: ${type}`); } - pos = pos.toLowerCase(); - if (pos.includes("l")) { + lpos = pos.toLowerCase(); + if (lpos.includes("l")) { orderPos = PositionTypes.Long; - } else if (pos.includes('s')) { + } else if (lpos.includes('s')) { orderPos = PositionTypes.Short; } else { - throw makeRuntimeRejectMsg(workerScript, "ERROR: Invalid Position Type passed into placeOrder()"); + throw makeRuntimeErrorMsg("cancelOrder", `Invalid position type: ${pos}`); } var params = { stock: stock, @@ -1771,7 +1775,7 @@ function NetscriptFunctions(workerScript) { checkTixApiAccess("getOrders"); if (Player.bitNodeN !== 8) { if (SourceFileFlags[8] <= 2) { - throw makeRuntimeRejectMsg(workerScript, "ERROR: Cannot use getOrders(). You must either be in BitNode-8 or have Level 3 of Source-File 8"); + throw makeRuntimeErrorMsg(workerScript, "You must either be in BitNode-8 or have Source-File 8 Level 3."); } } @@ -1798,7 +1802,7 @@ function NetscriptFunctions(workerScript) { getStockVolatility: function(symbol) { updateDynamicRam("getStockVolatility", getRamCost("getStockVolatility")); if (!Player.has4SDataTixApi) { - throw makeRuntimeRejectMsg(workerScript, "You don't have 4S Market Data TIX API Access! Cannot use getStockVolatility()"); + throw makeRuntimeErrorMsg("getStockVolatility", "You don't have 4S Market Data TIX API Access!"); } const stock = getStockFromSymbol(symbol, "getStockVolatility"); @@ -1807,7 +1811,7 @@ function NetscriptFunctions(workerScript) { getStockForecast: function(symbol) { updateDynamicRam("getStockForecast", getRamCost("getStockForecast")); if (!Player.has4SDataTixApi) { - throw makeRuntimeRejectMsg(workerScript, "You don't have 4S Market Data TIX API Access! Cannot use getStockForecast()"); + throw makeRuntimeErrorMsg("getStockForecast", "You don't have 4S Market Data TIX API Access!"); } const stock = getStockFromSymbol(symbol, "getStockForecast"); @@ -1820,24 +1824,18 @@ function NetscriptFunctions(workerScript) { checkTixApiAccess("purchase4SMarketData"); if (Player.has4SData) { - if (workerScript.shouldLog("purchase4SMarketData")) { - workerScript.log("Already purchased 4S Market Data"); - } + workerScript.log("purchase4SMarketData", "Already purchased 4S Market Data."); return true; } if (Player.money.lt(getStockMarket4SDataCost())) { - if (workerScript.shouldLog("purchase4SMarketData")) { - workerScript.log("Failed to purchase 4S Market Data - Not enough money"); - } + workerScript.log("purchase4SMarketData", "Not enough money to purchase 4S Market Data."); return false; } Player.has4SData = true; Player.loseMoney(getStockMarket4SDataCost()); - if (workerScript.shouldLog("purchase4SMarketData")) { - workerScript.log("Purchased 4S Market Data"); - } + workerScript.log("purchase4SMarketData", "Purchased 4S Market Data"); displayStockMarketContent(); return true; }, @@ -1846,24 +1844,18 @@ function NetscriptFunctions(workerScript) { checkTixApiAccess("purchase4SMarketDataTixApi"); if (Player.has4SDataTixApi) { - if (workerScript.shouldLog("purchase4SMarketDataTixApi")) { - workerScript.log("Already purchased 4S Market Data TIX API"); - } + workerScript.log("purchase4SMarketDataTixApi", "Already purchased 4S Market Data TIX API"); return true; } if (Player.money.lt(getStockMarket4STixApiCost())) { - if (workerScript.shouldLog("purchase4SMarketDataTixApi")) { - workerScript.log("Failed to purchase 4S Market Data TIX API - Not enough money"); - } + workerScript.log("purchase4SMarketDataTixApi", "Not enough money to purchase 4S Market Data TIX API"); return false; } Player.has4SDataTixApi = true; Player.loseMoney(getStockMarket4STixApiCost()); - if (workerScript.shouldLog("purchase4SMarketDataTixApi")) { - workerScript.log("Purchased 4S Market Data TIX API"); - } + workerScript.log("purchase4SMarketDataTixApi", "Purchased 4S Market Data TIX API"); displayStockMarketContent(); return true; }, @@ -1882,7 +1874,7 @@ function NetscriptFunctions(workerScript) { const cost = getPurchaseServerCost(ram); if (cost === Infinity) { - workerScript.scriptRef.log("ERROR: 'getPurchasedServerCost()' failed due to an invalid 'ram' argument"); + workerScript.log("getPurchasedServerCost", `Invalid argument: ram='${ram}'`); return Infinity; } @@ -1893,23 +1885,23 @@ function NetscriptFunctions(workerScript) { var hostnameStr = String(hostname); hostnameStr = hostnameStr.replace(/\s+/g, ''); if (hostnameStr == "") { - workerScript.log("ERROR: Passed empty string for hostname argument of purchaseServer()"); + workerScript.log("purchaseServer", `Invalid argument: hostname='${hostnameStr}'`); return ""; } if (Player.purchasedServers.length >= getPurchaseServerLimit()) { - workerScript.log(`ERROR: You have reached the maximum limit of ${getPurchaseServerLimit()} servers. You cannot purchase any more.`); + workerScript.log("purchaseServer", `You have reached the maximum limit of ${getPurchaseServerLimit()} servers. You cannot purchase any more.`); return ""; } const cost = getPurchaseServerCost(ram); if (cost === Infinity) { - workerScript.log("ERROR: 'purchaseServer()' failed due to an invalid 'ram' argument"); + workerScript.log("purchaseServer", `Invalid argument: ram='${ram}'`); return Infinity; } if (Player.money.lt(cost)) { - workerScript.log("ERROR: Not enough money to purchase server. Need $" + formatNumber(cost, 2)); + workerScript.log("purchaseServer", `Not enough money to purchase server. Need $${formatNumber(cost, 2)}`); return ""; } var newServ = safetlyCreateUniqueServer({ @@ -1928,9 +1920,7 @@ function NetscriptFunctions(workerScript) { homeComputer.serversOnNetwork.push(newServ.ip); newServ.serversOnNetwork.push(homeComputer.ip); Player.loseMoney(cost); - if (workerScript.disableLogs.ALL == null && workerScript.disableLogs.purchaseServer == null) { - workerScript.scriptRef.log("Purchased new server with hostname " + newServ.hostname + " for $" + formatNumber(cost, 2)); - } + workerScript.log("purchaseServer", `Purchased new server with hostname '${newServ.hostname}' for $${formatNumber(cost, 2)}`); return newServ.hostname; }, deleteServer: function(hostname) { @@ -1939,13 +1929,12 @@ function NetscriptFunctions(workerScript) { hostnameStr = hostnameStr.replace(/\s\s+/g, ''); var server = GetServerByHostname(hostnameStr); if (server == null) { - workerScript.scriptRef.log("ERROR: Could not find server with hostname " + hostnameStr + ". deleteServer() failed"); + workerScript.log("deleteServer", `Invalid argument: hostname='${hostnameStr}'`); return false; } if (!server.purchasedByPlayer || server.hostname === "home") { - workerScript.scriptRef.log("ERROR: Server " + server.hostname + " is not a purchased server. " + - "Cannot be deleted. deleteServer() failed"); + workerScript.log("deleteServer", "Cannot delete non-purchased server."); return false; } @@ -1953,19 +1942,19 @@ function NetscriptFunctions(workerScript) { // Can't delete server you're currently connected to if (server.isConnectedTo) { - workerScript.scriptRef.log("ERROR: deleteServer() failed because you are currently connected to the server you are trying to delete"); + workerScript.log("deleteServer", "You are currently connected to the server you are trying to delete."); return false; } // A server cannot delete itself if (ip === workerScript.serverIp) { - workerScript.scriptRef.log("ERROR: Cannot call deleteServer() on self. deleteServer() failed"); + workerScript.log("deleteServer", "Cannot delete the server this script is running on."); return false; } // Delete all scripts running on server if (server.runningScripts.length > 0) { - workerScript.scriptRef.log("ERROR: Cannot delete server " + server.hostname + " because it still has scripts running."); + workerScript.log("deleteServer", `Cannot delete server ('${server.hostname}') because it still has scripts running.`); return false; } @@ -1980,8 +1969,7 @@ function NetscriptFunctions(workerScript) { } if (!found) { - workerScript.scriptRef.log("ERROR: Could not identify server " + server.hostname + - "as a purchased server. This is likely a bug please contact game dev"); + workerScript.log("deleteServer", `Could not identify server ${server.hostname} as a purchased server. This is a bug. Report to dev.`); return false; } @@ -1994,15 +1982,12 @@ function NetscriptFunctions(workerScript) { for (var i = 0; i < homeComputer.serversOnNetwork.length; ++i) { if (ip == homeComputer.serversOnNetwork[i]) { homeComputer.serversOnNetwork.splice(i, 1); - if (workerScript.disableLogs.ALL == null && workerScript.disableLogs.deleteServer == null) { - workerScript.scriptRef.log("Deleted server " + hostnameStr); - } + workerScript.log("deleteServer", `Deleted server '${hostnameStr}`); return true; } } // Wasn't found on home computer - workerScript.scriptRef.log("ERROR: Could not find server " + server.hostname + - "as a purchased server. This is likely a bug please contact game dev"); + workerScript.log("deleteServer", `Could not find server ${server.hostname} as a purchased server. This is a bug. Report to dev.`); return false; }, getPurchasedServers: function(hostname=true) { @@ -2012,7 +1997,7 @@ function NetscriptFunctions(workerScript) { if (hostname) { var server = getServer(ip); if (server == null) { - throw makeRuntimeRejectMsg(workerScript, "ERROR: Could not find server in getPurchasedServers(). This is a bug please report to game dev"); + throw makeRuntimeErrorMsg("getPurchasedServers", "Could not find server. This is a bug. Report to dev."); } res.push(server.hostname); } else { @@ -2027,29 +2012,29 @@ function NetscriptFunctions(workerScript) { // Port 1-10 port = Math.round(port); if (port < 1 || port > CONSTANTS.NumNetscriptPorts) { - throw makeRuntimeRejectMsg(workerScript, "ERROR: Trying to write to invalid port: " + port + ". Only ports 1-" + CONSTANTS.NumNetscriptPorts + " are valid."); + throw makeRuntimeErrorMsg("write", `Trying to write to invalid port: ${port}. Only ports 1-${CONSTANTS.NumNetscriptPorts} are valid.`); } var port = NetscriptPorts[port-1]; if (port == null || !(port instanceof NetscriptPort)) { - throw makeRuntimeRejectMsg(workerScript, "Could not find port: " + port + ". This is a bug contact the game developer"); + throw makeRuntimeErrorMsg("write", `Could not find port: ${port}. This is a bug. Report to dev.`); } return port.write(data); } else if (isString(port)) { // Write to script or text file const fn = port; if (!isValidFilePath(fn)) { - throw makeRuntimeRejectMsg(workerScript, `write() failed due to invalid filepath: ${fn}`); + throw makeRuntimeErrorMsg("write", `Invalid filepath: ${fn}`); } // Coerce 'data' to be a string try { data = String(data); } catch (e) { - throw makeRuntimeRejectMsg(workerScript, `write() failed because of invalid data (${e}). Data being written must be convertible to a string`); + throw makeRuntimeErrorMsg("write", `Invalid data (${e}). Data being written must be convertible to a string`); } const server = workerScript.getServer(); if (server == null) { - throw makeRuntimeRejectMsg(workerScript, "Error getting Server for this script in write(). This is a bug please contact game dev"); + throw makeRuntimeErrorMsg("write", "Error getting Server. This is a bug. Report to dev."); } if (isScriptFilename(fn)) { // Write to script @@ -2078,7 +2063,7 @@ function NetscriptFunctions(workerScript) { } return true; } else { - throw makeRuntimeRejectMsg(workerScript, "Invalid argument passed in for write: " + port); + throw makeRuntimeErrorMsg("write", `Invalid argument: ${port}`); } }, tryWrite: function(port, data="") { @@ -2086,15 +2071,15 @@ function NetscriptFunctions(workerScript) { if (!isNaN(port)) { port = Math.round(port); if (port < 1 || port > CONSTANTS.NumNetscriptPorts) { - throw makeRuntimeRejectMsg(workerScript, "ERROR: tryWrite() called on invalid port: " + port + ". Only ports 1-" + CONSTANTS.NumNetscriptPorts + " are valid."); + throw makeRuntimeErrorMsg("tryWrite", `Invalid port: ${port}. Only ports 1-${CONSTANTS.NumNetscriptPorts} are valid.`); } var port = NetscriptPorts[port-1]; if (port == null || !(port instanceof NetscriptPort)) { - throw makeRuntimeRejectMsg(workerScript, "Could not find port: " + port + ". This is a bug contact the game developer"); + throw makeRuntimeErrorMsg("tryWrite", `Could not find port: ${port}. This is a bug. Report to dev.`); } return port.tryWrite(data); } else { - throw makeRuntimeRejectMsg(workerScript, "Invalid argument passed in for tryWrite: " + port); + throw makeRuntimeErrorMsg("tryWrite", `Invalid argument: ${port}`); } }, read: function(port) { @@ -2103,18 +2088,18 @@ function NetscriptFunctions(workerScript) { // Port 1-10 port = Math.round(port); if (port < 1 || port > CONSTANTS.NumNetscriptPorts) { - throw makeRuntimeRejectMsg(workerScript, "ERROR: Trying to read from invalid port: " + port + ". Only ports 1-" + CONSTANTS.NumNetscriptPorts + " are valid."); + throw makeRuntimeErrorMsg("read", `Invalid port: ${port}. Only ports 1-${CONSTANTS.NumNetscriptPorts} are valid.`); } var port = NetscriptPorts[port-1]; if (port == null || !(port instanceof NetscriptPort)) { - throw makeRuntimeRejectMsg(workerScript, "ERROR: Could not find port: " + port + ". This is a bug contact the game developer"); + throw makeRuntimeErrorMsg("read", `Could not find port: ${port}. This is a bug. Report to dev.`); } return port.read(); } else if (isString(port)) { // Read from script or text file let fn = port; let server = getServer(workerScript.serverIp); if (server == null) { - throw makeRuntimeRejectMsg(workerScript, "Error getting Server for this script in read(). This is a bug please contact game dev"); + throw makeRuntimeErrorMsg("read", "Error getting Server. This is a bug. Report to dev."); } if (isScriptFilename(fn)) { // Read from script @@ -2133,21 +2118,21 @@ function NetscriptFunctions(workerScript) { } } } else { - throw makeRuntimeRejectMsg(workerScript, "Invalid argument passed in for read(): " + port); + throw makeRuntimeErrorMsg("read", `Invalid argument: ${port}`); } }, peek: function(port) { updateDynamicRam("peek", getRamCost("peek")); if (isNaN(port)) { - throw makeRuntimeRejectMsg(workerScript, "ERROR: peek() called with invalid argument. Must be a port number between 1 and " + CONSTANTS.NumNetscriptPorts); + throw makeRuntimeErrorMsg("peek", `Invalid argument. Must be a port number between 1 and ${CONSTANTS.NumNetscriptPorts}, is ${port}`); } port = Math.round(port); if (port < 1 || port > CONSTANTS.NumNetscriptPorts) { - throw makeRuntimeRejectMsg(workerScript, "ERROR: peek() called with invalid argument. Must be a port number between 1 and " + CONSTANTS.NumNetscriptPorts); + throw makeRuntimeErrorMsg("peek", `Invalid argument. Must be a port number between 1 and ${CONSTANTS.NumNetscriptPorts}, is ${port}`); } var port = NetscriptPorts[port-1]; if (port == null || !(port instanceof NetscriptPort)) { - throw makeRuntimeRejectMsg(workerScript, "ERROR: Could not find port: " + port + ". This is a bug contact the game developer"); + throw makeRuntimeErrorMsg("peek", `Could not find port: ${port}. This is a bug. Report to dev.`); } return port.peek(); }, @@ -2156,40 +2141,40 @@ function NetscriptFunctions(workerScript) { if (!isNaN(port)) { // Clear port port = Math.round(port); if (port < 1 || port > CONSTANTS.NumNetscriptPorts) { - throw makeRuntimeRejectMsg(workerScript, "ERROR: Trying to clear invalid port: " + port + ". Only ports 1-" + CONSTANTS.NumNetscriptPorts + " are valid"); + throw makeRuntimeErrorMsg("clear", `Trying to clear invalid port: ${port}. Only ports 1-${CONSTANTS.NumNetscriptPorts} are valid`); } var port = NetscriptPorts[port-1]; if (port == null || !(port instanceof NetscriptPort)) { - throw makeRuntimeRejectMsg(workerScript, "ERROR: Could not find port: " + port + ". This is a bug contact the game developer"); + throw makeRuntimeErrorMsg("clear", `Could not find port: ${port}. This is a bug. Report to dev.`); } return port.clear(); } else if (isString(port)) { // Clear text file var fn = port; var server = getServer(workerScript.serverIp); if (server == null) { - throw makeRuntimeRejectMsg(workerScript, "Error getting Server for this script in clear(). This is a bug please contact game dev"); + throw makeRuntimeErrorMsg("clear", "Error getting Server. This is a bug. Report to dev."); } var txtFile = getTextFile(fn, server); if (txtFile != null) { txtFile.write(""); } } else { - throw makeRuntimeRejectMsg(workerScript, "Invalid argument passed in for clear(): " + port); + throw makeRuntimeErrorMsg("clear", `Invalid argument: ${port}`); } return 0; }, getPortHandle: function(port) { updateDynamicRam("getPortHandle", getRamCost("getPortHandle")); if (isNaN(port)) { - throw makeRuntimeRejectMsg(workerScript, "ERROR: Invalid argument passed into getPortHandle(). Must be an integer between 1 and " + CONSTANTS.NumNetscriptPorts); + throw makeRuntimeErrorMsg("getPortHandle", `Invalid port: ${port} Must be an integer between 1 and ${CONSTANTS.NumNetscriptPorts}.`); } port = Math.round(port); if (port < 1 || port > CONSTANTS.NumNetscriptPorts) { - throw makeRuntimeRejectMsg(workerScript, "ERROR: getPortHandle() called with invalid port number: " + port + ". Only ports 1-" + CONSTANTS.NumNetscriptPorts + " are valid"); + throw makeRuntimeErrorMsg("getPortHandle", `Invalid port: ${port}. Only ports 1-${CONSTANTS.NumNetscriptPorts} are valid.`); } var port = NetscriptPorts[port-1]; if (port == null || !(port instanceof NetscriptPort)) { - throw makeRuntimeRejectMsg(workerScript, "ERROR: Could not find port: " + port + ". This is a bug contact the game developer"); + throw makeRuntimeErrorMsg("getPortHandle", `Could not find port: ${port}. This is a bug. Report to dev.`); } return port; }, @@ -2203,7 +2188,7 @@ function NetscriptFunctions(workerScript) { const status = s.removeFile(fn); if (!status.res) { - workerScript.log(status.msg); + workerScript.log("rm", status.msg); } return status.res; @@ -2212,8 +2197,7 @@ function NetscriptFunctions(workerScript) { updateDynamicRam("scriptRunning", getRamCost("scriptRunning")); var server = getServer(ip); if (server == null) { - workerScript.scriptRef.log("scriptRunning() failed. Invalid IP or hostname passed in: " + ip); - throw makeRuntimeRejectMsg(workerScript, "scriptRunning() failed. Invalid IP or hostname passed in: " + ip); + throw makeRuntimeErrorMsg("scriptRunning", `Invalid IP/hostname: ${ip}`); } for (var i = 0; i < server.runningScripts.length; ++i) { if (server.runningScripts[i].filename == scriptname) { @@ -2226,8 +2210,7 @@ function NetscriptFunctions(workerScript) { updateDynamicRam("scriptKill", getRamCost("scriptKill")); var server = getServer(ip); if (server == null) { - workerScript.scriptRef.log("scriptKill() failed. Invalid IP or hostname passed in: " + ip); - throw makeRuntimeRejectMsg(workerScript, "scriptKill() failed. Invalid IP or hostname passed in: " + ip); + throw makeRuntimeErrorMsg("scriptKill", `Invalid IP/hostname: ${ip}`); } var suc = false; for (var i = 0; i < server.runningScripts.length; ++i) { @@ -2245,8 +2228,7 @@ function NetscriptFunctions(workerScript) { updateDynamicRam("getScriptRam", getRamCost("getScriptRam")); var server = getServer(ip); if (server == null) { - workerScript.scriptRef.log("getScriptRam() failed. Invalid IP or hostname passed in: " + ip); - throw makeRuntimeRejectMsg(workerScript, "getScriptRam() failed. Invalid IP or hostname passed in: " + ip); + throw makeRuntimeErrorMsg("getScriptRam", `Invalid IP/hostname: ${ip}`); } for (var i = 0; i < server.scripts.length; ++i) { if (server.scripts[i].filename == scriptname) { @@ -2295,8 +2277,7 @@ function NetscriptFunctions(workerScript) { // Get income for a particular script var server = getServer(ip); if (server == null) { - workerScript.scriptRef.log("getScriptIncome() failed. Invalid IP or hostnamed passed in: " + ip); - throw makeRuntimeRejectMsg(workerScript, "getScriptIncome() failed. Invalid IP or hostnamed passed in: " + ip); + throw makeRuntimeErrorMsg("getScriptIncome", `Invalid IP/hostnamed: ${ip}`); } var argsForScript = []; for (var i = 2; i < arguments.length; ++i) { @@ -2304,7 +2285,7 @@ function NetscriptFunctions(workerScript) { } var runningScriptObj = findRunningScript(scriptname, argsForScript, server); if (runningScriptObj == null) { - workerScript.scriptRef.log("getScriptIncome() failed. No such script "+ scriptname + " on " + server.hostname + " with args: " + arrayToString(argsForScript)); + workerScript.log("getScriptIncome", `No such script '${scriptname}' on '${server.hostname}' with args: ${arrayToString(argsForScript)}`); return -1; } return runningScriptObj.onlineMoneyMade / runningScriptObj.onlineRunningTime; @@ -2322,8 +2303,7 @@ function NetscriptFunctions(workerScript) { // Get income for a particular script var server = getServer(ip); if (server == null) { - workerScript.scriptRef.log("getScriptExpGain() failed. Invalid IP or hostnamed passed in: " + ip); - throw makeRuntimeRejectMsg(workerScript, "getScriptExpGain() failed. Invalid IP or hostnamed passed in: " + ip); + throw makeRuntimeErrorMsg("getScriptExpGain", `Invalid IP/hostnamed: ${ip}`); } var argsForScript = []; for (var i = 2; i < arguments.length; ++i) { @@ -2331,7 +2311,7 @@ function NetscriptFunctions(workerScript) { } var runningScriptObj = findRunningScript(scriptname, argsForScript, server); if (runningScriptObj == null) { - workerScript.scriptRef.log("getScriptExpGain() failed. No such script "+ scriptname + " on " + server.hostname + " with args: " + arrayToString(argsForScript)); + workerScript.log("getScriptExpGain", `No such script '${scriptname}' on '${server.hostname}' with args: ${arrayToString(argsForScript)}`); return -1; } return runningScriptObj.onlineExpGained / runningScriptObj.onlineRunningTime; @@ -2380,7 +2360,7 @@ function NetscriptFunctions(workerScript) { }, wget: async function(url, target, ip=workerScript.serverIp) { if (!isScriptFilename(target) && !target.endsWith(".txt")) { - workerScript.log(`ERROR: wget() failed because of an invalid target file: ${target}. Target file must be a script or text file`); + workerScript.log("wget", `Invalid target file: '${target}'. Must be a script or text file.`); return Promise.resolve(false); } var s = safeGetServer(ip, "wget"); @@ -2393,17 +2373,17 @@ function NetscriptFunctions(workerScript) { res = s.writeToTextFile(target, data); } if (!res.success) { - workerScript.log("ERROR: wget() failed"); + workerScript.log("wget", "Failed."); return resolve(false); } if (res.overwritten) { - workerScript.log(`wget() successfully retrieved content and overwrote ${target} on ${ip}`); + workerScript.log("wget", `Successfully retrieved content and overwrote '${target}' on '${ip}'`); return resolve(true); } - workerScript.log(`wget successfully retrieved content to new file ${target} on ${ip}`); + workerScript.log("wget", `Successfully retrieved content to new file '${target}' on '${ip}'`); return resolve(true); }, 'text').fail(function(e) { - workerScript.log(`ERROR: wget() failed: ${JSON.stringify(e)}`); + workerScript.log("wget", JSON.stringify(e)); return resolve(false) }); }); @@ -2416,28 +2396,21 @@ function NetscriptFunctions(workerScript) { /* Singularity Functions */ universityCourse: function(universityName, className) { updateDynamicRam("universityCourse", getRamCost("universityCourse")); - if (Player.bitNodeN !== 4) { - if (SourceFileFlags[4] <= 0) { - throw makeRuntimeRejectMsg(workerScript, "Cannot run universityCourse(). It is a Singularity Function and requires SourceFile-4 (level 1) to run."); - return false; - } - } + checkSingularityAccess("universityCourse", 1); if (inMission) { - workerScript.scriptRef.log("ERROR: universityCourse() failed because you are in the middle of a mission."); + workerScript.log("universityCourse", "You are in the middle of a mission."); return; } if (Player.isWorking) { var txt = Player.singularityStopWork(); - if (workerScript.disableLogs.ALL == null && workerScript.disableLogs.universityCourse == null) { - workerScript.scriptRef.log(txt); - } + workerScript.log("universityCourse", txt); } var costMult, expMult; switch(universityName.toLowerCase()) { case LocationName.AevumSummitUniversity.toLowerCase(): if (Player.city != CityName.Aevum) { - workerScript.scriptRef.log("ERROR: You cannot study at Summit University because you are not in Aevum. universityCourse() failed"); + workerScript.log("universityCourse", "You cannot study at 'Summit University' because you are not in 'Aevum'."); return false; } Player.gotoLocation(LocationName.AevumSummitUniversity); @@ -2446,7 +2419,7 @@ function NetscriptFunctions(workerScript) { break; case LocationName.Sector12RothmanUniversity.toLowerCase(): if (Player.city != CityName.Sector12) { - workerScript.scriptRef.log("ERROR: You cannot study at Rothman University because you are not in Sector-12. universityCourse() failed"); + workerScript.log("universityCourse", "You cannot study at 'Rothman University' because you are not in 'Sector-12'."); return false; } Player.location = LocationName.Sector12RothmanUniversity; @@ -2455,7 +2428,7 @@ function NetscriptFunctions(workerScript) { break; case LocationName.VolhavenZBInstituteOfTechnology.toLowerCase(): if (Player.city != CityName.Volhaven) { - workerScript.scriptRef.log("ERROR: You cannot study at ZB Institute of Technology because you are not in Volhaven. universityCourse() failed"); + workerScript.log("universityCourse", "You cannot study at 'ZB Institute of Technology' because you are not in 'Volhaven'."); return false; } Player.location = LocationName.VolhavenZBInstituteOfTechnology; @@ -2463,7 +2436,7 @@ function NetscriptFunctions(workerScript) { expMult = 4; break; default: - workerScript.scriptRef.log("Invalid university name: " + universityName + ". universityCourse() failed"); + workerScript.log("universityCourse", `Invalid university name: '${universityName}'.`); return false; } @@ -2488,39 +2461,30 @@ function NetscriptFunctions(workerScript) { task = CONSTANTS.ClassLeadership; break; default: - workerScript.scriptRef.log("Invalid class name: " + className + ". universityCourse() failed"); + workerScript.log("universityCourse", `Invalid class name: ${className}.`); return false; } Player.startClass(costMult, expMult, task); - if (workerScript.disableLogs.ALL == null && workerScript.disableLogs.universityCourse == null) { - workerScript.scriptRef.log("Started " + task + " at " + universityName); - } + workerScript.log("universityCourse", `Started ${task} at ${universityName}`); return true; }, gymWorkout: function(gymName, stat) { updateDynamicRam("gymWorkout", getRamCost("gymWorkout")); - if (Player.bitNodeN !== 4) { - if (SourceFileFlags[4] <= 0) { - throw makeRuntimeRejectMsg(workerScript, "Cannot run gymWorkout(). It is a Singularity Function and requires SourceFile-4 (level 1) to run."); - return false; - } - } + checkSingularityAccess("gymWorkout", 1); if (inMission) { - workerScript.scriptRef.log("ERROR: gymWorkout() failed because you are in the middle of a mission."); + workerScript.log("gymWorkout", "You are in the middle of a mission."); return; } if (Player.isWorking) { var txt = Player.singularityStopWork(); - if (workerScript.disableLogs.ALL == null && workerScript.disableLogs.gymWorkout == null) { - workerScript.scriptRef.log(txt); - } + workerScript.log("gymWorkout", txt); } var costMult, expMult; switch(gymName.toLowerCase()) { case LocationName.AevumCrushFitnessGym.toLowerCase(): if (Player.city != CityName.Aevum) { - workerScript.scriptRef.log("ERROR: You cannot workout at Crush Fitness because you are not in Aevum. gymWorkout() failed"); + workerScript.log("gymWorkout", "You cannot workout at 'Crush Fitness' because you are not in 'Aevum'."); return false; } Player.location = LocationName.AevumCrushFitnessGym; @@ -2529,7 +2493,7 @@ function NetscriptFunctions(workerScript) { break; case LocationName.AevumSnapFitnessGym.toLowerCase(): if (Player.city != CityName.Aevum) { - workerScript.scriptRef.log("ERROR: You cannot workout at Snap Fitness because you are not in Aevum. gymWorkout() failed"); + workerScript.log("gymWorkout", "You cannot workout at 'Snap Fitness' because you are not in 'Aevum'."); return false; } Player.location = LocationName.AevumSnapFitnessGym; @@ -2538,7 +2502,7 @@ function NetscriptFunctions(workerScript) { break; case LocationName.Sector12IronGym.toLowerCase(): if (Player.city != CityName.Sector12) { - workerScript.scriptRef.log("ERROR: You cannot workout at Iron Gym because you are not in Sector-12. gymWorkout() failed"); + workerScript.log("gymWorkout", "You cannot workout at 'Iron Gym' because you are not in 'Sector-12'."); return false; } Player.location = LocationName.Sector12IronGym; @@ -2547,7 +2511,7 @@ function NetscriptFunctions(workerScript) { break; case LocationName.Sector12PowerhouseGym.toLowerCase(): if (Player.city != CityName.Sector12) { - workerScript.scriptRef.log("ERROR: You cannot workout at Powerhouse Gym because you are not in Sector-12. gymWorkout() failed"); + workerScript.log("gymWorkout", "You cannot workout at 'Powerhouse Gym' because you are not in 'Sector-12'."); return false; } Player.location = LocationName.Sector12PowerhouseGym; @@ -2556,7 +2520,7 @@ function NetscriptFunctions(workerScript) { break; case LocationName.VolhavenMilleniumFitnessGym.toLowerCase(): if (Player.city != CityName.Volhaven) { - workerScript.scriptRef.log("ERROR: You cannot workout at Millenium Fitness Gym because you are not in Volhaven. gymWorkout() failed"); + workerScript.log("gymWorkout", "You cannot workout at 'Millenium Fitness Gym' because you are not in 'Volhaven'."); return false; } Player.location = LocationName.VolhavenMilleniumFitnessGym; @@ -2564,7 +2528,7 @@ function NetscriptFunctions(workerScript) { expMult = 4; break; default: - workerScript.scriptRef.log("Invalid gym name: " + gymName + ". gymWorkout() failed"); + workerScript.log("gymWorkout", `Invalid gym name: ${gymName}. gymWorkout() failed`); return false; } @@ -2586,23 +2550,16 @@ function NetscriptFunctions(workerScript) { Player.startClass(costMult, expMult, CONSTANTS.ClassGymAgility); break; default: - workerScript.scriptRef.log("Invalid stat: " + stat + ". gymWorkout() failed"); + workerScript.log("gymWorkout", `Invalid stat: ${stat}.`); return false; } - if (workerScript.disableLogs.ALL == null && workerScript.disableLogs.gymWorkout == null) { - workerScript.scriptRef.log("Started training " + stat + " at " + gymName); - } + workerScript.log("gymWorkout", `Started training ${stat} at ${gymName}`); return true; }, travelToCity: function(cityname) { updateDynamicRam("travelToCity", getRamCost("travelToCity")); - if (Player.bitNodeN !== 4) { - if (SourceFileFlags[4] <= 0) { - throw makeRuntimeRejectMsg(workerScript, "Cannot run travelToCity(). It is a Singularity Function and requires SourceFile-4 (level 1) to run."); - return false; - } - } + checkSingularityAccess("travelToCity", 1); switch(cityname) { case CityName.Aevum: @@ -2612,37 +2569,29 @@ function NetscriptFunctions(workerScript) { case CityName.Ishima: case CityName.Volhaven: if(Player.money.lt(CONSTANTS.TravelCost)) { - workerScript.scriptRef.log("ERROR: not enough money to travel with travelToCity()."); - throw makeRuntimeRejectMsg(workerScript, "ERROR: not enough money to travel with travelToCity()."); + throw makeRuntimeErrorMsg("travelToCity", "Not enough money to travel."); } Player.loseMoney(CONSTANTS.TravelCost); Player.city = cityname; - if (workerScript.disableLogs.ALL == null && workerScript.disableLogs.travelToCity == null) { - workerScript.scriptRef.log("Traveled to " + cityname); - } + workerScript.log("travelToCity", `Traveled to ${cityname}`); return true; default: - workerScript.scriptRef.log("ERROR: Invalid city name passed into travelToCity()."); + workerScript.log("travelToCity", `Invalid city name: '${cityname}'.`); return false; } }, purchaseTor: function() { updateDynamicRam("purchaseTor", getRamCost("purchaseTor")); - if (Player.bitNodeN !== 4) { - if (SourceFileFlags[4] <= 0) { - throw makeRuntimeRejectMsg(workerScript, "Cannot run purchaseTor(). It is a Singularity Function and requires SourceFile-4 (level 1) to run."); - return false; - } - } + checkSingularityAccess("purchaseTor", 1); if (SpecialServerIps["Darkweb Server"] != null) { - workerScript.scriptRef.log("You already have a TOR router! purchaseTor() failed"); + workerScript.log("purchaseTor", "You already have a TOR router!"); return false; } if (Player.money.lt(CONSTANTS.TorRouterCost)) { - workerScript.scriptRef.log("ERROR: You cannot afford to purchase a Tor router. purchaseTor() failed"); + workerScript.log("purchaseTor", "You cannot afford to purchase a Tor router."); return false; } Player.loseMoney(CONSTANTS.TorRouterCost); @@ -2657,22 +2606,15 @@ function NetscriptFunctions(workerScript) { Player.getHomeComputer().serversOnNetwork.push(darkweb.ip); darkweb.serversOnNetwork.push(Player.getHomeComputer().ip); Player.gainIntelligenceExp(CONSTANTS.IntelligenceSingFnBaseExpGain); - if (workerScript.disableLogs.ALL == null && workerScript.disableLogs.purchaseTor == null) { - workerScript.scriptRef.log("You have purchased a Tor router!"); - } + workerScript.log("purchaseTor", "You have purchased a Tor router!"); return true; }, purchaseProgram: function(programName) { updateDynamicRam("purchaseProgram", getRamCost("purchaseProgram")); - if (Player.bitNodeN !== 4) { - if (SourceFileFlags[4] <= 0) { - throw makeRuntimeRejectMsg(workerScript, "Cannot run purchaseProgram(). It is a Singularity Function and requires SourceFile-4 (level 1) to run."); - return false; - } - } + checkSingularityAccess("purchaseProgram", 1); if (SpecialServerIps["Darkweb Server"] == null) { - workerScript.scriptRef.log("ERROR: You do not have the TOR router. purchaseProgram() failed."); + workerScript.log("purchaseProgram", "You do not have the TOR router."); return false; } @@ -2687,36 +2629,29 @@ function NetscriptFunctions(workerScript) { } if(item == null) { - workerScript.scriptRef.log("ERROR: Invalid program name passed into purchaseProgram()."); + workerScript.log("purchaseProgram", `Invalid program name: '${programName}.`); return false; } if(Player.money.lt(item.price)) { - workerScript.scriptRef.log("Not enough money to purchase " + item.program); + workerScript.log("purchaseProgram", `Not enough money to purchase '${item.program}'. Need ${numeralWrapper.format(item.price, '$0.000a')}`); return false; } if(Player.hasProgram(item.program)) { - workerScript.scriptRef.log('You already have the '+item.program+' program'); + workerScript.log("purchaseProgram", `You already have the '${item.program}' program`); return true; } Player.loseMoney(item.price); Player.getHomeComputer().programs.push(item.program); - if (workerScript.disableLogs.ALL == null && workerScript.disableLogs.purchaseProgram == null) { - workerScript.scriptRef.log("You have purchased the "+item.program+" program. The new program can be found on your home computer."); - } + workerScript.log("purchaseProgram", `You have purchased the '${item.program}' program. The new program can be found on your home computer.`); return true; }, getStats: function() { updateDynamicRam("getStats", getRamCost("getStats")); - if (Player.bitNodeN !== 4) { - if (SourceFileFlags[4] <= 0) { - throw makeRuntimeRejectMsg(workerScript, "Cannot run getStats(). It is a Singularity Function and requires SourceFile-4 (level 1) to run."); - return {}; - } - } + checkSingularityAccess("getStats", 1); return { hacking: Player.hacking_skill, @@ -2730,12 +2665,7 @@ function NetscriptFunctions(workerScript) { }, getCharacterInformation: function() { updateDynamicRam("getCharacterInformation", getRamCost("getCharacterInformation")); - if (Player.bitNodeN !== 4) { - if (SourceFileFlags[4] <= 0) { - throw makeRuntimeRejectMsg(workerScript, "Cannot run getCharacterInformation(). It is a Singularity Function and requires SourceFile-4 (level 1) to run."); - return {}; - } - } + checkSingularityAccess("getCharacterInformation", 1); return { bitnode: Player.bitNodeN, @@ -2782,50 +2712,33 @@ function NetscriptFunctions(workerScript) { }, isBusy: function() { updateDynamicRam("isBusy", getRamCost("isBusy")); - if (Player.bitNodeN !== 4) { - if (SourceFileFlags[4] <= 0) { - throw makeRuntimeRejectMsg(workerScript, "Cannot run isBusy(). It is a Singularity Function and requires SourceFile-4 (level 1) to run."); - return; - } - } + checkSingularityAccess("isBusy", 1); return Player.isWorking || inMission; }, stopAction: function() { updateDynamicRam("stopAction", getRamCost("stopAction")); - if (Player.bitNodeN !== 4) { - if (SourceFileFlags[4] <= 0) { - throw makeRuntimeRejectMsg(workerScript, "Cannot run stopAction(). It is a Singularity Function and requires SourceFile-4 (level 1) to run."); - return false; - } - } + checkSingularityAccess("stopAction", 1); if (Player.isWorking) { var txt = Player.singularityStopWork(); - if (workerScript.disableLogs.ALL == null && workerScript.disableLogs.stopAction == null) { - workerScript.scriptRef.log(txt); - } + workerScript.log("stopAction", txt); return true; } return false; }, upgradeHomeRam: function() { updateDynamicRam("upgradeHomeRam", getRamCost("upgradeHomeRam")); - if (Player.bitNodeN !== 4) { - if (SourceFileFlags[4] <= 1) { - throw makeRuntimeRejectMsg(workerScript, "Cannot run upgradeHomeRam(). It is a Singularity Function and requires SourceFile-4 (level 2) to run."); - return false; - } - } + checkSingularityAccess("upgradeHomeRam", 2); // Check if we're at max RAM const homeComputer = Player.getHomeComputer(); if (homeComputer.maxRam >= CONSTANTS.HomeComputerMaxRam) { - workerScript.log(`ERROR: upgradeHomeRam() failed because your home computer is at max RAM`); + workerScript.log("upgradeHomeRam", `Your home computer is at max RAM.`); return false; } const cost = Player.getUpgradeHomeRamCost(); if (Player.money.lt(cost)) { - workerScript.scriptRef.log("ERROR: upgradeHomeRam() failed because you don't have enough money"); + workerScript.log("upgradeHomeRam", `You don't have enough money. Need ${numeralWrapper.format(cost, '$0.000a')}`); return false; } @@ -2833,30 +2746,18 @@ function NetscriptFunctions(workerScript) { Player.loseMoney(cost); Player.gainIntelligenceExp(CONSTANTS.IntelligenceSingFnBaseExpGain); - if (workerScript.disableLogs.ALL == null && workerScript.disableLogs.upgradeHomeRam == null) { - workerScript.scriptRef.log("Purchased additional RAM for home computer! It now has " + homeComputer.maxRam + "GB of RAM."); - } + workerScript.log("upgradeHomeRam", `Purchased additional RAM for home computer! It now has ${homeComputer.maxRam}GB of RAM.`); return true; }, getUpgradeHomeRamCost: function() { updateDynamicRam("getUpgradeHomeRamCost", getRamCost("getUpgradeHomeRamCost")); - if (Player.bitNodeN !== 4) { - if (SourceFileFlags[4] <= 1) { - throw makeRuntimeRejectMsg(workerScript, "Cannot run getUpgradeHomeRamCost(). It is a Singularity Function and requires SourceFile-4 (level 2) to run."); - return false; - } - } + checkSingularityAccess("getUpgradeHomeRamCost", 2); return Player.getUpgradeHomeRamCost(); }, workForCompany: function(companyName) { updateDynamicRam("workForCompany", getRamCost("workForCompany")); - if (Player.bitNodeN !== 4) { - if (SourceFileFlags[4] <= 1) { - throw makeRuntimeRejectMsg(workerScript, "Cannot run workForCompany(). It is a Singularity Function and requires SourceFile-4 (level 2) to run."); - return false; - } - } + checkSingularityAccess("workForCompany", 2); // Sanitize input if (companyName == null) { @@ -2865,19 +2766,19 @@ function NetscriptFunctions(workerScript) { // Make sure its a valid company if (companyName == null || companyName === "" || !(Companies[companyName] instanceof Company)) { - workerScript.scriptRef.log(`ERROR: workForCompany() failed because of an invalid company specified: ${companyName}`); + workerScript.log("workForCompany", `Invalid company: '${companyName}'`); return false; } // Make sure player is actually employed at the comapny if (!Object.keys(Player.jobs).includes(companyName)) { - workerScript.scriptRef.log(`ERROR: workForCompany() failed because you do not have a job at ${companyName}`); + workerScript.log("workForCompany", `You do not have a job at '${companyName}'`); return false; } // Cant work while in a mission if (inMission) { - workerScript.scriptRef.log("ERROR: workForCompany() failed because you are in the middle of a mission."); + workerScript.log("workForCompany", "You are in the middle of a mission."); return false; } @@ -2885,15 +2786,13 @@ function NetscriptFunctions(workerScript) { const companyPositionName = Player.jobs[companyName]; const companyPosition = CompanyPositions[companyPositionName]; if (companyPositionName === "" || !(companyPosition instanceof CompanyPosition)) { - workerScript.scriptRef.log("ERROR: workForCompany() failed because you do not have a job"); + workerScript.log("workForCompany", "You do not have a job"); return false; } if (Player.isWorking) { var txt = Player.singularityStopWork(); - if (workerScript.disableLogs.ALL == null && workerScript.disableLogs.workForCompany == null) { - workerScript.scriptRef.log(txt); - } + workerScript.log("workForCompany", txt); } if (companyPosition.isPartTimeJob()) { @@ -2901,24 +2800,13 @@ function NetscriptFunctions(workerScript) { } else { Player.startWork(companyName); } - if (workerScript.disableLogs.ALL == null && workerScript.disableLogs.workForCompany == null) { - workerScript.log(`Began working at ${Player.companyName} as a ${companyPositionName}`); - } + workerScript.log("workForCompany", `Began working at '${Player.companyName}' as a '${companyPositionName}'`); return true; }, applyToCompany: function(companyName, field) { updateDynamicRam("applyToCompany", getRamCost("applyToCompany")); - if (Player.bitNodeN !== 4) { - if (SourceFileFlags[4] <= 1) { - throw makeRuntimeRejectMsg(workerScript, "Cannot run applyToCompany(). It is a Singularity Function and requires SourceFile-4 (level 2) to run."); - return false; - } - } - - if (!companyExists(companyName)) { - workerScript.scriptRef.log("ERROR: applyToCompany() failed because specified company " + companyName + " does not exist."); - return false; - } + checkSingularityAccess("applyToCompany", 2); + getCompany("applyToCompany", companyName); Player.location = companyName; var res; @@ -2963,153 +2851,92 @@ function NetscriptFunctions(workerScript) { res = Player.applyForPartTimeWaiterJob(true); break; default: - workerScript.scriptRef.log("ERROR: Invalid job passed into applyToCompany: " + field + ". applyToCompany() failed"); + workerScript.log("applyToCompany", `Invalid job: '${field}'.`); return false; } // The Player object's applyForJob function can return string with special error messages if (isString(res)) { - workerScript.scriptRef.log(res); + workerScript.log("applyToCompany", res); return false; } if (res) { - if (workerScript.disableLogs.ALL == null && workerScript.disableLogs.applyToCompany == null) { - workerScript.log(`You were offered a new job at ${companyName} as a ${Player.jobs[companyName]}`); - } + workerScript.log("applyToCompany", `You were offered a new job at '${companyName}' as a '${Player.jobs[companyName]}'`); } else { - if (workerScript.disableLogs.ALL == null && workerScript.disableLogs.applyToCompany == null) { - workerScript.log(`You failed to get a new job/promotion at ${companyName} in the ${field} field.`); - } + workerScript.log("applyToCompany", `You failed to get a new job/promotion at '${companyName}' in the '${field}' field.`); } return res; }, getCompanyRep: function(companyName) { updateDynamicRam("getCompanyRep", getRamCost("getCompanyRep")); - if (Player.bitNodeN !== 4) { - if (SourceFileFlags[4] <= 1) { - throw makeRuntimeRejectMsg(workerScript, "Cannot run getCompanyRep(). It is a Singularity Function and requires SourceFile-4 (level 2) to run."); - return false; - } - } - - var company = Companies[companyName]; - if (company == null || !(company instanceof Company)) { - workerScript.scriptRef.log("ERROR: Invalid companyName passed into getCompanyRep(): " + companyName); - return -1; - } + checkSingularityAccess("getCompanyRep", 2); + const company = getCompany("getCompanyRep", companyName); return company.playerReputation; }, getCompanyFavor: function(companyName) { updateDynamicRam("getCompanyFavor", getRamCost("getCompanyFavor")); - if (Player.bitNodeN !== 4) { - if (SourceFileFlags[4] <= 1) { - throw makeRuntimeRejectMsg(workerScript, "Cannot run getCompanyFavor(). It is a Singularity Function and requires SourceFile-4 (level 2) to run."); - return false; - } - } - - var company = Companies[companyName]; - if (company == null || !(company instanceof Company)) { - workerScript.scriptRef.log("ERROR: Invalid companyName passed into getCompanyFavor(): " + companyName); - return -1; - } + checkSingularityAccess("getCompanyFavor", 2); + const company = getCompany("getCompanyFavor", companyName); return company.favor; }, getCompanyFavorGain: function(companyName) { updateDynamicRam("getCompanyFavorGain", getRamCost("getCompanyFavorGain")); - if (Player.bitNodeN !== 4) { - if (SourceFileFlags[4] <= 1) { - throw makeRuntimeRejectMsg(workerScript, "Cannot run getCompanyFavorGain(). It is a Singularity Function and requires SourceFile-4 (level 2) to run."); - return -1; - } - } - - var company = Companies[companyName]; - if (company == null || !(company instanceof Company)) { - workerScript.scriptRef.log("ERROR: Invalid companyName passed into getCompanyFavorGain(): " + companyName); - return -1; - } + checkSingularityAccess("getCompanyFavorGain", 2); + const company = getCompany("getCompanyFavorGain", companyName); return company.getFavorGain()[0]; }, checkFactionInvitations: function() { updateDynamicRam("checkFactionInvitations", getRamCost("checkFactionInvitations")); - if (Player.bitNodeN !== 4) { - if (SourceFileFlags[4] <= 1) { - throw makeRuntimeRejectMsg(workerScript, "Cannot run checkFactionInvitations(). It is a Singularity Function and requires SourceFile-4 (level 2) to run."); - return false; - } - } + checkSingularityAccess("checkFactionInvitations", 2); // Make a copy of Player.factionInvitations return Player.factionInvitations.slice(); }, joinFaction: function(name) { updateDynamicRam("joinFaction", getRamCost("joinFaction")); - if (Player.bitNodeN !== 4) { - if (SourceFileFlags[4] <= 1) { - throw makeRuntimeRejectMsg(workerScript, "Cannot run joinFaction(). It is a Singularity Function and requires SourceFile-4 (level 2) to run."); - return false; - } - } - - if (!factionExists(name)) { - workerScript.scriptRef.log("ERROR: Faction specified in joinFaction() does not exist."); - return false; - } + checkSingularityAccess("joinFaction", 2); + getFaction("workForFaction", name); if (!Player.factionInvitations.includes(name)) { - workerScript.scriptRef.log("ERROR: Cannot join " + name + " Faction because you have not been invited. joinFaction() failed"); + workerScript.log("joinFaction", `You have not been invited by faction '${name}'`); return false; } - var fac = Factions[name]; + const fac = Factions[name]; joinFaction(fac); // Update Faction Invitation list to account for joined + banned factions - for (var i = 0; i < Player.factionInvitations.length; ++i) { + for (let i = 0; i < Player.factionInvitations.length; ++i) { if (Player.factionInvitations[i] == name || Factions[Player.factionInvitations[i]].isBanned) { Player.factionInvitations.splice(i, 1); i--; } } Player.gainIntelligenceExp(CONSTANTS.IntelligenceSingFnBaseExpGain); - if (workerScript.disableLogs.ALL == null && workerScript.disableLogs.joinFaction == null) { - workerScript.scriptRef.log("Joined the " + name + " faction."); - } + workerScript.log("joinFaction", `Joined the '${name}' faction.`); return true; }, workForFaction: function(name, type) { updateDynamicRam("workForFaction", getRamCost("workForFaction")); - if (Player.bitNodeN !== 4) { - if (SourceFileFlags[4] <= 1) { - throw makeRuntimeRejectMsg(workerScript, "Cannot run workForFaction(). It is a Singularity Function and requires SourceFile-4 (level 2) to run."); - return false; - } - } + checkSingularityAccess("workForFaction", 2); + getFaction("workForFaction", name); // if the player is in a gang and the target faction is any of the gang faction, fail if(Player.inGang() && AllGangs[name] !== undefined) { - workerScript.scriptRef.log("ERROR: Faction specified in workForFaction() does not offer work at the moment."); + workerScript.log("workForFaction", `Faction '${name}' does not offer work at the moment.`); return; } if (inMission) { - workerScript.scriptRef.log("ERROR: workForFaction() failed because you are in the middle of a mission."); + workerScript.log("workForFaction", "You are in the middle of a mission."); return; } - if (!factionExists(name)) { - workerScript.scriptRef.log("ERROR: Faction specified in workForFaction() does not exist."); - return false; - } - if (!Player.factions.includes(name)) { - workerScript.scriptRef.log("ERROR: workForFaction() failed because you are not a member of " + name); + workerScript.log("workForFaction", `You are not a member of '${name}'`); return false; } if (Player.isWorking) { - var txt = Player.singularityStopWork(); - if (workerScript.shouldLog("workForFaction")) { - workerScript.log(txt); - } + const txt = Player.singularityStopWork(); + workerScript.log("workForFaction", txt); } var fac = Factions[name]; @@ -3139,142 +2966,90 @@ function NetscriptFunctions(workerScript) { case "hacking contracts": case "hackingcontracts": if (!hackAvailable.includes(fac.name)) { - workerScript.log("ERROR: Cannot carry out hacking contracts for " + fac.name + ". workForFaction() failed"); + workerScript.log("workForFaction", `Faction '${fac.name}' do not need help with hacking contracts.`); return false; } Player.startFactionHackWork(fac); - if (workerScript.shouldLog("workForFaction")) { - workerScript.log("Started carrying out hacking contracts for " + fac.name); - } + workerScript.log("workForFaction", `Started carrying out hacking contracts for '${fac.name}'`); return true; case "field": case "fieldwork": case "field work": if (!fdWkAvailable.includes(fac.name)) { - workerScript.log("ERROR: Cannot carry out field missions for " + fac.name + ". workForFaction() failed"); + workerScript.log("workForFaction", `Faction '${fac.name}' do not need help with field missions.`); return false; } Player.startFactionFieldWork(fac); - if (workerScript.shouldLog("workForFaction")) { - workerScript.log("Started carrying out field missions for " + fac.name); - } + workerScript.log("workForFaction", `Started carrying out field missions for '${fac.name}'`); return true; case "security": case "securitywork": case "security work": if (!scWkAvailable.includes(fac.name)) { - workerScript.log("ERROR: Cannot serve as security detail for " + fac.name + ". workForFaction() failed"); + workerScript.log("workForFaction", `Faction '${fac.name}' do not need help with security work.`); return false; } Player.startFactionSecurityWork(fac); - if (workerScript.shouldLog("workForFaction")) { - workerScript.log("Started serving as security details for " + fac.name); - } + workerScript.log("workForFaction", `Started carrying out security work for '${fac.name}'`); return true; default: - workerScript.log("ERROR: Invalid work type passed into workForFaction(): " + type); + workerScript.log("workForFaction", `Invalid work type: '${type}`); } return true; }, getFactionRep: function(name) { updateDynamicRam("getFactionRep", getRamCost("getFactionRep")); - if (Player.bitNodeN !== 4) { - if (SourceFileFlags[4] <= 1) { - throw makeRuntimeRejectMsg(workerScript, "Cannot run getFactionRep(). It is a Singularity Function and requires SourceFile-4 (level 2) to run."); - return -1; - } - } - - if (!factionExists(name)) { - workerScript.scriptRef.log("ERROR: Faction specified in getFactionRep() does not exist."); - return -1; - } - - return Factions[name].playerReputation; + checkSingularityAccess("getFactionRep", 2); + const faction = getFaction("getFactionRep", name); + return faction.playerReputation; }, getFactionFavor: function(name) { updateDynamicRam("getFactionFavor", getRamCost("getFactionFavor")); - if (Player.bitNodeN !== 4) { - if (SourceFileFlags[4] <= 1) { - throw makeRuntimeRejectMsg(workerScript, "Cannot run getFactionFavor(). It is a Singularity Function and requires SourceFile-4 (level 2) to run."); - return -1; - } - } - - if (!factionExists(name)) { - workerScript.scriptRef.log("ERROR: Faction specified in getFactionFavor() does not exist."); - return -1; - } - - return Factions[name].favor; + checkSingularityAccess("getFactionFavor", 2); + const faction = getFaction("getFactionFavor", name); + return faction.favor; }, getFactionFavorGain: function(name) { updateDynamicRam("getFactionFavorGain", getRamCost("getFactionFavorGain")); - if (Player.bitNodeN !== 4) { - if (SourceFileFlags[4] <= 1) { - throw makeRuntimeRejectMsg(workerScript, "Cannot run getFactionFavorGain(). It is a Singularity Function and requires SourceFile-4 (level 2) to run."); - return -1; - } - } - - if (!factionExists(name)) { - workerScript.scriptRef.log("ERROR: Faction specified in getFactionFavorGain() does not exist."); - return -1; - } - - return Factions[name].getFavorGain()[0]; + checkSingularityAccess("getFactionFavorGain", 2); + const faction = getFaction("getFactionFavorGain", name); + return faction.getFavorGain()[0]; }, donateToFaction: function(name, amt) { updateDynamicRam("donateToFaction", getRamCost("donateToFaction")); - if (Player.bitNodeN !== 4) { - if (SourceFileFlags[4] <= 2) { - throw makeRuntimeRejectMsg(workerScript, "Cannot run donateToFaction(). It is a Singularity Function and requires SourceFile-4 (level 3) to run."); - return; - } - } + checkSingularityAccess("donateToFaction", 3); + const faction = getFaction("donateToFaction", name); - if (!factionExists(name)) { - workerScript.log(`ERROR: Faction specified in donateToFaction() does not exist: ${name}`); - return false; - } if (typeof amt !== 'number' || amt <= 0) { - workerScript.log(`ERROR: Invalid donation amount specified in donateToFaction(): ${amt}. Must be numeric and positive`); + workerScript.log("donateToFaction", `Invalid donation amount: '${amt}'.`); return false; } if (Player.money.lt(amt)) { - workerScript.log(`ERROR: You do not have enough money to donate $${amt} to ${name}`); + workerScript.log("donateToFaction", `You do not have enough money to donate ${numeralWrapper.format(amt, '$0.000a')} to '${name}'`); return false; } - var repNeededToDonate = Math.round(CONSTANTS.BaseFavorToDonate * BitNodeMultipliers.RepToDonateToFaction); - if (Factions[name].favor < repNeededToDonate) { - workerScript.log(`ERROR: You do not have enough favor to donate to this faction. Have ${Factions[name].favor}, need ${repNeededToDonate}`); + const repNeededToDonate = Math.round(CONSTANTS.BaseFavorToDonate * BitNodeMultipliers.RepToDonateToFaction); + if (faction.favor < repNeededToDonate) { + workerScript.log("donateToFaction", `You do not have enough favor to donate to this faction. Have ${faction.favor}, need ${repNeededToDonate}`); return false; } - var repGain = amt / CONSTANTS.DonateMoneyToRepDivisor * Player.faction_rep_mult; - Factions[name].playerReputation += repGain; + const repGain = amt / CONSTANTS.DonateMoneyToRepDivisor * Player.faction_rep_mult; + faction.playerReputation += repGain; Player.loseMoney(amt); - if (workerScript.shouldLog("donateToFaction")) { - workerScript.log(`$${amt} donated to ${name} for ${repGain} reputation`); - } + workerScript.log("donateToFaction", `${numeralWrapper.format(amt, '$0.000a')} donated to '${name}' for ${numeralWrapper.format(repGain, '0.000a')} reputation`); return true; }, createProgram: function(name) { updateDynamicRam("createProgram", getRamCost("createProgram")); - if (Player.bitNodeN !== 4) { - if (SourceFileFlags[4] <= 2) { - throw makeRuntimeRejectMsg(workerScript, "Cannot run createProgram(). It is a Singularity Function and requires SourceFile-4 (level 3) to run."); - return false; - } - } + checkSingularityAccess("createProgram", 3); + if (inMission) { - workerScript.scriptRef.log("ERROR: createProgram() failed because you are in the middle of a mission."); + workerScript.log("createProgram", "You are in the middle of a mission."); return; } if (Player.isWorking) { var txt = Player.singularityStopWork(); - if (workerScript.disableLogs.ALL == null && workerScript.disableLogs.createProgram == null) { - workerScript.scriptRef.log(txt); - } + workerScript.log("createProgram", txt); } name = name.toLowerCase(); @@ -3287,43 +3062,34 @@ function NetscriptFunctions(workerScript) { } if (p == null) { - workerScript.scriptRef.log("ERROR: createProgram() failed because the specified program does not exist: " + name); + workerScript.log("createProgram", `The specified program does not exist: '${name}`); return false; } if (Player.hasProgram(p.name)) { - workerScript.scriptRef.log('ERROR: createProgram() failed because you already have the ' + p.name + ' program'); + workerScript.log("createProgram", `You already have the '${p.name}' program`); return false; } if (!p.create.req(Player)) { - workerScript.scriptRef.log("ERROR: createProgram() failed because hacking level is too low to create " + p.name + " (level " + p.create.level + " req)"); + workerScript.log("createProgram", `Hacking level is too low to create '${p.name}' (level ${p.create.level} req)`); return false } Player.startCreateProgramWork(p.name, p.create.time, p.create.level); - if (workerScript.disableLogs.ALL == null && workerScript.disableLogs.createProgram == null) { - workerScript.scriptRef.log("Began creating program: " + name); - } + workerScript.log("createProgram", `Began creating program: '${name}'`); return true; }, commitCrime: function(crimeRoughName) { updateDynamicRam("commitCrime", getRamCost("commitCrime")); - if (Player.bitNodeN !== 4) { - if (SourceFileFlags[4] <= 2) { - throw makeRuntimeRejectMsg(workerScript, "Cannot run commitCrime(). It is a Singularity Function and requires SourceFile-4 (level 3) to run."); - return; - } - } + checkSingularityAccess("commitCrime", 3); if (inMission) { - workerScript.scriptRef.log("ERROR: commitCrime() failed because you are in the middle of a mission."); + workerScript.log("commitCrime", "You are in the middle of a mission."); return; } if (Player.isWorking) { - var txt = Player.singularityStopWork(); - if (workerScript.disableLogs.ALL == null && workerScript.disableLogs.commitCrime == null) { - workerScript.scriptRef.log(txt); - } + const txt = Player.singularityStopWork(); + workerScript.log("commitCrime", txt); } // Set Location to slums @@ -3331,53 +3097,36 @@ function NetscriptFunctions(workerScript) { const crime = findCrime(crimeRoughName.toLowerCase()); if(crime == null) { // couldn't find crime - throw makeRuntimeRejectMsg(workerScript, "Invalid crime passed into commitCrime(): " + crimeRoughName); - } - if(workerScript.disableLogs.ALL == null && workerScript.disableLogs.commitCrime == null) { - workerScript.scriptRef.log("Attempting to commit crime: "+crime.name+"..."); + throw makeRuntimeErrorMsg("commitCrime", `Invalid crime: '${crimeRoughName}'`); } + workerScript.log("commitCrime", `Attempting to commit ${crime.name}...`); return crime.commit(Player, 1, {workerscript: workerScript}); }, getCrimeChance: function(crimeRoughName) { updateDynamicRam("getCrimeChance", getRamCost("getCrimeChance")); - if (Player.bitNodeN !== 4) { - if (SourceFileFlags[4] <= 2) { - throw makeRuntimeRejectMsg(workerScript, "Cannot run getCrimeChance(). It is a Singularity Function and requires SourceFile-4 (level 3) to run."); - return; - } - } + checkSingularityAccess("getCrimeChance", 3); const crime = findCrime(crimeRoughName.toLowerCase()); if(crime == null) { - throw makeRuntimeRejectMsg(workerScript, "Invalid crime passed into getCrimeChance(): " + crime); + throw makeRuntimeErrorMsg("getCrimeChance", `Invalid crime: ${crimeRoughName}`); } return crime.successRate(Player); }, getCrimeStats: function(crimeRoughName) { updateDynamicRam("getCrimeStats", getRamCost("getCrimeStats")); - if (Player.bitNodeN !== 4) { - if (SourceFileFlags[4] <= 2) { - throw makeRuntimeRejectMsg(workerScript, "Cannot run getCrimeStats(). It is a Singularity Function and requires SourceFile-4 (level 3) to run."); - return; - } - } + checkSingularityAccess("getCrimeStats", 3); const crime = findCrime(crimeRoughName.toLowerCase()); if(crime == null) { - throw makeRuntimeRejectMsg(workerScript, "Invalid crime passed into getCrimeStats(): " + crime); + throw makeRuntimeErrorMsg("getCrimeStats", `Invalid crime: ${crimeRoughName}`); } return Object.assign({}, crime); }, getOwnedAugmentations: function(purchased=false) { updateDynamicRam("getOwnedAugmentations", getRamCost("getOwnedAugmentations")); - if (Player.bitNodeN !== 4) { - if (SourceFileFlags[4] <= 2) { - throw makeRuntimeRejectMsg(workerScript, "Cannot run getOwnedAugmentations(). It is a Singularity Function and requires SourceFile-4 (level 3) to run."); - return []; - } - } + checkSingularityAccess("getOwnedAugmentations", 3); var res = []; for (var i = 0; i < Player.augmentations.length; ++i) { res.push(Player.augmentations[i].name); @@ -3391,12 +3140,7 @@ function NetscriptFunctions(workerScript) { }, getOwnedSourceFiles: function() { updateDynamicRam("getOwnedSourceFiles", getRamCost("getOwnedSourceFiles")); - if (Player.bitNodeN !== 4) { - if (SourceFileFlags[4] <= 2) { - throw makeRuntimeRejectMsg(workerScript, "Cannot run getOwnedSourceFiles(). It is a Singularity Function and requires SourceFile-4 (level 3) to run."); - return []; - } - } + checkSingularityAccess("getOwnedSourceFiles", 3); let res = []; for (let i = 0; i < Player.sourceFiles.length; ++i) { res.push({n: Player.sourceFiles[i].n, lvl: Player.sourceFiles[i].lvl}); @@ -3405,20 +3149,10 @@ function NetscriptFunctions(workerScript) { }, getAugmentationsFromFaction: function(facname) { updateDynamicRam("getAugmentationsFromFaction", getRamCost("getAugmentationsFromFaction")); - if (Player.bitNodeN !== 4) { - if (SourceFileFlags[4] <= 2) { - throw makeRuntimeRejectMsg(workerScript, "Cannot run getAugmentationsFromFaction(). It is a Singularity Function and requires SourceFile-4 (level 3) to run."); - return []; - } - } + checkSingularityAccess("getAugmentationsFromFaction", 3); + const faction = getFaction("getAugmentationsFromFaction", facname); - const fac = Factions[facname]; - if (!(fac instanceof Faction)) { - workerScript.scriptRef.log("ERROR: getAugmentationsFromFaction() failed. Invalid faction name passed in (this is case-sensitive): " + facname); - return []; - } - - // If player has a gang with this faction, return all factions + // If player has a gang with this faction, return all augmentations. if (Player.hasGangWith(facname)) { const res = []; for (const augName in Augmentations) { @@ -3431,74 +3165,31 @@ function NetscriptFunctions(workerScript) { return res; } - return fac.augmentations.slice(); + return faction.augmentations.slice(); }, getAugmentationPrereq: function(name) { updateDynamicRam("getAugmentationPrereq", getRamCost("getAugmentationPrereq")); - if (Player.bitNodeN !== 4) { - if (SourceFileFlags[4] <= 2) { - throw makeRuntimeRejectMsg(workerScript, "Cannot run getAugmentationPrereq(). It is a Singularity Function and requires SourceFile-4 (level 3) to run."); - return false; - } - } - - if (!augmentationExists(name)) { - workerScript.scriptRef.log("ERROR: getAugmentationPrereq() failed. Invalid Augmentation name passed in (note: this is case-sensitive): " + name); - return []; - } - - var aug = Augmentations[name]; + checkSingularityAccess("getAugmentationPrereq", 3); + const aug = getAugmentation("getAugmentationPrereq", name); return aug.prereqs.slice(); }, getAugmentationCost: function(name) { updateDynamicRam("getAugmentationCost", getRamCost("getAugmentationCost")); - if (Player.bitNodeN !== 4) { - if (SourceFileFlags[4] <= 2) { - throw makeRuntimeRejectMsg(workerScript, "Cannot run getAugmentationCost(). It is a Singularity Function and requires SourceFile-4 (level 3) to run."); - return false; - } - } - - if (!augmentationExists(name)) { - workerScript.scriptRef.log("ERROR: getAugmentationCost() failed. Invalid Augmentation name passed in (note: this is case-sensitive): " + name); - return [-1, -1]; - } - - var aug = Augmentations[name]; + checkSingularityAccess("getAugmentationCost", 3); + const aug = getAugmentation("getAugmentationCost", name); return [aug.baseRepRequirement, aug.baseCost]; }, getAugmentationStats: function(name) { updateDynamicRam("getAugmentationStats", getRamCost("getAugmentationStats")); - if (Player.bitNodeN !== 4) { - if (SourceFileFlags[4] <= 2) { - throw makeRuntimeRejectMsg(workerScript, "Cannot run getAugmentationStats(). It is a Singularity Function and requires SourceFile-4 (level 3) to run."); - return false; - } - } - - if (!augmentationExists(name)) { - workerScript.scriptRef.log("ERROR: getAugmentationStats() failed. Invalid Augmentation name passed in (note: this is case-sensitive): " + name); - return {}; - } - - - var aug = Augmentations[name]; + checkSingularityAccess("getAugmentationStats", 3); + const aug = getAugmentation("getAugmentationStats", name); return Object.assign({}, aug.mults); }, purchaseAugmentation: function(faction, name) { updateDynamicRam("purchaseAugmentation", getRamCost("purchaseAugmentation")); - if (Player.bitNodeN !== 4) { - if (SourceFileFlags[4] <= 2) { - throw makeRuntimeRejectMsg(workerScript, "Cannot run purchaseAugmentation(). It is a Singularity Function and requires SourceFile-4 (level 3) to run."); - return false; - } - } - - const fac = Factions[faction]; - if (!(fac instanceof Faction)) { - workerScript.log("ERROR: purchaseAugmentation() failed because of invalid faction name: " + faction); - return false; - } + checkSingularityAccess("purchaseAugmentation", 3); + const fac = getFaction("purchaseAugmentation", faction); + const aug = getAugmentation("purchaseAugmentation", name); let augs = []; if (Player.hasGangWith(faction)) { @@ -3513,39 +3204,33 @@ function NetscriptFunctions(workerScript) { } if (!augs.includes(name)) { - workerScript.log("ERROR: purchaseAugmentation() failed because the faction " + faction + " does not contain the " + name + " augmentation"); + workerScript.log("purchaseAugmentation", `Faction '${faction}' does not have the '${name}' augmentation.`); return false; } - const aug = Augmentations[name]; - if (!(aug instanceof Augmentation)) { - workerScript.log("ERROR: purchaseAugmentation() failed because of invalid augmentation name: " + name); - return false; - } - - let isNeuroflux = (aug.name === AugmentationNames.NeuroFluxGovernor); + const isNeuroflux = (aug.name === AugmentationNames.NeuroFluxGovernor); if (!isNeuroflux) { for (let j = 0; j < Player.queuedAugmentations.length; ++j) { if (Player.queuedAugmentations[j].name === aug.name) { - workerScript.log("ERROR: purchaseAugmentation() failed because you already have " + name); + workerScript.log("purchaseAugmentation", `You already have the '${name}' augmentation.`); return false; } } for (let j = 0; j < Player.augmentations.length; ++j) { if (Player.augmentations[j].name === aug.name) { - workerScript.log("ERROR: purchaseAugmentation() failed because you already have " + name); + workerScript.log("purchaseAugmentation", `You already have the '${name}' augmentation.`); return false; } } } if (fac.playerReputation < aug.baseRepRequirement) { - workerScript.log("ERROR: purchaseAugmentation() failed because you do not have enough reputation with " + fac.name); + workerScript.log("purchaseAugmentation", `You do not have enough reputation with '${fac.name}'.`); return false; } - var res = purchaseAugmentation(aug, fac, true); - workerScript.log(res); + const res = purchaseAugmentation(aug, fac, true); + workerScript.log("purchaseAugmentation", res); if (isString(res) && res.startsWith("You purchased")) { Player.gainIntelligenceExp(CONSTANTS.IntelligenceSingFnBaseExpGain); return true; @@ -3553,18 +3238,13 @@ function NetscriptFunctions(workerScript) { return false; } }, - softReset: function() { + softReset: function(cbScript) { updateDynamicRam("softReset", getRamCost("softReset")); - if (Player.bitNodeN !== 4) { - if (SourceFileFlags[4] <= 2) { - throw makeRuntimeRejectMsg(workerScript, "Cannot run softReset(). It is a Singularity Function and requires SourceFile-4 (level 3) to run."); - return false; - } - } + checkSingularityAccess("softReset", 3); - workerScript.log("Soft resetting. This will cause this script to be killed"); + workerScript.log("softReset", "Soft resetting. This will cause this script to be killed"); setTimeoutRef(() => { - prestigeAugmentation(); + prestigeAugmentation(cbScript); }, 0); // Prevent workerScript from "finishing execution naturally" @@ -3573,19 +3253,14 @@ function NetscriptFunctions(workerScript) { }, installAugmentations: function(cbScript) { updateDynamicRam("installAugmentations", getRamCost("installAugmentations")); - if (Player.bitNodeN !== 4) { - if (SourceFileFlags[4] <= 2) { - throw makeRuntimeRejectMsg(workerScript, "Cannot run installAugmentations(). It is a Singularity Function and requires SourceFile-4 (level 3) to run."); - return false; - } - } + checkSingularityAccess("installAugmentations", 3); if (Player.queuedAugmentations.length === 0) { - workerScript.scriptRef.log("ERROR: installAugmentations() failed because you do not have any Augmentations to be installed"); + workerScript.log("installAugmentations", "You do not have any Augmentations to be installed."); return false; } Player.gainIntelligenceExp(CONSTANTS.IntelligenceSingFnBaseExpGain); - workerScript.log("Installing Augmentations. This will cause this script to be killed"); + workerScript.log("installAugmentations", "Installing Augmentations. This will cause this script to be killed"); setTimeoutRef(() => { installAugmentations(cbScript); }, 0); @@ -3598,24 +3273,13 @@ function NetscriptFunctions(workerScript) { gang: { getMemberNames: function() { updateDynamicRam("getMemberNames", getRamCost("gang", "getMemberNames")); - nsGang.checkGangApiAccess(workerScript, "getMemberNames"); - - try { - const names = []; - for (const member of Player.gang.members) { - names.push(member.name); - } - return names; - } catch(e) { - throw makeRuntimeRejectMsg(workerScript, nsGang.unknownGangApiExceptionMessage("getMemberNames", e)); - } + checkGangApiAccess("getMemberNames"); + return Player.gang.members.map(member => member.name); }, getGangInformation: function() { updateDynamicRam("getGangInformation", getRamCost("gang", "getGangInformation")); - nsGang.checkGangApiAccess(workerScript, "getGangInformation"); - - try { - return { + checkGangApiAccess("getGangInformation"); + return { faction: Player.gang.facName, isHacking: Player.gang.isHackingGang, moneyGainRate: Player.gang.moneyGainRate, @@ -3627,273 +3291,167 @@ function NetscriptFunctions(workerScript) { territoryWarfareEngaged: Player.gang.territoryWarfareEngaged, wantedLevel: Player.gang.wanted, wantedLevelGainRate: Player.gang.wantedGainRate, - } - } catch(e) { - throw makeRuntimeRejectMsg(workerScript, nsGang.unknownGangApiExceptionMessage("getGangInformation", e)); - } + }; }, getOtherGangInformation: function() { updateDynamicRam("getOtherGangInformation", getRamCost("gang", "getOtherGangInformation")); - nsGang.checkGangApiAccess(workerScript, "getOtherGangInformation"); - - try { - // We have to make a deep copy - const cpy = {}; - for (const gang in AllGangs) { - cpy[gang] = Object.assign({}, AllGangs[gang]); - } - - return cpy; - } catch(e) { - throw makeRuntimeRejectMsg(workerScript, nsGang.unknownGangApiExceptionMessage("getOtherGangInformation", e)); + checkGangApiAccess("getOtherGangInformation"); + const cpy = {}; + for (const gang in AllGangs) { + cpy[gang] = Object.assign({}, AllGangs[gang]); } + + return cpy; }, getMemberInformation: function(name) { updateDynamicRam("getMemberInformation", getRamCost("gang", "getMemberInformation")); - nsGang.checkGangApiAccess(workerScript, "getMemberInformation"); - - try { - for (const member of Player.gang.members) { - if (member.name === name) { - return { - agility: member.agi, - agilityEquipMult: member.agi_mult, - agilityAscensionMult: member.agi_asc_mult, - augmentations: member.augmentations.slice(), - charisma: member.cha, - charismaEquipMult: member.cha_mult, - charismaAscensionMult: member.cha_asc_mult, - defense: member.def, - defenseEquipMult: member.def_mult, - defenseAscensionMult: member.def_asc_mult, - dexterity: member.dex, - dexterityEquipMult: member.dex_mult, - dexterityAscensionMult: member.dex_asc_mult, - equipment: member.upgrades.slice(), - hacking: member.hack, - hackingEquipMult: member.hack_mult, - hackingAscensionMult: member.hack_asc_mult, - strength: member.str, - strengthEquipMult: member.str_mult, - strengthAscensionMult: member.str_asc_mult, - task: member.task, - } - } - } - - workerScript.log(`Invalid argument passed to gang.getMemberInformation(). No gang member could be found with name ${name}`); - return {}; // Member could not be found - } catch(e) { - throw makeRuntimeRejectMsg(workerScript, nsGang.unknownGangApiExceptionMessage("getMemberInformation", e)); + checkGangApiAccess("getMemberInformation"); + const member = getGangMember("getMemberInformation", name); + return { + agility: member.agi, + agilityEquipMult: member.agi_mult, + agilityAscensionMult: member.agi_asc_mult, + augmentations: member.augmentations.slice(), + charisma: member.cha, + charismaEquipMult: member.cha_mult, + charismaAscensionMult: member.cha_asc_mult, + defense: member.def, + defenseEquipMult: member.def_mult, + defenseAscensionMult: member.def_asc_mult, + dexterity: member.dex, + dexterityEquipMult: member.dex_mult, + dexterityAscensionMult: member.dex_asc_mult, + equipment: member.upgrades.slice(), + hacking: member.hack, + hackingEquipMult: member.hack_mult, + hackingAscensionMult: member.hack_asc_mult, + strength: member.str, + strengthEquipMult: member.str_mult, + strengthAscensionMult: member.str_asc_mult, + task: member.task, } }, canRecruitMember: function() { updateDynamicRam("canRecruitMember", getRamCost("gang", "canRecruitMember")); - nsGang.checkGangApiAccess(workerScript, "canRecruitMember"); - - try { - return Player.gang.canRecruitMember(); - } catch(e) { - throw makeRuntimeRejectMsg(workerScript, nsGang.unknownGangApiExceptionMessage("canRecruitMember", e)); - } + checkGangApiAccess("canRecruitMember"); + return Player.gang.canRecruitMember(); }, recruitMember: function(name) { updateDynamicRam("recruitMember", getRamCost("gang", "recruitMember")); - nsGang.checkGangApiAccess(workerScript, "recruitMember"); - - try { - const res = Player.gang.recruitMember(name); - if (workerScript.shouldLog("recruitMember")) { - if (res) { - workerScript.log(`Successfully recruited Gang Member ${name}`); - } else { - workerScript.log(`Failed to recruit Gang Member ${name}`); - } + checkGangApiAccess("recruitMember"); + const recruited = Player.gang.recruitMember(name); + if (workerScript.shouldLog("recruitMember")) { + if (recruited) { + workerScript.log("recruitMember", `Successfully recruited Gang Member '${name}'`); + } else { + workerScript.log("recruitMember", `Failed to recruit Gang Member '${name}'`); } - - return res; - } catch(e) { - throw makeRuntimeRejectMsg(workerScript, nsGang.unknownGangApiExceptionMessage("recruitMember", e)); } + + return recruited; }, getTaskNames: function() { updateDynamicRam("getTaskNames", getRamCost("gang", "getTaskNames")); - nsGang.checkGangApiAccess(workerScript, "getTaskNames"); - - try { - const tasks = Player.gang.getAllTaskNames(); - tasks.unshift("Unassigned"); - return tasks; - } catch(e) { - throw makeRuntimeRejectMsg(workerScript, nsGang.unknownGangApiExceptionMessage("getTaskNames", e)); - } + checkGangApiAccess("getTaskNames"); + const tasks = Player.gang.getAllTaskNames(); + tasks.unshift("Unassigned"); + return tasks; }, setMemberTask: function(memberName, taskName) { updateDynamicRam("setMemberTask", getRamCost("gang", "setMemberTask")); - nsGang.checkGangApiAccess(workerScript, "setMemberTask"); - - try { - for (const member of Player.gang.members) { - if (member.name === memberName) { - const res = member.assignToTask(taskName); - if (workerScript.shouldLog("setMemberTask")) { - if (res) { - workerScript.log(`Successfully assigned Gang Member ${memberName} to ${taskName} task`); - } else { - workerScript.log(`Failed to assign Gang Member ${memberName} to ${taskName} task. ${memberName} is now Unassigned`); - } - } - - return res; - } + checkGangApiAccess("setMemberTask"); + const member = getGangMember("setMemberTask", memberName); + const success = member.assignToTask(taskName); + if (workerScript.shouldLog("setMemberTask")) { + if (success) { + workerScript.log("setMemberTask", `Successfully assigned Gang Member '${memberName}' to '${taskName}' task`); + } else { + workerScript.log("setMemberTask", `Failed to assign Gang Member '${memberName}' to '${taskName}' task. '${memberName}' is now Unassigned`); } - - workerScript.log(`Invalid argument passed to gang.setMemberTask(). No gang member could be found with name ${memberName}`); - return false; - } catch(e) { - throw makeRuntimeRejectMsg(workerScript, nsGang.unknownGangApiExceptionMessage("setMemberTask", e)); } + + return success; }, getTaskStats: function(taskName) { updateDynamicRam("getTaskStats", getRamCost("gang", "getTaskStats")); - nsGang.checkGangApiAccess(workerScript, "getTaskStats"); - const task = GangMemberTasks[taskName]; - if (!task) { - throw makeRuntimeRejectMsg(workerScript, nsGang.unknownGangApiExceptionMessage("getTaskStats", `${taskName} does not exists`)); - } + checkGangApiAccess("getTaskStats"); + const task = getGangTask("getTaskStats", taskName); const copy = Object.assign({}, task); copy.territory = Object.assign({}, task.territory) return copy; }, getEquipmentNames: function() { updateDynamicRam("getEquipmentNames", getRamCost("gang", "getEquipmentNames")); - nsGang.checkGangApiAccess(workerScript, "getEquipmentNames"); - - try { - return Player.gang.getAllUpgradeNames(); - } catch(e) { - throw makeRuntimeRejectMsg(workerScript, nsGang.unknownGangApiExceptionMessage("getEquipmentNames", e)); - } + checkGangApiAccess("getEquipmentNames"); + return Player.gang.getAllUpgradeNames(); }, getEquipmentCost: function(equipName) { updateDynamicRam("getEquipmentCost", getRamCost("gang", "getEquipmentCost")); - nsGang.checkGangApiAccess(workerScript, "getEquipmentCost"); - - try { - return Player.gang.getUpgradeCost(equipName); - } catch(e) { - throw makeRuntimeRejectMsg(workerScript, nsGang.unknownGangApiExceptionMessage("getEquipmentCost", e)); - } + checkGangApiAccess("getEquipmentCost"); + return Player.gang.getUpgradeCost(equipName); }, getEquipmentType: function(equipName) { updateDynamicRam("getEquipmentType", getRamCost("gang", "getEquipmentType")); - nsGang.checkGangApiAccess(workerScript, "getEquipmentType"); - - try { - return Player.gang.getUpgradeType(equipName); - } catch(e) { - throw makeRuntimeRejectMsg(workerScript, nsGang.unknownGangApiExceptionMessage("getEquipmentType", e)); - } + checkGangApiAccess("getEquipmentType"); + return Player.gang.getUpgradeType(equipName); }, getEquipmentStats: function(equipName) { updateDynamicRam("getEquipmentStats", getRamCost("gang", "getEquipmentStats")); - nsGang.checkGangApiAccess(workerScript, "getEquipmentStats"); - + checkGangApiAccess("getEquipmentStats"); const equipment = GangMemberUpgrades[equipName]; if (!equipment) { - throw makeRuntimeRejectMsg(workerScript, nsGang.unknownGangApiExceptionMessage("getEquipmentStats", `${equipName} does not exists`)); + throw makeRuntimeErrorMsg("getEquipmentStats", `Invalid equipment: ${equipName}`); } return Object.assign({}, equipment.mults); }, purchaseEquipment: function(memberName, equipName) { updateDynamicRam("purchaseEquipment", getRamCost("gang", "purchaseEquipment")); - nsGang.checkGangApiAccess(workerScript, "purchaseEquipment"); - - try { - for (const member of Player.gang.members) { - if (member.name === memberName) { - const res = member.buyUpgrade(equipName, Player, Player.gang); - if (workerScript.shouldLog("purchaseEquipment")) { - if (res) { - workerScript.log(`Purchased ${equipName} for Gang member ${memberName}`); - } else { - workerScript.log(`Failed to purchase ${equipName} for Gang member ${memberName}`); - } - } - - return res; - } + checkGangApiAccess("purchaseEquipment"); + const member = getGangMember("purchaseEquipment", memberName); + const res = member.buyUpgrade(equipName, Player, Player.gang); + if (workerScript.shouldLog("purchaseEquipment")) { + if (res) { + workerScript.log("purchaseEquipment", `Purchased '${equipName}' for Gang member '${memberName}'`); + } else { + workerScript.log("purchaseEquipment", `Failed to purchase '${equipName}' for Gang member '${memberName}'`); } - - workerScript.log(`Invalid argument passed to gang.purchaseEquipment(). No gang member could be found with name ${memberName}`); - return false; - } catch(e) { - throw makeRuntimeRejectMsg(workerScript, nsGang.unknownGangApiExceptionMessage("purchaseEquipment", e)); } + + return res; }, ascendMember: function(name) { updateDynamicRam("ascendMember", getRamCost("gang", "ascendMember")); - nsGang.checkGangApiAccess(workerScript, "ascendMember"); - - try { - for (const member of Player.gang.members) { - if (member.name === name) { - return Player.gang.ascendMember(member, workerScript); - } - } - - workerScript.log(`Invalid argument passed to gang.ascendMember(). No gang member could be found with name ${name}`); - return false; - } catch(e) { - throw makeRuntimeRejectMsg(workerScript, nsGang.unknownGangApiExceptionMessage("ascendMember", e)); - } + checkGangApiAccess("ascendMember"); + const member = getGangMember("ascendMember", name); + return Player.gang.ascendMember(member, workerScript); }, setTerritoryWarfare: function(engage) { updateDynamicRam("setTerritoryWarfare", getRamCost("gang", "setTerritoryWarfare")); - nsGang.checkGangApiAccess(workerScript, "setTerritoryWarfare"); - - try { - if (engage) { - Player.gang.territoryWarfareEngaged = true; - if (workerScript.shouldLog("setTerritoryWarfare")) { - workerScript.log("Engaging in Gang Territory Warfare"); - } - } else { - Player.gang.territoryWarfareEngaged = false; - if (workerScript.shouldLog("setTerritoryWarfare")) { - workerScript.log("Disengaging in Gang Territory Warfare"); - } - } - } catch(e) { - throw makeRuntimeRejectMsg(workerScript, nsGang.unknownGangApiExceptionMessage("setTerritoryWarfare", e)); + checkGangApiAccess("setTerritoryWarfare"); + if (engage) { + Player.gang.territoryWarfareEngaged = true; + workerScript.log("setTerritoryWarfare", "Engaging in Gang Territory Warfare"); + } else { + Player.gang.territoryWarfareEngaged = false; + workerScript.log("setTerritoryWarfare", "Disengaging in Gang Territory Warfare"); } }, getChanceToWinClash: function(otherGang) { updateDynamicRam("getChanceToWinClash", getRamCost("gang", "getChanceToWinClash")); - nsGang.checkGangApiAccess(workerScript, "getChanceToWinClash"); - - try { - if (AllGangs[otherGang] == null) { - workerScript.log(`Invalid gang specified in gang.getChanceToWinClash() : ${otherGang}`); - return 0; - } - - const playerPower = AllGangs[Player.gang.facName].power; - const otherPower = AllGangs[otherGang].power; - - return playerPower / (otherPower + playerPower); - } catch(e) { - throw makeRuntimeRejectMsg(workerScript, nsGang.unknownGangApiExceptionMessage("getChanceToWinClash", e)); + checkGangApiAccess("getChanceToWinClash"); + if (AllGangs[otherGang] == null) { + throw makeRuntimeErrorMsg(`gang.${getChanceToWinClash}`, `Invalid gang: ${otherGang}`); } + + const playerPower = AllGangs[Player.gang.facName].power; + const otherPower = AllGangs[otherGang].power; + + return playerPower / (otherPower + playerPower); }, getBonusTime: function() { - nsGang.checkGangApiAccess(workerScript, "getBonusTime"); - - try { - return Math.round(Player.gang.storedCycles / 5); - } catch(e) { - throw makeRuntimeRejectMsg(workerScript, nsGang.unknownGangApiExceptionMessage("getBonusTime", e)); - } + updateDynamicRam("getBonusTime", getRamCost("gang", "getBonusTime")); + checkGangApiAccess("getBonusTime"); + return Math.round(Player.gang.storedCycles / 5); }, }, // end gang namespace @@ -3901,419 +3459,224 @@ function NetscriptFunctions(workerScript) { bladeburner: { getContractNames: function() { updateDynamicRam("getContractNames", getRamCost("bladeburner", "getContractNames")); - if (Player.bladeburner instanceof Bladeburner && (Player.bitNodeN === 7 || SourceFileFlags[7] > 0)) { - return Player.bladeburner.getContractNamesNetscriptFn(); - } - throw makeRuntimeRejectMsg(workerScript, "getContractNames() failed because you do not currently have access to the Bladeburner API. This is either because you are not currently employed " + - "at the Bladeburner division or because you do not have Source-File 7"); + checkBladeburnerAccess("getContractNames"); + return Player.bladeburner.getContractNamesNetscriptFn(); }, getOperationNames: function() { updateDynamicRam("getOperationNames", getRamCost("bladeburner", "getOperationNames")); - if (Player.bladeburner instanceof Bladeburner && (Player.bitNodeN === 7 || SourceFileFlags[7] > 0)) { - return Player.bladeburner.getOperationNamesNetscriptFn(); - } - throw makeRuntimeRejectMsg(workerScript, "getOperationNames() failed because you do not currently have access to the Bladeburner API. This is either because you are not currently employed " + - "at the Bladeburner division or because you do not have Source-File 7"); + checkBladeburnerAccess("getOperationNames"); + return Player.bladeburner.getOperationNamesNetscriptFn(); }, getBlackOpNames: function() { updateDynamicRam("getBlackOpNames", getRamCost("bladeburner", "getBlackOpNames")); - if (Player.bladeburner instanceof Bladeburner && (Player.bitNodeN === 7 || SourceFileFlags[7] > 0)) { - return Player.bladeburner.getBlackOpNamesNetscriptFn(); - } - throw makeRuntimeRejectMsg(workerScript, "getBlackOpNames() failed because you do not currently have access to the Bladeburner API. This is either because you are not currently employed " + - "at the Bladeburner division or because you do not have Source-File 7"); + checkBladeburnerAccess("getBlackOpNames"); + return Player.bladeburner.getBlackOpNamesNetscriptFn(); }, getBlackOpRank: function(name="") { updateDynamicRam("getBlackOpRank", getRamCost("bladeburner", "getBlackOpRank")); - if (Player.bladeburner instanceof Bladeburner && (Player.bitNodeN === 7 || SourceFileFlags[7] > 0)) { - const actionId = Player.bladeburner.getActionIdFromTypeAndName('blackops', name) - if (!actionId) { - return -1; - } - const actionObj = Player.bladeburner.getActionObject(actionId); - if (!actionObj) { - return -1; - } - return actionObj.reqdRank; - } - throw makeRuntimeRejectMsg(workerScript, "getBlackOpRank() failed because you do not currently have access to the Bladeburner API. This is either because you are not currently employed " + - "at the Bladeburner division or because you do not have Source-File 7"); + checkBladeburnerAccess("getBlackOpRank"); + const action = getBladeburnerActionObject("getBlackOpRank", "blackops", name); + return action.reqdRank; }, getGeneralActionNames: function() { updateDynamicRam("getGeneralActionNames", getRamCost("bladeburner", "getGeneralActionNames")); - if (Player.bladeburner instanceof Bladeburner && (Player.bitNodeN === 7 || SourceFileFlags[7] > 0)) { - return Player.bladeburner.getGeneralActionNamesNetscriptFn(); - } - throw makeRuntimeRejectMsg(workerScript, "getGeneralActionNames() failed because you do not currently have access to the Bladeburner API. This is either because you are not currently employed " + - "at the Bladeburner division or because you do not have Source-File 7"); + checkBladeburnerAccess("getGeneralActionNames"); + return Player.bladeburner.getGeneralActionNamesNetscriptFn(); }, getSkillNames: function() { updateDynamicRam("getSkillNames", getRamCost("bladeburner", "getSkillNames")); - if (Player.bladeburner instanceof Bladeburner && (Player.bitNodeN === 7 || SourceFileFlags[7] > 0)) { - return Player.bladeburner.getSkillNamesNetscriptFn(); - } - throw makeRuntimeRejectMsg(workerScript, "getSkillNames() failed because you do not currently have access to the Bladeburner API. This is either because you are not currently employed " + - "at the Bladeburner division or because you do not have Source-File 7"); + checkBladeburnerAccess("getSkillNames"); + return Player.bladeburner.getSkillNamesNetscriptFn(); }, startAction: function(type="", name="") { updateDynamicRam("startAction", getRamCost("bladeburner", "startAction")); - if (Player.bladeburner instanceof Bladeburner && (Player.bitNodeN === 7 || SourceFileFlags[7] > 0)) { - try { - return Player.bladeburner.startActionNetscriptFn(type, name, workerScript); - } catch(e) { - throw makeRuntimeRejectMsg(workerScript, "Bladeburner.startAction() failed with exception: " + e); - } + checkBladeburnerAccess("startAction"); + try { + return Player.bladeburner.startActionNetscriptFn(type, name, workerScript); + } catch(e) { + throw makeRuntimeErrorMsg("bladeburner.startAction", e); } - throw makeRuntimeRejectMsg(workerScript, "startAction() failed because you do not currently have access to the Bladeburner API. This is either because you are not currently employed " + - "at the Bladeburner division or because you do not have Source-File 7"); }, stopBladeburnerAction: function() { updateDynamicRam("stopBladeburnerAction", getRamCost("bladeburner", "stopBladeburnerAction")); - if (Player.bladeburner instanceof Bladeburner && (Player.bitNodeN === 7 || SourceFileFlags[7] > 0)) { - return Player.bladeburner.resetAction(); - } - throw makeRuntimeRejectMsg(workerScript, "stopBladeburnerAction() failed because you do not currently have access to the Bladeburner API. This is either because you are not currently employed " + - "at the Bladeburner division or because you do not have Source-File 7"); + checkBladeburnerAccess("stopBladeburnerAction"); + return Player.bladeburner.resetAction(); }, getCurrentAction: function() { updateDynamicRam("getCurrentAction", getRamCost("bladeburner", "getCurrentAction")); - if (Player.bladeburner instanceof Bladeburner && (Player.bitNodeN === 7 || SourceFileFlags[7] > 0)) { - return Player.bladeburner.getTypeAndNameFromActionId(Player.bladeburner.action); - } - throw makeRuntimeRejectMsg(workerScript, "getCurrentAction() failed because you do not currently have access to the Bladeburner API. This is either because you are not currently employed " + - "at the Bladeburner division or because you do not have Source-File 7"); + checkBladeburnerAccess("getCurrentAction"); + return Player.bladeburner.getTypeAndNameFromActionId(Player.bladeburner.action); }, getActionTime: function(type="", name="") { updateDynamicRam("getActionTime", getRamCost("bladeburner", "getActionTime")); - if (Player.bladeburner instanceof Bladeburner && (Player.bitNodeN === 7 || SourceFileFlags[7] > 0)) { - try { - return Player.bladeburner.getActionTimeNetscriptFn(type, name, workerScript); - } catch(e) { - throw makeRuntimeRejectMsg(workerScript, "Bladeburner.getActionTime() failed with exception: " + e); - } + checkBladeburnerAccess("getActionTime"); + try { + return Player.bladeburner.getActionTimeNetscriptFn(type, name, workerScript); + } catch(e) { + throw makeRuntimeErrorMsg("bladeburner.getActionTime", e); } - throw makeRuntimeRejectMsg(workerScript, "getActionTime() failed because you do not currently have access to the Bladeburner API. This is either because you are not currently employed " + - "at the Bladeburner division or because you do not have Source-File 7"); }, getActionEstimatedSuccessChance: function(type="", name="") { updateDynamicRam("getActionEstimatedSuccessChance", getRamCost("bladeburner", "getActionEstimatedSuccessChance")); - if (Player.bladeburner instanceof Bladeburner && (Player.bitNodeN === 7 || SourceFileFlags[7] > 0)) { - try { - return Player.bladeburner.getActionEstimatedSuccessChanceNetscriptFn(type, name, workerScript); - } catch(e) { - throw makeRuntimeRejectMsg(workerScript, "Bladeburner.getActionEstimatedSuccessChance() failed with exception: " + e); - } + checkBladeburnerAccess("getActionEstimatedSuccessChance"); + try { + return Player.bladeburner.getActionEstimatedSuccessChanceNetscriptFn(type, name, workerScript); + } catch(e) { + throw makeRuntimeErrorMsg("bladeburner.getActionEstimatedSuccessChance", e); } - throw makeRuntimeRejectMsg(workerScript, "getActionEstimatedSuccessChance() failed because you do not currently have access to the Bladeburner API. This is either because you are not currently employed " + - "at the Bladeburner division or because you do not have Source-File 7"); }, getActionRepGain: function(type="", name="", level) { updateDynamicRam("getActionRepGain", getRamCost("bladeburner", "getActionRepGain")); - checkBladeburnerAccess(workerScript, "getActionRepGain"); - - try { - var errorLogText = unknownBladeburnerActionErrorMessage("getActionAutolevel", type, name); - const actionId = Player.bladeburner.getActionIdFromTypeAndName(type, name); - if (actionId == null) { - workerScript.log(errorLogText); - return -1; - } - const actionObj = Player.bladeburner.getActionObject(actionId); - if (actionObj == null) { - workerScript.log(errorLogText); - return -1; - } - var rewardMultiplier; - if (level == null || isNaN(level)) { - rewardMultiplier = Math.pow(actionObj.rewardFac, actionObj.level - 1); - } else { - rewardMultiplier = Math.pow(actionObj.rewardFac, level - 1); - } - - return actionObj.rankGain * rewardMultiplier * BitNodeMultipliers.BladeburnerRank; - } catch(err) { - throw makeRuntimeRejectMsg(workerScript, unknownBladeburnerExceptionMessage("getActionAutolevel", err)); + checkBladeburnerAccess("getActionRepGain"); + const action = getBladeburnerActionObject("getActionRepGain", type, name); + let rewardMultiplier; + if (level == null || isNaN(level)) { + rewardMultiplier = Math.pow(action.rewardFac, action.level - 1); + } else { + rewardMultiplier = Math.pow(action.rewardFac, level - 1); } + + return action.rankGain * rewardMultiplier * BitNodeMultipliers.BladeburnerRank; }, getActionCountRemaining: function(type="", name="") { updateDynamicRam("getActionCountRemaining", getRamCost("bladeburner", "getActionCountRemaining")); - if (Player.bladeburner instanceof Bladeburner && (Player.bitNodeN === 7 || SourceFileFlags[7] > 0)) { - try { - return Player.bladeburner.getActionCountRemainingNetscriptFn(type, name, workerScript); - } catch(e) { - throw makeRuntimeRejectMsg(workerScript, "Bladeburner.getActionCountRemaining() failed with exception: " + e); - } + checkBladeburnerAccess("getActionCountRemaining"); + try { + return Player.bladeburner.getActionCountRemainingNetscriptFn(type, name, workerScript); + } catch(e) { + throw makeRuntimeErrorMsg("bladeburner.getActionCountRemaining", e); } - throw makeRuntimeRejectMsg(workerScript, "getActionCountRemaining() failed because you do not currently have access to the Bladeburner API. This is either because you are not currently employed " + - "at the Bladeburner division or because you do not have Source-File 7"); }, getActionMaxLevel: function(type="", name="") { updateDynamicRam("getActionMaxLevel", getRamCost("bladeburner", "getActionMaxLevel")); - checkBladeburnerAccess(workerScript, "getActionMaxLevel"); - - try { - var errorLogText = unknownBladeburnerActionErrorMessage("getActionMaxLevel", type, name); - const actionId = Player.bladeburner.getActionIdFromTypeAndName(type, name); - if (actionId == null) { - workerScript.log(errorLogText); - return -1; - } - const actionObj = Player.bladeburner.getActionObject(actionId); - if (actionObj == null) { - workerScript.log(errorLogText); - return -1; - } - return actionObj.maxLevel; - } catch(err) { - throw makeRuntimeRejectMsg(workerScript, unknownBladeburnerExceptionMessage("getActionMaxLevel", err)); - } + checkBladeburnerAccess("getActionMaxLevel"); + const action = getBladeburnerActionObject("getActionMaxLevel", type, name); + return action.maxLevel; }, getActionCurrentLevel: function(type="", name="") { updateDynamicRam("getActionCurrentLevel", getRamCost("bladeburner", "getActionCurrentLevel")); - checkBladeburnerAccess(workerScript, "getActionCurrentLevel"); - - try { - var errorLogText = unknownBladeburnerActionErrorMessage("getActionCurrentLevel", type, name); - const actionId = Player.bladeburner.getActionIdFromTypeAndName(type, name); - if (actionId == null) { - workerScript.log(errorLogText); - return -1; - } - const actionObj = Player.bladeburner.getActionObject(actionId); - if (actionObj == null) { - workerScript.log(errorLogText); - return -1; - } - return actionObj.level; - } catch(err) { - throw makeRuntimeRejectMsg(workerScript, unknownBladeburnerExceptionMessage("getActionCurrentLevel", err)); - } + checkBladeburnerAccess("getActionCurrentLevel"); + const action = getBladeburnerActionObject("getActionCurrentLevel", type, name); + return action.level; }, getActionAutolevel: function(type="", name="") { updateDynamicRam("getActionAutolevel", getRamCost("bladeburner", "getActionAutolevel")); - checkBladeburnerAccess(workerScript, "getActionAutolevel"); - - try { - var errorLogText = unknownBladeburnerActionErrorMessage("getActionAutolevel", type, name); - const actionId = Player.bladeburner.getActionIdFromTypeAndName(type, name); - if (actionId == null) { - workerScript.log(errorLogText); - return false; - } - const actionObj = Player.bladeburner.getActionObject(actionId); - if (actionObj == null) { - workerScript.log(errorLogText); - return false; - } - return actionObj.autoLevel; - } catch(err) { - throw makeRuntimeRejectMsg(workerScript, unknownBladeburnerExceptionMessage("getActionAutolevel", err)); - } + checkBladeburnerAccess("getActionAutolevel"); + const action = getBladeburnerActionObject("getActionCurrentLevel", type, name); + return action.autoLevel; }, setActionAutolevel: function(type="", name="", autoLevel=true) { updateDynamicRam("setActionAutolevel", getRamCost("bladeburner", "setActionAutolevel")); - checkBladeburnerAccess(workerScript, "setActionAutolevel"); - - try { - var errorLogText = unknownBladeburnerActionErrorMessage("setActionAutolevel", type, name); - const actionId = Player.bladeburner.getActionIdFromTypeAndName(type, name); - if (actionId == null) { - workerScript.log(errorLogText); - return; - } - const actionObj = Player.bladeburner.getActionObject(actionId); - if (actionObj == null) { - workerScript.log(errorLogText); - return; - } - actionObj.autoLevel = autoLevel; - } catch(err) { - throw makeRuntimeRejectMsg(workerScript, unknownBladeburnerExceptionMessage("setActionAutolevel", err)); - } + checkBladeburnerAccess("setActionAutolevel"); + const action = getBladeburnerActionObject("getActionCurrentLevel", type, name); + action.autoLevel = autoLevel; }, setActionLevel: function(type="", name="", level=1) { updateDynamicRam("setActionLevel", getRamCost("bladeburner", "setActionLevel")); - checkBladeburnerAccess(workerScript, "setActionLevel"); - - try { - var errorLogText = unknownBladeburnerActionErrorMessage("setActionLevel", type, name); - const actionId = Player.bladeburner.getActionIdFromTypeAndName(type, name); - if (actionId == null) { - workerScript.log(errorLogText); - return; - } - const actionObj = Player.bladeburner.getActionObject(actionId); - if (actionObj == null) { - workerScript.log(errorLogText); - return; - } - if(level > actionObj.maxLevel) { - workerScript.log(`ERROR: bladeburner.${setActionLevel}() failed because level exceeds max level for given action.`); - return; - } - if(level < 1) { - workerScript.log(`ERROR: bladeburner.${setActionLevel}() failed because level is below 1.`); - return; - } - actionObj.level = level; - } catch(err) { - throw makeRuntimeRejectMsg(workerScript, unknownBladeburnerExceptionMessage("setActionLevel", err)); + checkBladeburnerAccess("setActionLevel"); + const action = getBladeburnerActionObject("setActionLevel", type, name); + if(level < 1 || level > action.maxLevel) { + throw makeRuntimeErrorMsg("bladeburner.setActionLevel", `Level must be between 1 and ${action.maxLevel}, is ${level}`) } + actionObj.level = level; }, getRank: function() { updateDynamicRam("getRank", getRamCost("bladeburner", "getRank")); - if (Player.bladeburner instanceof Bladeburner && (Player.bitNodeN === 7 || SourceFileFlags[7] > 0)) { - return Player.bladeburner.rank; - } - throw makeRuntimeRejectMsg(workerScript, "getRank() failed because you do not currently have access to the Bladeburner API. This is either because you are not currently employed " + - "at the Bladeburner division or because you do not have Source-File 7"); + checkBladeburnerAccess("getRank"); + return Player.bladeburner.rank; }, getSkillPoints: function() { updateDynamicRam("getSkillPoints", getRamCost("bladeburner", "getSkillPoints")); - if (Player.bladeburner instanceof Bladeburner && (Player.bitNodeN === 7 || SourceFileFlags[7] > 0)) { - return Player.bladeburner.skillPoints; - } - throw makeRuntimeRejectMsg(workerScript, "getSkillPoints() failed because you do not currently have access to the Bladeburner API. This is either because you are not currently employed " + - "at the Bladeburner division or because you do not have Source-File 7"); + checkBladeburnerAccess("getSkillPoints"); + return Player.bladeburner.skillPoints; }, getSkillLevel: function(skillName="") { updateDynamicRam("getSkillLevel", getRamCost("bladeburner", "getSkillLevel")); - if (Player.bladeburner instanceof Bladeburner && (Player.bitNodeN === 7 || SourceFileFlags[7] > 0)) { - try { - return Player.bladeburner.getSkillLevelNetscriptFn(skillName, workerScript); - } catch(e) { - throw makeRuntimeRejectMsg(workerScript, "Bladeburner.getSkillLevel() failed with exception: " + e); - } + checkBladeburnerAccess("getSkillLevel"); + try { + return Player.bladeburner.getSkillLevelNetscriptFn(skillName, workerScript); + } catch(e) { + throw makeRuntimeErrorMsg("bladeburner.getSkillLevel", e); } - throw makeRuntimeRejectMsg(workerScript, "getSkillLevel() failed because you do not currently have access to the Bladeburner API. This is either because you are not currently employed " + - "at the Bladeburner division or because you do not have Source-File 7"); }, getSkillUpgradeCost: function(skillName="") { updateDynamicRam("getSkillUpgradeCost", getRamCost("bladeburner", "getSkillUpgradeCost")); - if (Player.bladeburner instanceof Bladeburner && (Player.bitNodeN === 7 || SourceFileFlags[7] > 0)) { - try { - return Player.bladeburner.getSkillUpgradeCostNetscriptFn(skillName, workerScript); - } catch(e) { - throw makeRuntimeRejectMsg(workerScript, "Bladeburner.getSkillUpgradeCost() failed with exception: " + e); - } + checkBladeburnerAccess("getSkillUpgradeCost"); + try { + return Player.bladeburner.getSkillUpgradeCostNetscriptFn(skillName, workerScript); + } catch(e) { + throw makeRuntimeErrorMsg("bladeburner.getSkillUpgradeCost", e); } - throw makeRuntimeRejectMsg(workerScript, "getSkillUpgradeCost() failed because you do not currently have access to the Bladeburner API. This is either because you are not currently employed " + - "at the Bladeburner division or because you do not have Source-File 7"); }, upgradeSkill: function(skillName) { updateDynamicRam("upgradeSkill", getRamCost("bladeburner", "upgradeSkill")); - if (Player.bladeburner instanceof Bladeburner && (Player.bitNodeN === 7 || SourceFileFlags[7] > 0)) { - try { - return Player.bladeburner.upgradeSkillNetscriptFn(skillName, workerScript); - } catch(e) { - throw makeRuntimeRejectMsg(workerScript, "Bladeburner.upgradeSkill() failed with exception: " + e); - } + checkBladeburnerAccess("upgradeSkill"); + try { + return Player.bladeburner.upgradeSkillNetscriptFn(skillName, workerScript); + } catch(e) { + throw makeRuntimeErrorMsg("bladeburner.upgradeSkill", e); } - throw makeRuntimeRejectMsg(workerScript, "upgradeSkill() failed because you do not currently have access to the Bladeburner API. This is either because you are not currently employed " + - "at the Bladeburner division or because you do not have Source-File 7"); }, getTeamSize: function(type="", name="") { updateDynamicRam("getTeamSize", getRamCost("bladeburner", "getTeamSize")); - if (Player.bladeburner instanceof Bladeburner && (Player.bitNodeN === 7 || SourceFileFlags[7] > 0)) { - try { - return Player.bladeburner.getTeamSizeNetscriptFn(type, name, workerScript); - } catch(e) { - throw makeRuntimeRejectMsg(workerScript, "Bladeburner.getTeamSize() failed with exception: " + e); - } + checkBladeburnerAccess("getTeamSize"); + try { + return Player.bladeburner.getTeamSizeNetscriptFn(type, name, workerScript); + } catch(e) { + throw makeRuntimeErrorMsg("bladeburner.getTeamSize", e); } - throw makeRuntimeRejectMsg(workerScript, "getTeamSize() failed because you do not currently have access to the Bladeburner API. This is either because you are not currently employed " + - "at the Bladeburner division or because you do not have Source-File 7"); }, setTeamSize: function(type="", name="", size) { updateDynamicRam("setTeamSize",getRamCost("bladeburner", "setTeamSize")); - if (Player.bladeburner instanceof Bladeburner && (Player.bitNodeN === 7 || SourceFileFlags[7] > 0)) { - try { - return Player.bladeburner.setTeamSizeNetscriptFn(type, name, size, workerScript); - } catch(e) { - throw makeRuntimeRejectMsg(workerScript, "Bladeburner.setTeamSize() failed with exception: " + e); - } + checkBladeburnerAccess("setTeamSize"); + try { + return Player.bladeburner.setTeamSizeNetscriptFn(type, name, size, workerScript); + } catch(e) { + throw makeRuntimeErrorMsg("bladeburner.setTeamSize", e); } - throw makeRuntimeRejectMsg(workerScript, "setTeamSize() failed because you do not currently have access to the Bladeburner API. This is either because you are not currently employed " + - "at the Bladeburner division or because you do not have Source-File 7"); }, getCityEstimatedPopulation: function(cityName) { updateDynamicRam("getCityEstimatedPopulation", getRamCost("bladeburner", "getCityEstimatedPopulation")); - if (Player.bladeburner instanceof Bladeburner && (Player.bitNodeN === 7 || SourceFileFlags[7] > 0)) { - try { - return Player.bladeburner.getCityEstimatedPopulationNetscriptFn(cityName, workerScript); - } catch(e) { - throw makeRuntimeRejectMsg(workerScript, "Bladeburner.getCityEstimatedPopulation() failed with exception: " + e); - } - } - throw makeRuntimeRejectMsg(workerScript, "getCityEstimatedPopulation() failed because you do not currently have access to the Bladeburner API. This is either because you are not currently employed " + - "at the Bladeburner division or because you do not have Source-File 7"); + checkBladeburnerAccess("getCityEstimatedPopulation"); + checkBladeburnerCity("getCityEstimatedPopulation", cityName); + return Player.bladeburner.cities[cityName].popEst; }, getCityEstimatedCommunities: function(cityName) { updateDynamicRam("getCityEstimatedCommunities", getRamCost("bladeburner", "getCityEstimatedCommunities")); - if (Player.bladeburner instanceof Bladeburner && (Player.bitNodeN === 7 || SourceFileFlags[7] > 0)) { - try { - return Player.bladeburner.getCityEstimatedCommunitiesNetscriptFn(cityName, workerScript); - } catch(e) { - throw makeRuntimeRejectMsg(workerScript, "Bladeburner.getCityEstimatedCommunities() failed with exception: " + e); - } - } - throw makeRuntimeRejectMsg(workerScript, "getCityEstimatedCommunities() failed because you do not currently have access to the Bladeburner API. This is either because you are not currently employed " + - "at the Bladeburner division or because you do not have Source-File 7"); + checkBladeburnerAccess("getCityEstimatedCommunities"); + checkBladeburnerCity("getCityEstimatedCommunities", cityName); + return Player.bladeburner.cities[cityName].commsEst; }, getCityChaos: function(cityName) { updateDynamicRam("getCityChaos", getRamCost("bladeburner", "getCityChaos")); - if (Player.bladeburner instanceof Bladeburner && (Player.bitNodeN === 7 || SourceFileFlags[7] > 0)) { - try { - return Player.bladeburner.getCityChaosNetscriptFn(cityName, workerScript); - } catch(e) { - throw makeRuntimeRejectMsg(workerScript, "Bladeburner.getCityChaos() failed with exception: " + e); - } - } - throw makeRuntimeRejectMsg(workerScript, "getCityChaos() failed because you do not currently have access to the Bladeburner API. This is either because you are not currently employed " + - "at the Bladeburner division or because you do not have Source-File 7"); + checkBladeburnerAccess("getCityChaos"); + checkBladeburnerCity("getCityChaos", cityName); + return Player.bladeburner.cities[cityName].chaos; }, getCity: function() { updateDynamicRam("getCity", getRamCost("bladeburner", "getCity")); - if (Player.bladeburner instanceof Bladeburner && (Player.bitNodeN === 7 || SourceFileFlags[7] > 0)) { - try { - return Player.bladeburner.city; - } catch(e) { - throw makeRuntimeRejectMsg(workerScript, "Bladeburner.getCity() failed with exception: " + e); - } - } - throw makeRuntimeRejectMsg(workerScript, "getCity() failed because you do not currently have access to the Bladeburner API. This is either because you are not currently employed " + - "at the Bladeburner division or because you do not have Source-File 7"); + checkBladeburnerAccess("getCityChaos"); + return Player.bladeburner.city; }, switchCity: function(cityName) { updateDynamicRam("switchCity", getRamCost("bladeburner", "switchCity")); - if (Player.bladeburner instanceof Bladeburner && (Player.bitNodeN === 7 || SourceFileFlags[7] > 0)) { - try { - return Player.bladeburner.switchCityNetscriptFn(cityName, workerScript); - } catch(e) { - throw makeRuntimeRejectMsg(workerScript, "Bladeburner.switchCity() failed with exception: " + e); - } - } - throw makeRuntimeRejectMsg(workerScript, "switchCity() failed because you do not currently have access to the Bladeburner API. This is either because you are not currently employed " + - "at the Bladeburner division or because you do not have Source-File 7"); + checkBladeburnerAccess("switchCity"); + checkBladeburnerCity("switchCity", cityName); + return Player.bladeburner.city = cityName; }, getStamina: function() { updateDynamicRam("getStamina", getRamCost("bladeburner", "getStamina")); - if (Player.bladeburner instanceof Bladeburner && (Player.bitNodeN === 7 || SourceFileFlags[7] > 0)) { - return [Player.bladeburner.stamina, Player.bladeburner.maxStamina]; - } - throw makeRuntimeRejectMsg(workerScript, "getStamina() failed because you do not currently have access to the Bladeburner API. This is either because you are not currently employed " + - "at the Bladeburner division or because you do not have Source-File 7"); + checkBladeburnerAccess("getStamina"); + return [Player.bladeburner.stamina, Player.bladeburner.maxStamina]; }, joinBladeburnerFaction: function() { updateDynamicRam("joinBladeburnerFaction", getRamCost("bladeburner", "joinBladeburnerFaction")); - if (Player.bladeburner instanceof Bladeburner && (Player.bitNodeN === 7 || SourceFileFlags[7] > 0)) { - return Player.bladeburner.joinBladeburnerFactionNetscriptFn(workerScript); - } - throw makeRuntimeRejectMsg(workerScript, "joinBladeburnerFaction() failed because you do not currently have access to the Bladeburner API. This is either because you are not currently employed " + - "at the Bladeburner division or because you do not have Source-File 7"); + checkBladeburnerAccess("joinBladeburnerFaction"); + return Player.bladeburner.joinBladeburnerFactionNetscriptFn(workerScript); }, joinBladeburnerDivision: function() { updateDynamicRam("joinBladeburnerDivision", getRamCost("bladeburner", "joinBladeburnerDivision")); + checkBladeburnerAccess("joinBladeburnerDivision"); if ((Player.bitNodeN === 7 || SourceFileFlags[7] > 0)) { if (Player.bitNodeN === 8) { return false; } if (Player.bladeburner instanceof Bladeburner) { @@ -4321,7 +3684,7 @@ function NetscriptFunctions(workerScript) { } else if (Player.strength >= 100 && Player.defense >= 100 && Player.dexterity >= 100 && Player.agility >= 100) { Player.bladeburner = new Bladeburner({new:true}); - workerScript.log("You have been accepted into the Bladeburner division"); + workerScript.log("joinBladeburnerDivision", "You have been accepted into the Bladeburner division"); const worldHeader = document.getElementById("world-menu-header"); if (worldHeader instanceof HTMLElement) { @@ -4330,19 +3693,15 @@ function NetscriptFunctions(workerScript) { return true; } else { - workerScript.log("You do not meet the requirements for joining the Bladeburner division"); + workerScript.log("joinBladeburnerDivision", "You do not meet the requirements for joining the Bladeburner division"); return false; } } - throw makeRuntimeRejectMsg(workerScript, "joinBladeburnerDivision() failed because you do not currently have access to the Bladeburner API. This is either because you are not currently employed " + - "at the Bladeburner division or because you do not have Source-File 7"); }, getBonusTime: function() { - if ((Player.bitNodeN === 7 || SourceFileFlags[7] > 0)) { - return Math.round(Player.bladeburner.storedCycles / 5); - } - throw makeRuntimeRejectMsg(workerScript, "getBonusTime() failed because you do not currently have access to the Bladeburner API. This is either because you are not currently employed " + - "at the Bladeburner division or because you do not have Source-File 7"); + updateDynamicRam("getBonusTime", getRamCost("bladeburner", "getBonusTime")); + checkBladeburnerAccess("getBonusTime"); + return Math.round(Player.bladeburner.storedCycles / 5); } }, // End Bladeburner @@ -4350,11 +3709,7 @@ function NetscriptFunctions(workerScript) { codingcontract: { attempt: function(answer, fn, ip=workerScript.serverIp, { returnReward } = {}) { updateDynamicRam("attempt", getRamCost("codingcontract", "attempt")); - const contract = getCodingContract(fn, ip); - if (contract == null) { - workerScript.log(`ERROR: codingcontract.getData() failed because it could find the specified contract ${fn} on server ${ip}`); - return false; - } + const contract = getCodingContract("attempt", ip, fn); // Convert answer to string. If the answer is a 2D array, then we have to // manually add brackets for the inner arrays @@ -4372,16 +3727,16 @@ function NetscriptFunctions(workerScript) { const serv = safeGetServer(ip, "codingcontract.attempt"); if (contract.isSolution(answer)) { const reward = Player.gainCodingContractReward(contract.reward, contract.getDifficulty()); - workerScript.log(`Successfully completed Coding Contract ${fn}. Reward: ${reward}`); + workerScript.log("attempt", `Successfully completed Coding Contract '${fn}'. Reward: ${reward}`); serv.removeContract(fn); return returnReward ? reward : true; } else { ++contract.tries; if (contract.tries >= contract.getMaxNumTries()) { - workerScript.log(`Coding Contract ${fn} failed. Contract is now self-destructing`); + workerScript.log("attempt", `Coding Contract attempt '${fn}' failed. Contract is now self-destructing`); serv.removeContract(fn); } else { - workerScript.log(`Coding Contract ${fn} failed. ${contract.getMaxNumTries() - contract.tries} attempts remaining`); + workerScript.log("attempt", `Coding Contract attempt '${fn}' failed. ${contract.getMaxNumTries() - contract.tries} attempts remaining.`); } return returnReward ? "" : false; @@ -4389,21 +3744,13 @@ function NetscriptFunctions(workerScript) { }, getContractType: function(fn, ip=workerScript.serverIp) { updateDynamicRam("getContractType", getRamCost("codingcontract", "getContractType")); - let contract = getCodingContract(fn, ip); - if (contract == null) { - workerScript.log(`ERROR: codingcontract.getData() failed because it could find the specified contract ${fn} on server ${ip}`); - return null; - } + const contract = getCodingContract("getContractType", ip, fn); return contract.getType(); }, getData: function(fn, ip=workerScript.serverIp) { updateDynamicRam("getData", getRamCost("codingcontract", "getData")); - let contract = getCodingContract(fn, ip); - if (contract == null) { - workerScript.log(`ERROR: codingcontract.getData() failed because it could find the specified contract ${fn} on server ${ip}`); - return null; - } - let data = contract.getData(); + const contract = getCodingContract("getData", ip, fn); + const data = contract.getData(); if (data.constructor === Array) { // For two dimensional arrays, we have to copy the internal arrays using // slice() as well. As of right now, no contract has arrays that have @@ -4422,20 +3769,12 @@ function NetscriptFunctions(workerScript) { }, getDescription: function(fn, ip=workerScript.serverIp) { updateDynamicRam("getDescription", getRamCost("codingcontract", "getDescription")); - var contract = getCodingContract(fn, ip); - if (contract == null) { - workerScript.log(`ERROR: codingcontract.getDescription() failed because it could find the specified contract ${fn} on server ${ip}`); - return ""; - } + const contract = getCodingContract("getDescription", ip, fn); return contract.getDescription(); }, getNumTriesRemaining: function(fn, ip=workerScript.serverIp) { updateDynamicRam("getNumTriesRemaining", getRamCost("codingcontract", "getNumTriesRemaining")); - var contract = getCodingContract(fn, ip); - if (contract == null) { - workerScript.log(`ERROR: codingcontract.getNumTriesRemaining() failed because it could find the specified contract ${fn} on server ${ip}`); - return -1; - } + const contract = getCodingContract("getNumTriesRemaining", ip, fn); return contract.getMaxNumTries() - contract.tries; }, }, // End coding contracts @@ -4443,137 +3782,83 @@ function NetscriptFunctions(workerScript) { // Duplicate Sleeve API sleeve: { getNumSleeves: function() { - if (Player.bitNodeN !== 10 && !SourceFileFlags[10]) { - throw makeRuntimeRejectMsg(workerScript, "getNumSleeves() failed because you do not currently have access to the Sleeve API. This is either because you are not in BitNode-10 or because you do not have Source-File 10"); - } updateDynamicRam("getNumSleeves", getRamCost("sleeve", "getNumSleeves")); + checkSleeveAPIAccess("getNumSleeves"); return Player.sleeves.length; }, setToShockRecovery: function(sleeveNumber=0) { - if (Player.bitNodeN !== 10 && !SourceFileFlags[10]) { - throw makeRuntimeRejectMsg(workerScript, "setToShockRecovery() failed because you do not currently have access to the Sleeve API. This is either because you are not in BitNode-10 or because you do not have Source-File 10"); - } updateDynamicRam("setToShockRecovery", getRamCost("sleeve", "setToShockRecovery")); - if (sleeveNumber >= Player.sleeves.length || sleeveNumber < 0) { - workerScript.log(`ERROR: sleeve.setToShockRecovery(${sleeveNumber}) failed because it is an invalid sleeve number.`); - return false; - } - + checkSleeveAPIAccess("setToShockRecovery"); + checkSleeveNumber("setToShockRecovery", sleeveNumber); return Player.sleeves[sleeveNumber].shockRecovery(Player); }, setToSynchronize: function(sleeveNumber=0) { - if (Player.bitNodeN !== 10 && !SourceFileFlags[10]) { - throw makeRuntimeRejectMsg(workerScript, "setToSynchronize() failed because you do not currently have access to the Sleeve API. This is either because you are not in BitNode-10 or because you do not have Source-File 10"); - } updateDynamicRam("setToSynchronize", getRamCost("sleeve", "setToSynchronize")); - if (sleeveNumber >= Player.sleeves.length || sleeveNumber < 0) { - workerScript.log(`ERROR: sleeve.setToSynchronize(${sleeveNumber}) failed because it is an invalid sleeve number.`); - return false; - } - + checkSleeveAPIAccess("setToSynchronize"); + checkSleeveNumber("setToSynchronize", sleeveNumber); return Player.sleeves[sleeveNumber].synchronize(Player); }, setToCommitCrime: function(sleeveNumber=0, crimeName="") { - if (Player.bitNodeN !== 10 && !SourceFileFlags[10]) { - throw makeRuntimeRejectMsg(workerScript, "setToCommitCrime() failed because you do not currently have access to the Sleeve API. This is either because you are not in BitNode-10 or because you do not have Source-File 10"); - } updateDynamicRam("setToCommitCrime", getRamCost("sleeve", "setToCommitCrime")); - if (sleeveNumber >= Player.sleeves.length || sleeveNumber < 0) { - workerScript.log(`ERROR: sleeve.setToCommitCrime(${sleeveNumber}) failed because it is an invalid sleeve number.`); - return false; - } - + checkSleeveAPIAccess("setToCommitCrime"); + checkSleeveNumber("setToCommitCrime", sleeveNumber); return Player.sleeves[sleeveNumber].commitCrime(Player, crimeName); }, setToUniversityCourse: function(sleeveNumber=0, universityName="", className="") { - if (Player.bitNodeN !== 10 && !SourceFileFlags[10]) { - throw makeRuntimeRejectMsg(workerScript, "setToUniversityCourse() failed because you do not currently have access to the Sleeve API. This is either because you are not in BitNode-10 or because you do not have Source-File 10"); - } updateDynamicRam("setToUniversityCourse", getRamCost("sleeve", "setToUniversityCourse")); - if (sleeveNumber >= Player.sleeves.length || sleeveNumber < 0) { - workerScript.log(`ERROR: sleeve.setToUniversityCourse(${sleeveNumber}) failed because it is an invalid sleeve number.`); - return false; - } - + checkSleeveAPIAccess("setToUniversityCourse"); + checkSleeveNumber("setToUniversityCourse", sleeveNumber); return Player.sleeves[sleeveNumber].takeUniversityCourse(Player, universityName, className); }, travel: function(sleeveNumber=0, cityName="") { - if (Player.bitNodeN !== 10 && !SourceFileFlags[10]) { - throw makeRuntimeRejectMsg(workerScript, "travel() failed because you do not currently have access to the Sleeve API. This is either because you are not in BitNode-10 or because you do not have Source-File 10"); - } updateDynamicRam("travel", getRamCost("sleeve", "travel")); - if (sleeveNumber >= Player.sleeves.length || sleeveNumber < 0) { - workerScript.log(`ERROR: sleeve.travel(${sleeveNumber}) failed because it is an invalid sleeve number.`); - return false; - } - + checkSleeveAPIAccess("travel"); + checkSleeveNumber("travel", sleeveNumber); return Player.sleeves[sleeveNumber].travel(Player, cityName); }, setToCompanyWork: function(sleeveNumber=0, companyName="") { - if (Player.bitNodeN !== 10 && !SourceFileFlags[10]) { - throw makeRuntimeRejectMsg(workerScript, "setToCompanyWork() failed because you do not currently have access to the Sleeve API. This is either because you are not in BitNode-10 or because you do not have Source-File 10"); - } updateDynamicRam("setToCompanyWork", getRamCost("sleeve", "setToCompanyWork")); - if (sleeveNumber >= Player.sleeves.length || sleeveNumber < 0) { - workerScript.log(`ERROR: sleeve.setToCompanyWork(${sleeveNumber}) failed because it is an invalid sleeve number.`); - return false; - } + checkSleeveAPIAccess("setToCompanyWork"); + checkSleeveNumber("setToCompanyWork", sleeveNumber); // Cannot work at the same company that another sleeve is working at for (let i = 0; i < Player.sleeves.length; ++i) { if (i === sleeveNumber) { continue; } const other = Player.sleeves[i]; if (other.currentTask === SleeveTaskType.Company && other.currentTaskLocation === companyName) { - workerScript.log(`ERROR: sleeve.setToCompanyWork() failed for Sleeve ${sleeveNumber} because Sleeve ${i} is doing the same task`); - return false; + throw makeRuntimeErrorMsg("sleeve.setToFactionWork", `Sleeve ${sleeveNumber} cannot work for company ${companyName} because Sleeve ${i} is already working for them.`) } } return Player.sleeves[sleeveNumber].workForCompany(Player, companyName); }, setToFactionWork: function(sleeveNumber=0, factionName="", workType="") { - if (Player.bitNodeN !== 10 && !SourceFileFlags[10]) { - throw makeRuntimeRejectMsg(workerScript, "setToFactionWork() failed because you do not currently have access to the Sleeve API. This is either because you are not in BitNode-10 or because you do not have Source-File 10"); - } updateDynamicRam("setToFactionWork", getRamCost("sleeve", "setToFactionWork")); - if (sleeveNumber >= Player.sleeves.length || sleeveNumber < 0) { - workerScript.log(`ERROR: sleeve.setToFactionWork(${sleeveNumber}) failed because it is an invalid sleeve number.`); - return false; - } + checkSleeveAPIAccess("setToFactionWork"); + checkSleeveNumber("setToFactionWork", sleeveNumber); // Cannot work at the same faction that another sleeve is working at for (let i = 0; i < Player.sleeves.length; ++i) { if (i === sleeveNumber) { continue; } const other = Player.sleeves[i]; if (other.currentTask === SleeveTaskType.Faction && other.currentTaskLocation === factionName) { - workerScript.log(`ERROR: sleeve.setToFactionWork() failed for Sleeve ${sleeveNumber} because Sleeve ${i} is doing the same task`); - return false; + throw makeRuntimeErrorMsg("sleeve.setToFactionWork", `Sleeve ${sleeveNumber} cannot work for faction ${factionName} because Sleeve ${i} is already working for them.`) } } return Player.sleeves[sleeveNumber].workForFaction(Player, factionName, workType); }, setToGymWorkout: function(sleeveNumber=0, gymName="", stat="") { - if (Player.bitNodeN !== 10 && !SourceFileFlags[10]) { - throw makeRuntimeRejectMsg(workerScript, "setToGymWorkout() failed because you do not currently have access to the Sleeve API. This is either because you are not in BitNode-10 or because you do not have Source-File 10"); - } updateDynamicRam("setToGymWorkout", getRamCost("sleeve", "setToGymWorkout")); - if (sleeveNumber >= Player.sleeves.length || sleeveNumber < 0) { - workerScript.log(`ERROR: sleeve.setToGymWorkout(${sleeveNumber}) failed because it is an invalid sleeve number.`); - return false; - } + checkSleeveAPIAccess("setToGymWorkout"); + checkSleeveNumber("setToGymWorkout", sleeveNumber); return Player.sleeves[sleeveNumber].workoutAtGym(Player, gymName, stat); }, getSleeveStats: function(sleeveNumber=0) { - if (Player.bitNodeN !== 10 && !SourceFileFlags[10]) { - throw makeRuntimeRejectMsg(workerScript, "getStats() failed because you do not currently have access to the Sleeve API. This is either because you are not in BitNode-10 or because you do not have Source-File 10"); - } updateDynamicRam("getSleeveStats", getRamCost("sleeve", "getSleeveStats")); - if (sleeveNumber >= Player.sleeves.length || sleeveNumber < 0) { - workerScript.log(`ERROR: sleeve.workoutAtGym(${sleeveNumber}) failed because it is an invalid sleeve number.`); - return false; - } + checkSleeveAPIAccess("getSleeveStats"); + checkSleeveNumber("getSleeveStats", sleeveNumber); const sl = Player.sleeves[sleeveNumber]; return { @@ -4588,14 +3873,9 @@ function NetscriptFunctions(workerScript) { }; }, getTask: function(sleeveNumber=0) { - if (Player.bitNodeN !== 10 && !SourceFileFlags[10]) { - throw makeRuntimeRejectMsg(workerScript, "getTask() failed because you do not currently have access to the Sleeve API. This is either because you are not in BitNode-10 or because you do not have Source-File 10"); - } updateDynamicRam("getTask", getRamCost("sleeve", "getTask")); - if (sleeveNumber >= Player.sleeves.length || sleeveNumber < 0) { - workerScript.log(`ERROR: sleeve.getTask(${sleeveNumber}) failed because it is an invalid sleeve number.`); - return false; - } + checkSleeveAPIAccess("getTask"); + checkSleeveNumber("getTask", sleeveNumber); const sl = Player.sleeves[sleeveNumber]; return { @@ -4607,14 +3887,9 @@ function NetscriptFunctions(workerScript) { }; }, getInformation: function(sleeveNumber=0) { - if (Player.bitNodeN !== 10 && !SourceFileFlags[10]) { - throw makeRuntimeRejectMsg(workerScript, "getInformation() failed because you do not currently have access to the Sleeve API. This is either because you are not in BitNode-10 or because you do not have Source-File 10"); - } updateDynamicRam("getInformation", getRamCost("sleeve", "getInformation")); - if (sleeveNumber >= Player.sleeves.length || sleeveNumber < 0) { - workerScript.log(`ERROR: sleeve.getInformation(${sleeveNumber}) failed because it is an invalid sleeve number.`); - return false; - } + checkSleeveAPIAccess("getInformation"); + checkSleeveNumber("getInformation", sleeveNumber); const sl = Player.sleeves[sleeveNumber]; return { @@ -4675,14 +3950,9 @@ function NetscriptFunctions(workerScript) { } }, getSleeveAugmentations: function(sleeveNumber=0) { - if (Player.bitNodeN !== 10 && !SourceFileFlags[10]) { - throw makeRuntimeRejectMsg(workerScript, "getSleeveAugmentations() failed because you do not currently have access to the Sleeve API. This is either because you are not in BitNode-10 or because you do not have Source-File 10"); - } updateDynamicRam("getSleeveAugmentations", getRamCost("sleeve", "getSleeveAugmentations")); - if (sleeveNumber >= Player.sleeves.length || sleeveNumber < 0) { - workerScript.log(`ERROR: sleeve.getSleeveAugmentations(${sleeveNumber}) failed because it is an invalid sleeve number.`); - return []; - } + checkSleeveAPIAccess("getSleeveAugmentations"); + checkSleeveNumber("getSleeveAugmentations", sleeveNumber); const augs = []; for (let i = 0; i < Player.sleeves[sleeveNumber].augmentations.length; i++) { @@ -4691,14 +3961,9 @@ function NetscriptFunctions(workerScript) { return augs; }, getSleevePurchasableAugs: function(sleeveNumber=0) { - if (Player.bitNodeN !== 10 && !SourceFileFlags[10]) { - throw makeRuntimeRejectMsg(workerScript, "getSleevePurchasableAugs() failed because you do not currently have access to the Sleeve API. This is either because you are not in BitNode-10 or because you do not have Source-File 10"); - } updateDynamicRam("getSleevePurchasableAugs", getRamCost("sleeve", "getSleevePurchasableAugs")); - if (sleeveNumber >= Player.sleeves.length || sleeveNumber < 0) { - workerScript.log(`ERROR: sleeve.getSleevePurchasableAugs(${sleeveNumber}) failed because it is an invalid sleeve number.`); - return []; - } + checkSleeveAPIAccess("getSleevePurchasableAugs"); + checkSleeveNumber("getSleevePurchasableAugs", sleeveNumber); const purchasableAugs = findSleevePurchasableAugs(Player.sleeves[sleeveNumber], Player); const augs = []; @@ -4713,18 +3978,13 @@ function NetscriptFunctions(workerScript) { return augs; }, purchaseSleeveAug: function(sleeveNumber=0, augName="") { - if (Player.bitNodeN !== 10 && !SourceFileFlags[10]) { - throw makeRuntimeRejectMsg(workerScript, "purchaseSleeveAug() failed because you do not currently have access to the Sleeve API. This is either because you are not in BitNode-10 or because you do not have Source-File 10"); - } updateDynamicRam("purchaseSleeveAug", getRamCost("sleeve", "purchaseSleeveAug")); - if (sleeveNumber >= Player.sleeves.length || sleeveNumber < 0) { - workerScript.log(`ERROR: sleeve.purchaseSleeveAug(${sleeveNumber}) failed because it is an invalid sleeve number.`); - return false; - } + checkSleeveAPIAccess("purchaseSleeveAug"); + checkSleeveNumber("purchaseSleeveAug", sleeveNumber); const aug = Augmentations[augName]; if (!aug) { - workerScript.log(`ERROR: sleeve.purchaseSleeveAug(${sleeveNumber}) failed because ${augName} is not a valid aug.`); + throw makeRuntimeErrorMsg("sleeve.purchaseSleeveAug", `Invalid aug: ${augName}`) } return Player.sleeves[sleeveNumber].tryBuyAugmentation(Player, aug); @@ -4738,12 +3998,6 @@ function NetscriptFunctions(workerScript) { }, exploit: function() { Player.giveExploit(Exploit.UndocumentedFunctionCall); - }, - whatever: function(ip) { - const server = getServer(ip); - if (server == null) { - throw makeRuntimeRejectMsg(workerScript, `${lineNumber()}: hack('${ip}'): Invalid IP/hostname.`); - } } } // End return } // End NetscriptFunction() diff --git a/src/NetscriptGang.js b/src/NetscriptGang.js index 1fce46666..d592ff251 100644 --- a/src/NetscriptGang.js +++ b/src/NetscriptGang.js @@ -6,10 +6,3 @@ export function unknownGangApiExceptionMessage(functionName, err) { return `gang.${functionName}() failed with exception: ` + err; } -export function checkGangApiAccess(workerScript, functionName) { - const accessDenied = `gang.${functionName}() failed because you do not currently have a Gang`; - const hasAccess = Player.gang instanceof Gang; - if (!hasAccess) { - throw makeRuntimeRejectMsg(workerScript, accessDenied); - } -} diff --git a/src/NetscriptJSEvaluator.js b/src/NetscriptJSEvaluator.js index 1f8a9e255..084cb4d3e 100644 --- a/src/NetscriptJSEvaluator.js +++ b/src/NetscriptJSEvaluator.js @@ -1,21 +1,12 @@ import { makeRuntimeRejectMsg } from "./NetscriptEvaluator"; import { Script } from "./Script/Script"; +import { ScriptUrl } from "./Script/ScriptUrl"; // Makes a blob that contains the code of a given script. export function makeScriptBlob(code) { return new Blob([code], {type: "text/javascript"}); } -class ScriptUrl { - /** - * @param {string} filename - * @param {string} url - */ - constructor(filename, url) { - this.filename = filename; - this.url = url; - } -} // Begin executing a user JS script, and return a promise that resolves // or rejects when the script finishes. @@ -40,7 +31,7 @@ export async function executeJSScript(scripts = [], workerScript) { urls = _getScriptUrls(script, scripts, []); script.url = urls[urls.length - 1].url; script.module = new Promise(resolve => resolve(eval('import(urls[urls.length - 1].url)'))); - script.dependencies = urls.map(u => u.filename); + script.dependencies = urls; } loadedModule = await script.module; @@ -69,7 +60,7 @@ export async function executeJSScript(scripts = [], workerScript) { function shouldCompile(script, scripts) { if (script.module === "") return true; return script.dependencies.some(dep => { - const depScript = scripts.find(s => s.filename == dep); + const depScript = scripts.find(s => s.filename == dep.url); // If the script is not present on the server, we should recompile, if only to get any necessary // compilation errors. diff --git a/src/NetscriptWorker.js b/src/NetscriptWorker.js index a07f92f32..f030ac93d 100644 --- a/src/NetscriptWorker.js +++ b/src/NetscriptWorker.js @@ -501,7 +501,7 @@ export function createAndAddWorkerScript(runningScriptObj, server) { if (!w.running) { return; } killWorkerScript(s); - w.log("Script finished running"); + w.log("", "Script finished running"); }).catch(function(w) { if (w instanceof Error) { dialogBoxCreate("Script runtime unknown error. This is a bug please contact game developer"); @@ -509,22 +509,27 @@ export function createAndAddWorkerScript(runningScriptObj, server) { return; } else if (w instanceof WorkerScript) { if (isScriptErrorMessage(w.errorMessage)) { - var errorTextArray = w.errorMessage.split("|"); + const errorTextArray = w.errorMessage.split("|"); if (errorTextArray.length != 4) { console.error("ERROR: Something wrong with Error text in evaluator..."); console.error("Error text: " + errorText); return; } - var serverIp = errorTextArray[1]; - var scriptName = errorTextArray[2]; - var errorMsg = errorTextArray[3]; + const serverIp = errorTextArray[1]; + const scriptName = errorTextArray[2]; + const errorMsg = errorTextArray[3]; - dialogBoxCreate("Script runtime error:
    Server Ip: " + serverIp + - "
    Script name: " + scriptName + - "
    Args:" + arrayToString(w.args) + "
    " + errorMsg); - w.log("Script crashed with runtime error"); + let msg = `RUNTIME ERROR
    ${scriptName}@${serverIp}
    ` + if (w.args.length > 0) { + msg += `Args: ${arrayToString(w.args)}
    ` + } + msg += "
    "; + msg += errorMsg; + + dialogBoxCreate(msg); + w.log("", "Script crashed with runtime error"); } else { - w.log("Script killed"); + w.log("", "Script killed"); return; // Already killed, so stop here } w.running = false; @@ -594,14 +599,14 @@ export function loadAllRunningScripts() { /** * Run a script from inside another script (run(), exec(), spawn(), etc.) */ -export function runScriptFromScript(server, scriptname, args, workerScript, threads=1) { +export function runScriptFromScript(caller, server, scriptname, args, workerScript, threads=1) { // Sanitize arguments if (!(workerScript instanceof WorkerScript)) { return 0; } if (typeof scriptname !== "string" || !Array.isArray(args)) { - workerScript.log(`ERROR: runScriptFromScript() failed due to invalid arguments`); + workerScript.log(caller, `Invalid arguments: scriptname='${scriptname} args='${ags}'`); console.error(`runScriptFromScript() failed due to invalid arguments`); return 0; } @@ -609,14 +614,14 @@ export function runScriptFromScript(server, scriptname, args, workerScript, thre // Check if the script is already running let runningScriptObj = server.getRunningScript(scriptname, args); if (runningScriptObj != null) { - workerScript.log(`${scriptname} is already running on ${server.hostname}`); + workerScript.log(caller, `'${scriptname}' is already running on '${server.hostname}'`); return 0; } // 'null/undefined' arguments are not allowed for (let i = 0; i < args.length; ++i) { if (args[i] == null) { - workerScript.log("ERROR: Cannot execute a script with null/undefined as an argument"); + workerScript.log(caller, "Cannot execute a script with null/undefined as an argument"); return 0; } } @@ -633,16 +638,14 @@ export function runScriptFromScript(server, scriptname, args, workerScript, thre const ramAvailable = server.maxRam - server.ramUsed; if (server.hasAdminRights == false) { - workerScript.log(`Cannot run script ${scriptname} on ${server.hostname} because you do not have root access!`); + workerScript.log(caller, `You do not have root access on '${server.hostname}'`); return 0; } else if (ramUsage > ramAvailable){ - workerScript.log(`Cannot run script ${scriptname} (t=${threads}) on ${server.hostname} because there is not enough available RAM!`); + workerScript.log(caller, `Cannot run script '${scriptname}' (t=${threads}) on '${server.hostname}' because there is not enough available RAM!`); return 0; } else { // Able to run script - if (workerScript.disableLogs.ALL == null && workerScript.disableLogs.exec == null && workerScript.disableLogs.run == null && workerScript.disableLogs.spawn == null) { - workerScript.log(`Running script: ${scriptname} on ${server.hostname} with ${threads} threads and args: ${arrayToString(args)}.`); - } + workerScript.log(caller, `'${scriptname}' on '${server.hostname}' with ${threads} threads and args: ${arrayToString(args)}.`); let runningScriptObj = new RunningScript(script, args); runningScriptObj.threads = threads; @@ -651,6 +654,6 @@ export function runScriptFromScript(server, scriptname, args, workerScript, thre } } - workerScript.log(`Could not find script ${scriptname} on ${server.hostname}`); + workerScript.log(caller, `Could not find script '${scriptname}' on '${server.hostname}'`); return 0; } diff --git a/src/Script/Script.ts b/src/Script/Script.ts index 4b4f8ea07..cb3c8d112 100644 --- a/src/Script/Script.ts +++ b/src/Script/Script.ts @@ -5,6 +5,7 @@ * being evaluated. See RunningScript for that */ import { calculateRamUsage } from "./RamCalculations"; +import { ScriptUrl } from "./ScriptUrl"; import { Page, routing } from "../ui/navigationTracking"; import { setTimeoutRef } from "../utils/SetTimeoutRef"; @@ -42,7 +43,7 @@ export class Script { // Only used with NS2 scripts; the list of dependency script filenames. This is constructed // whenever the script is first evaluated, and therefore may be out of date if the script // has been updated since it was last run. - dependencies: string[] = []; + dependencies: ScriptUrl[] = []; // Amount of RAM this Script requres to run ramUsage: number = 0; diff --git a/src/Script/ScriptUrl.ts b/src/Script/ScriptUrl.ts new file mode 100644 index 000000000..903066690 --- /dev/null +++ b/src/Script/ScriptUrl.ts @@ -0,0 +1,9 @@ +export class ScriptUrl { + filename: string; + url: string; + + constructor(filename: string, url: string) { + this.filename = filename; + this.url = url; + } +} diff --git a/src/StockMarket/BuyingAndSelling.ts b/src/StockMarket/BuyingAndSelling.ts index ba6ec3630..b0a76ea15 100644 --- a/src/StockMarket/BuyingAndSelling.ts +++ b/src/StockMarket/BuyingAndSelling.ts @@ -43,7 +43,7 @@ export function buyStock(stock: Stock, shares: number, workerScript: WorkerScrip if (shares <= 0) { return false; } if (stock == null || isNaN(shares)) { if (tixApi) { - workerScript!.log(`ERROR: buyStock() failed due to invalid arguments`); + workerScript!.log("buyStock", `Invalid arguments: stock='${stock}' shares='${shares}'`); } else if (opts.suppressDialog !== true) { dialogBoxCreate("Failed to buy stock. This may be a bug, contact developer"); } @@ -56,7 +56,7 @@ export function buyStock(stock: Stock, shares: number, workerScript: WorkerScrip if (totalPrice == null) { return false; } if (Player.money.lt(totalPrice)) { if (tixApi) { - workerScript!.log(`ERROR: buyStock() failed because you do not have enough money to purchase this position. You need ${numeralWrapper.formatMoney(totalPrice)}`); + workerScript!.log("buyStock", `You do not have enough money to purchase this position. You need ${numeralWrapper.formatMoney(totalPrice)}.`); } else if (opts.suppressDialog !== true) { dialogBoxCreate(`You do not have enough money to purchase this. You need ${numeralWrapper.formatMoney(totalPrice)}`); } @@ -67,7 +67,7 @@ export function buyStock(stock: Stock, shares: number, workerScript: WorkerScrip // Would this purchase exceed the maximum number of shares? if (shares + stock.playerShares + stock.playerShortShares > stock.maxShares) { if (tixApi) { - workerScript!.log(`ERROR: buyStock() failed because purchasing this many shares would exceed ${stock.symbol}'s maximum number of shares`); + workerScript!.log("buyStock", `Purchasing '${shares + stock.playerShares + stock.playerShortShares}' shares would exceed ${stock.symbol}'s maximum (${stock.maxShares}) number of shares`); } else if (opts.suppressDialog !== true) { dialogBoxCreate(`You cannot purchase this many shares. ${stock.symbol} has a maximum of ${numeralWrapper.formatBigNumber(stock.maxShares)} shares.`); } @@ -88,7 +88,7 @@ export function buyStock(stock: Stock, shares: number, workerScript: WorkerScrip const resultTxt = `Bought ${numeralWrapper.format(shares, '0,0')} shares of ${stock.symbol} for ${numeralWrapper.formatMoney(totalPrice)}. ` + `Paid ${numeralWrapper.formatMoney(CONSTANTS.StockMarketCommission)} in commission fees.` if (tixApi) { - if (workerScript!.shouldLog("buyStock")) { workerScript!.log(resultTxt); } + workerScript!.log("buyStock", resultTxt) } else if (opts.suppressDialog !== true) { dialogBoxCreate(resultTxt); } @@ -110,7 +110,7 @@ export function sellStock(stock: Stock, shares: number, workerScript: WorkerScri // Sanitize/Validate arguments if (stock == null || shares < 0 || isNaN(shares)) { if (tixApi) { - workerScript!.log(`ERROR: sellStock() failed due to invalid arguments`); + workerScript!.log("sellStock", `Invalid arguments: stock='${stock}' shares='${shares}'`); } else if (opts.suppressDialog !== true) { dialogBoxCreate("Failed to sell stock. This is probably due to an invalid quantity. Otherwise, this may be a bug, contact developer"); } @@ -146,7 +146,7 @@ export function sellStock(stock: Stock, shares: number, workerScript: WorkerScri const resultTxt = `Sold ${numeralWrapper.format(shares, '0,0')} shares of ${stock.symbol}. ` + `After commissions, you gained a total of ${numeralWrapper.formatMoney(gains)}.`; if (tixApi) { - if (workerScript!.shouldLog("sellStock")) { workerScript!.log(resultTxt); } + workerScript!.log("sellStock", resultTxt) } else if (opts.suppressDialog !== true) { dialogBoxCreate(resultTxt); } @@ -170,7 +170,7 @@ export function shortStock(stock: Stock, shares: number, workerScript: WorkerScr if (shares <= 0) { return false; } if (stock == null || isNaN(shares)) { if (tixApi) { - workerScript!.log("ERROR: shortStock() failed because of invalid arguments."); + workerScript!.log("shortStock", `Invalid arguments: stock='${stock}' shares='${shares}'`); } else if (opts.suppressDialog !== true) { dialogBoxCreate("Failed to initiate a short position in a stock. This is probably " + "due to an invalid quantity. Otherwise, this may be a bug, so contact developer"); @@ -183,7 +183,7 @@ export function shortStock(stock: Stock, shares: number, workerScript: WorkerScr if (totalPrice == null) { return false; } if (Player.money.lt(totalPrice)) { if (tixApi) { - workerScript!.log("ERROR: shortStock() failed because you do not have enough " + + workerScript!.log("shortStock", "You do not have enough " + "money to purchase this short position. You need " + numeralWrapper.formatMoney(totalPrice)); } else if (opts.suppressDialog !== true) { @@ -197,7 +197,7 @@ export function shortStock(stock: Stock, shares: number, workerScript: WorkerScr // Would this purchase exceed the maximum number of shares? if (shares + stock.playerShares + stock.playerShortShares > stock.maxShares) { if (tixApi) { - workerScript!.log(`ERROR: shortStock() failed because purchasing this many short shares would exceed ${stock.symbol}'s maximum number of shares.`); + workerScript!.log("shortStock", `This '${shares + stock.playerShares + stock.playerShortShares}' short shares would exceed ${stock.symbol}'s maximum (${stock.maxShares}) number of shares.`); } else if (opts.suppressDialog !== true) { dialogBoxCreate(`You cannot purchase this many shares. ${stock.symbol} has a maximum of ${stock.maxShares} shares.`); } @@ -220,7 +220,7 @@ export function shortStock(stock: Stock, shares: number, workerScript: WorkerScr `for ${numeralWrapper.formatMoney(totalPrice)}. Paid ${numeralWrapper.formatMoney(CONSTANTS.StockMarketCommission)} ` + `in commission fees.`; if (tixApi) { - if (workerScript!.shouldLog("shortStock")) { workerScript!.log(resultTxt); } + workerScript!.log("shortStock", resultTxt); } else if (!opts.suppressDialog) { dialogBoxCreate(resultTxt); } @@ -241,7 +241,7 @@ export function sellShort(stock: Stock, shares: number, workerScript: WorkerScri if (stock == null || isNaN(shares) || shares < 0) { if (tixApi) { - workerScript!.log("ERROR: sellShort() failed because of invalid arguments."); + workerScript!.log("sellShort", `Invalid arguments: stock='${stock}' shares='${shares}'`); } else if (!opts.suppressDialog) { dialogBoxCreate("Failed to sell a short position in a stock. This is probably " + "due to an invalid quantity. Otherwise, this may be a bug, so contact developer"); @@ -257,7 +257,7 @@ export function sellShort(stock: Stock, shares: number, workerScript: WorkerScri const totalGain = getSellTransactionGain(stock, shares, PositionTypes.Short); if (totalGain == null || isNaN(totalGain) || origCost == null) { if (tixApi) { - workerScript!.log(`Failed to sell short position in a stock. This is probably either due to invalid arguments, or a bug`); + workerScript!.log("sellShort", `Failed to sell short position in a stock. This is probably either due to invalid arguments, or a bug`); } else if (!opts.suppressDialog) { dialogBoxCreate(`Failed to sell short position in a stock. This is probably either due to invalid arguments, or a bug`); } @@ -286,7 +286,7 @@ export function sellShort(stock: Stock, shares: number, workerScript: WorkerScri const resultTxt = `Sold your short position of ${numeralWrapper.format(shares, '0,0')} shares of ${stock.symbol}. ` + `After commissions, you gained a total of ${numeralWrapper.formatMoney(totalGain)}`; if (tixApi) { - if (workerScript!.shouldLog("sellShort")) { workerScript!.log(resultTxt); } + workerScript!.log("sellShort", resultTxt); } else if (!opts.suppressDialog) { dialogBoxCreate(resultTxt); } diff --git a/src/StockMarket/StockMarket.tsx b/src/StockMarket/StockMarket.tsx index 97802e56f..307dd5d80 100644 --- a/src/StockMarket/StockMarket.tsx +++ b/src/StockMarket/StockMarket.tsx @@ -38,7 +38,7 @@ export function placeOrder(stock: Stock, shares: number, price: number, type: Or const tixApi = (workerScript instanceof WorkerScript); if (!(stock instanceof Stock)) { if (tixApi) { - workerScript!.log(`ERROR: Invalid stock passed to placeOrder() function`); + workerScript!.log("placeOrder", `Invalid stock: '${stock}'`); } else { dialogBoxCreate(`ERROR: Invalid stock passed to placeOrder() function`); } @@ -46,7 +46,7 @@ export function placeOrder(stock: Stock, shares: number, price: number, type: Or } if (typeof shares !== "number" || typeof price !== "number") { if (tixApi) { - workerScript!.log("ERROR: Invalid numeric value provided for either 'shares' or 'price' argument"); + workerScript!.log("placeOrder", `Invalid arguments: shares='${shares}' price='${price}'`); } else { dialogBoxCreate("ERROR: Invalid numeric value provided for either 'shares' or 'price' argument"); } From e7dbc08e18fb54c5420e621b79d64bcc2c54b7b7 Mon Sep 17 00:00:00 2001 From: Olivier Gagnon Date: Thu, 11 Mar 2021 16:48:00 -0500 Subject: [PATCH 15/19] fix documentation for Bladeburner API. --- doc/source/netscript/bladeburnerapi/getActionAutolevel.rst | 1 + .../netscript/bladeburnerapi/getActionCountRemaining.rst | 1 + .../netscript/bladeburnerapi/getActionCurrentLevel.rst | 1 + .../bladeburnerapi/getActionEstimatedSuccessChance.rst | 1 + doc/source/netscript/bladeburnerapi/getActionMaxLevel.rst | 1 + doc/source/netscript/bladeburnerapi/getActionRepGain.rst | 1 + doc/source/netscript/bladeburnerapi/getActionTime.rst | 1 + doc/source/netscript/bladeburnerapi/getBlackOpNames.rst | 1 + doc/source/netscript/bladeburnerapi/getBlackOpRank.rst | 1 + doc/source/netscript/bladeburnerapi/getBonusTime.rst | 1 + doc/source/netscript/bladeburnerapi/getCity.rst | 1 + doc/source/netscript/bladeburnerapi/getCityChaos.rst | 1 + .../bladeburnerapi/getCityEstimatedCommunities.rst | 1 + .../netscript/bladeburnerapi/getCityEstimatedPopulation.rst | 1 + doc/source/netscript/bladeburnerapi/getContractNames.rst | 1 + doc/source/netscript/bladeburnerapi/getCurrentAction.rst | 1 + .../netscript/bladeburnerapi/getGeneralActionNames.rst | 1 + doc/source/netscript/bladeburnerapi/getOperationNames.rst | 1 + doc/source/netscript/bladeburnerapi/getRank.rst | 1 + doc/source/netscript/bladeburnerapi/getSkillLevel.rst | 1 + doc/source/netscript/bladeburnerapi/getSkillNames.rst | 1 + doc/source/netscript/bladeburnerapi/getSkillPoints.rst | 1 + doc/source/netscript/bladeburnerapi/getSkillUpgradeCost.rst | 1 + doc/source/netscript/bladeburnerapi/getStamina.rst | 1 + doc/source/netscript/bladeburnerapi/getTeamSize.rst | 1 + .../netscript/bladeburnerapi/joinBladeburnerDivision.rst | 1 + .../netscript/bladeburnerapi/joinBladeburnerFaction.rst | 1 + doc/source/netscript/bladeburnerapi/setActionAutolevel.rst | 1 + doc/source/netscript/bladeburnerapi/setActionLevel.rst | 1 + doc/source/netscript/bladeburnerapi/setTeamSize.rst | 1 + doc/source/netscript/bladeburnerapi/startAction.rst | 1 + .../netscript/bladeburnerapi/stopBladeburnerAction.rst | 1 + doc/source/netscript/bladeburnerapi/switchCity.rst | 1 + doc/source/netscript/bladeburnerapi/upgradeSkill.rst | 1 + src/Constants.ts | 6 +++--- 35 files changed, 37 insertions(+), 3 deletions(-) diff --git a/doc/source/netscript/bladeburnerapi/getActionAutolevel.rst b/doc/source/netscript/bladeburnerapi/getActionAutolevel.rst index 36c3e283a..7e49939f6 100644 --- a/doc/source/netscript/bladeburnerapi/getActionAutolevel.rst +++ b/doc/source/netscript/bladeburnerapi/getActionAutolevel.rst @@ -2,6 +2,7 @@ getActionAutolevel() Netscript Function ======================================= .. js:function:: getActionAutolevel(type, name) + :RAM cost: 4 GB :param string type: Type of action. See :ref:`bladeburner_action_types` diff --git a/doc/source/netscript/bladeburnerapi/getActionCountRemaining.rst b/doc/source/netscript/bladeburnerapi/getActionCountRemaining.rst index a3fe57cec..a1938bb9e 100644 --- a/doc/source/netscript/bladeburnerapi/getActionCountRemaining.rst +++ b/doc/source/netscript/bladeburnerapi/getActionCountRemaining.rst @@ -2,6 +2,7 @@ getActionCountRemaining() Netscript Function ============================================ .. js:function:: getActionCountRemaining(type, name) + :RAM cost: 4 GB :param string type: Type of action. See :ref:`bladeburner_action_types` diff --git a/doc/source/netscript/bladeburnerapi/getActionCurrentLevel.rst b/doc/source/netscript/bladeburnerapi/getActionCurrentLevel.rst index 0389b4534..efb234e8a 100644 --- a/doc/source/netscript/bladeburnerapi/getActionCurrentLevel.rst +++ b/doc/source/netscript/bladeburnerapi/getActionCurrentLevel.rst @@ -2,6 +2,7 @@ getActionCurrentLevel() Netscript Function ========================================== .. js:function:: getActionCurrentLevel(type, name) + :RAM cost: 4 GB :param string type: Type of action. See :ref:`bladeburner_action_types` diff --git a/doc/source/netscript/bladeburnerapi/getActionEstimatedSuccessChance.rst b/doc/source/netscript/bladeburnerapi/getActionEstimatedSuccessChance.rst index 5e6afcf7c..5ca773c2e 100644 --- a/doc/source/netscript/bladeburnerapi/getActionEstimatedSuccessChance.rst +++ b/doc/source/netscript/bladeburnerapi/getActionEstimatedSuccessChance.rst @@ -2,6 +2,7 @@ getActionEstimatedSuccessChance() Netscript Function ==================================================== .. js:function:: getActionEstimatedSuccessChance(type, name) + :RAM cost: 4 GB :param string type: Type of action. See :ref:`bladeburner_action_types` diff --git a/doc/source/netscript/bladeburnerapi/getActionMaxLevel.rst b/doc/source/netscript/bladeburnerapi/getActionMaxLevel.rst index d830289fd..a42bf7517 100644 --- a/doc/source/netscript/bladeburnerapi/getActionMaxLevel.rst +++ b/doc/source/netscript/bladeburnerapi/getActionMaxLevel.rst @@ -2,6 +2,7 @@ getActionMaxLevel() Netscript Function ====================================== .. js:function:: getActionMaxLevel(type, name) + :RAM cost: 4 GB :param string type: Type of action. See :ref:`bladeburner_action_types` diff --git a/doc/source/netscript/bladeburnerapi/getActionRepGain.rst b/doc/source/netscript/bladeburnerapi/getActionRepGain.rst index 3fe966422..2d9948a97 100644 --- a/doc/source/netscript/bladeburnerapi/getActionRepGain.rst +++ b/doc/source/netscript/bladeburnerapi/getActionRepGain.rst @@ -2,6 +2,7 @@ getActionRepGain() Netscript Function ===================================== .. js:function:: getActionRepGain(type, name[, level=current level]) + :RAM cost: 4 GB :param string type: Type of action. See :ref:`bladeburner_action_types` diff --git a/doc/source/netscript/bladeburnerapi/getActionTime.rst b/doc/source/netscript/bladeburnerapi/getActionTime.rst index d36e038e5..42df756fc 100644 --- a/doc/source/netscript/bladeburnerapi/getActionTime.rst +++ b/doc/source/netscript/bladeburnerapi/getActionTime.rst @@ -2,6 +2,7 @@ getActionTime() Netscript Function ================================== .. js:function:: getActionTime(type, name) + :RAM cost: 4 GB :param string type: Type of action. See :ref:`bladeburner_action_types` diff --git a/doc/source/netscript/bladeburnerapi/getBlackOpNames.rst b/doc/source/netscript/bladeburnerapi/getBlackOpNames.rst index 3bf3c8a07..b95edd9bf 100644 --- a/doc/source/netscript/bladeburnerapi/getBlackOpNames.rst +++ b/doc/source/netscript/bladeburnerapi/getBlackOpNames.rst @@ -2,6 +2,7 @@ getBlackOpNames() Netscript Function ==================================== .. js:function:: getBlackOpNames() + :RAM cost: 0.4 GB Returns an array of strings containing the names of all Bladeburner Black Ops diff --git a/doc/source/netscript/bladeburnerapi/getBlackOpRank.rst b/doc/source/netscript/bladeburnerapi/getBlackOpRank.rst index bf8be9f7d..0aba8a3ad 100644 --- a/doc/source/netscript/bladeburnerapi/getBlackOpRank.rst +++ b/doc/source/netscript/bladeburnerapi/getBlackOpRank.rst @@ -2,6 +2,7 @@ getBlackOpRank() Netscript Function ==================================== .. js:function:: getBlackOpRank(name) + :RAM cost: 2 GB :param string name: name of the BlackOp. Must be an exact match. diff --git a/doc/source/netscript/bladeburnerapi/getBonusTime.rst b/doc/source/netscript/bladeburnerapi/getBonusTime.rst index c559684b2..9fdf7d3cc 100644 --- a/doc/source/netscript/bladeburnerapi/getBonusTime.rst +++ b/doc/source/netscript/bladeburnerapi/getBonusTime.rst @@ -2,6 +2,7 @@ getBonusTime() Netscript Function ================================= .. js:function:: getBonusTime() + :RAM cost: 0 GB Returns the amount of accumulated "bonus time" (seconds) for the Bladeburner mechanic. diff --git a/doc/source/netscript/bladeburnerapi/getCity.rst b/doc/source/netscript/bladeburnerapi/getCity.rst index 8103859fd..cdc2d775e 100644 --- a/doc/source/netscript/bladeburnerapi/getCity.rst +++ b/doc/source/netscript/bladeburnerapi/getCity.rst @@ -2,6 +2,7 @@ getCity() Netscript Function ============================ .. js:function:: getCity() + :RAM cost: 4 GB Returns the city that the player is currently in (for Bladeburner). diff --git a/doc/source/netscript/bladeburnerapi/getCityChaos.rst b/doc/source/netscript/bladeburnerapi/getCityChaos.rst index 204bbc112..77fb0b073 100644 --- a/doc/source/netscript/bladeburnerapi/getCityChaos.rst +++ b/doc/source/netscript/bladeburnerapi/getCityChaos.rst @@ -2,6 +2,7 @@ getCityChaos() Netscript Function ================================= .. js:function:: getCityChaos(cityName) + :RAM cost: 4 GB :param string cityName: Name of city. Case-sensitive diff --git a/doc/source/netscript/bladeburnerapi/getCityEstimatedCommunities.rst b/doc/source/netscript/bladeburnerapi/getCityEstimatedCommunities.rst index 27119b362..2dd20c9f2 100644 --- a/doc/source/netscript/bladeburnerapi/getCityEstimatedCommunities.rst +++ b/doc/source/netscript/bladeburnerapi/getCityEstimatedCommunities.rst @@ -2,6 +2,7 @@ getCityEstimatedCommunities() Netscript Function ================================================ .. js:function:: getCityEstimatedCommunities(cityName) + :RAM cost: 4 GB :param string cityName: Name of city. Case-sensitive diff --git a/doc/source/netscript/bladeburnerapi/getCityEstimatedPopulation.rst b/doc/source/netscript/bladeburnerapi/getCityEstimatedPopulation.rst index c5cf73a5e..328f2aa19 100644 --- a/doc/source/netscript/bladeburnerapi/getCityEstimatedPopulation.rst +++ b/doc/source/netscript/bladeburnerapi/getCityEstimatedPopulation.rst @@ -2,6 +2,7 @@ getCityEstimatedPopulation() Netscript Function =============================================== .. js:function:: getCityEstimatedPopulation(cityName) + :RAM cost: 4 GB :param string cityName: Name of city. Case-sensitive diff --git a/doc/source/netscript/bladeburnerapi/getContractNames.rst b/doc/source/netscript/bladeburnerapi/getContractNames.rst index c5c5c8176..f5aa79808 100644 --- a/doc/source/netscript/bladeburnerapi/getContractNames.rst +++ b/doc/source/netscript/bladeburnerapi/getContractNames.rst @@ -2,6 +2,7 @@ getContractNames() Netscript Function ===================================== .. js:function:: getContractNames() + :RAM cost: 0.4 GB Returns an array of strings containing the names of all Bladeburner contracts diff --git a/doc/source/netscript/bladeburnerapi/getCurrentAction.rst b/doc/source/netscript/bladeburnerapi/getCurrentAction.rst index 9d5275ad7..d15e7fed2 100644 --- a/doc/source/netscript/bladeburnerapi/getCurrentAction.rst +++ b/doc/source/netscript/bladeburnerapi/getCurrentAction.rst @@ -2,6 +2,7 @@ getCurrentAction() Netscript Function ===================================== .. js:function:: getCurrentAction() + :RAM cost: 1 GB Returns an object that represents the player's current Bladeburner action:: diff --git a/doc/source/netscript/bladeburnerapi/getGeneralActionNames.rst b/doc/source/netscript/bladeburnerapi/getGeneralActionNames.rst index 6c232efac..efa335998 100644 --- a/doc/source/netscript/bladeburnerapi/getGeneralActionNames.rst +++ b/doc/source/netscript/bladeburnerapi/getGeneralActionNames.rst @@ -2,6 +2,7 @@ getGeneralActionNames() Netscript Function ========================================== .. js:function:: getGeneralActionNames() + :RAM cost: 0.4 GB Returns an array of strings containing the names of all general Bladeburner actions diff --git a/doc/source/netscript/bladeburnerapi/getOperationNames.rst b/doc/source/netscript/bladeburnerapi/getOperationNames.rst index fcfc235ea..0bce307a9 100644 --- a/doc/source/netscript/bladeburnerapi/getOperationNames.rst +++ b/doc/source/netscript/bladeburnerapi/getOperationNames.rst @@ -2,6 +2,7 @@ getOperationNames() Netscript Function ====================================== .. js:function:: getOperationNames() + :RAM cost: 0.4 GB Returns an array of strings containing the names of all Bladeburner operations diff --git a/doc/source/netscript/bladeburnerapi/getRank.rst b/doc/source/netscript/bladeburnerapi/getRank.rst index 1d7027dbc..dca51ff25 100644 --- a/doc/source/netscript/bladeburnerapi/getRank.rst +++ b/doc/source/netscript/bladeburnerapi/getRank.rst @@ -2,6 +2,7 @@ getRank() Netscript Function ============================ .. js:function:: getRank() + :RAM cost: 4 GB Returns the player's Bladeburner Rank diff --git a/doc/source/netscript/bladeburnerapi/getSkillLevel.rst b/doc/source/netscript/bladeburnerapi/getSkillLevel.rst index 8a34cbfcc..832e16fa0 100644 --- a/doc/source/netscript/bladeburnerapi/getSkillLevel.rst +++ b/doc/source/netscript/bladeburnerapi/getSkillLevel.rst @@ -2,6 +2,7 @@ getSkillLevel() Netscript Function ================================== .. js:function:: getSkillLevel(skillName="") + :RAM cost: 4 GB :param string skillName: Name of skill. Case-sensitive and must be an exact match diff --git a/doc/source/netscript/bladeburnerapi/getSkillNames.rst b/doc/source/netscript/bladeburnerapi/getSkillNames.rst index 9090b8ac0..fd5a8ded5 100644 --- a/doc/source/netscript/bladeburnerapi/getSkillNames.rst +++ b/doc/source/netscript/bladeburnerapi/getSkillNames.rst @@ -2,6 +2,7 @@ getSkillNames() Netscript Function ================================== .. js:function:: getSkillNames() + :RAM cost: 0.4 GB Returns an array of strings containing the names of all Bladeburner skills diff --git a/doc/source/netscript/bladeburnerapi/getSkillPoints.rst b/doc/source/netscript/bladeburnerapi/getSkillPoints.rst index 406d35eed..a6aabbc02 100644 --- a/doc/source/netscript/bladeburnerapi/getSkillPoints.rst +++ b/doc/source/netscript/bladeburnerapi/getSkillPoints.rst @@ -2,6 +2,7 @@ getSkillPoints() Netscript Function =================================== .. js:function:: getSkillPoints() + :RAM cost: 4 GB Returns the number of Bladeburner skill points you have diff --git a/doc/source/netscript/bladeburnerapi/getSkillUpgradeCost.rst b/doc/source/netscript/bladeburnerapi/getSkillUpgradeCost.rst index 178fc97a5..6f88df730 100644 --- a/doc/source/netscript/bladeburnerapi/getSkillUpgradeCost.rst +++ b/doc/source/netscript/bladeburnerapi/getSkillUpgradeCost.rst @@ -2,6 +2,7 @@ getSkillUpgradeCost() Netscript Function ======================================== .. js:function:: getSkillUpgradeCost(skillName="") + :RAM cost: 4 GB :param string skillName: Name of skill. Case-sensitive and must be an exact match diff --git a/doc/source/netscript/bladeburnerapi/getStamina.rst b/doc/source/netscript/bladeburnerapi/getStamina.rst index 6ec02fed1..13b0ebfac 100644 --- a/doc/source/netscript/bladeburnerapi/getStamina.rst +++ b/doc/source/netscript/bladeburnerapi/getStamina.rst @@ -2,6 +2,7 @@ getStamina() Netscript Function =============================== .. js:function:: getStamina() + :RAM cost: 4 GB Returns an array with two elements: diff --git a/doc/source/netscript/bladeburnerapi/getTeamSize.rst b/doc/source/netscript/bladeburnerapi/getTeamSize.rst index 9084dceb8..bdfaf9be7 100644 --- a/doc/source/netscript/bladeburnerapi/getTeamSize.rst +++ b/doc/source/netscript/bladeburnerapi/getTeamSize.rst @@ -2,6 +2,7 @@ getTeamSize() Netscript Function ================================ .. js:function:: getTeamSize(type, name) + :RAM cost: 4 GB :param string type: Type of action. See :ref:`bladeburner_action_types` diff --git a/doc/source/netscript/bladeburnerapi/joinBladeburnerDivision.rst b/doc/source/netscript/bladeburnerapi/joinBladeburnerDivision.rst index 49905feef..58f9cbe2e 100644 --- a/doc/source/netscript/bladeburnerapi/joinBladeburnerDivision.rst +++ b/doc/source/netscript/bladeburnerapi/joinBladeburnerDivision.rst @@ -2,6 +2,7 @@ joinBladeburnerDivision() Netscript Function ============================================ .. js:function:: joinBladeburnerDivision() + :RAM cost: 4 GB Attempts to join the Bladeburner division. diff --git a/doc/source/netscript/bladeburnerapi/joinBladeburnerFaction.rst b/doc/source/netscript/bladeburnerapi/joinBladeburnerFaction.rst index 4f89281b9..8cb103c88 100644 --- a/doc/source/netscript/bladeburnerapi/joinBladeburnerFaction.rst +++ b/doc/source/netscript/bladeburnerapi/joinBladeburnerFaction.rst @@ -2,6 +2,7 @@ joinBladeburnerFaction() Netscript Function =========================================== .. js:function:: joinBladeburnerFaction() + :RAM cost: 4 GB Attempts to join the Bladeburner faction. diff --git a/doc/source/netscript/bladeburnerapi/setActionAutolevel.rst b/doc/source/netscript/bladeburnerapi/setActionAutolevel.rst index 5a544a804..ede833539 100644 --- a/doc/source/netscript/bladeburnerapi/setActionAutolevel.rst +++ b/doc/source/netscript/bladeburnerapi/setActionAutolevel.rst @@ -2,6 +2,7 @@ setActionAutolevel() Netscript Function ======================================= .. js:function:: setActionAutolevel(type, name, autoLevel) + :RAM cost: 4 GB :param string type: Type of action. See :ref:`bladeburner_action_types` diff --git a/doc/source/netscript/bladeburnerapi/setActionLevel.rst b/doc/source/netscript/bladeburnerapi/setActionLevel.rst index b87ba335b..3b4b09366 100644 --- a/doc/source/netscript/bladeburnerapi/setActionLevel.rst +++ b/doc/source/netscript/bladeburnerapi/setActionLevel.rst @@ -2,6 +2,7 @@ setActionLevel() Netscript Function =================================== .. js:function:: setActionLevel(type, name, level) + :RAM cost: 4 GB :param string type: Type of action. See :ref:`bladeburner_action_types` diff --git a/doc/source/netscript/bladeburnerapi/setTeamSize.rst b/doc/source/netscript/bladeburnerapi/setTeamSize.rst index 37b4a6b97..c13886473 100644 --- a/doc/source/netscript/bladeburnerapi/setTeamSize.rst +++ b/doc/source/netscript/bladeburnerapi/setTeamSize.rst @@ -2,6 +2,7 @@ setTeamSize() Netscript Function ================================ .. js:function:: setTeamSize(type, name, size) + :RAM cost: 4 GB :param string type: Type of action. See :ref:`bladeburner_action_types` diff --git a/doc/source/netscript/bladeburnerapi/startAction.rst b/doc/source/netscript/bladeburnerapi/startAction.rst index 76a291732..1c6040135 100644 --- a/doc/source/netscript/bladeburnerapi/startAction.rst +++ b/doc/source/netscript/bladeburnerapi/startAction.rst @@ -2,6 +2,7 @@ startAction() Netscript Function ================================ .. js:function:: startAction(type, name) + :RAM cost: 4 GB :param string type: Type of action. See :ref:`bladeburner_action_types` diff --git a/doc/source/netscript/bladeburnerapi/stopBladeburnerAction.rst b/doc/source/netscript/bladeburnerapi/stopBladeburnerAction.rst index 3ef2533b5..db59dea95 100644 --- a/doc/source/netscript/bladeburnerapi/stopBladeburnerAction.rst +++ b/doc/source/netscript/bladeburnerapi/stopBladeburnerAction.rst @@ -2,6 +2,7 @@ stopBladeburnerAction() Netscript Function ========================================== .. js:function:: stopBladeburnerAction() + :RAM cost: 2 GB Stops the current Bladeburner action diff --git a/doc/source/netscript/bladeburnerapi/switchCity.rst b/doc/source/netscript/bladeburnerapi/switchCity.rst index b8730cb24..a696b5057 100644 --- a/doc/source/netscript/bladeburnerapi/switchCity.rst +++ b/doc/source/netscript/bladeburnerapi/switchCity.rst @@ -2,6 +2,7 @@ switchCity() Netscript Function =============================== .. js:function:: switchCity(cityName) + :RAM cost: 4 GB :param string cityName: Name of city diff --git a/doc/source/netscript/bladeburnerapi/upgradeSkill.rst b/doc/source/netscript/bladeburnerapi/upgradeSkill.rst index 60fbb469a..191e38429 100644 --- a/doc/source/netscript/bladeburnerapi/upgradeSkill.rst +++ b/doc/source/netscript/bladeburnerapi/upgradeSkill.rst @@ -2,6 +2,7 @@ upgradeSkill() Netscript Function ================================= .. js:function:: upgradeSkill(skillName) + :RAM cost: 4 GB :param string skillName: Name of Skill to be upgraded. Case-sensitive and must be an exact match diff --git a/src/Constants.ts b/src/Constants.ts index dc4267738..7120d6594 100644 --- a/src/Constants.ts +++ b/src/Constants.ts @@ -235,15 +235,15 @@ export let CONSTANTS: IMap = { * For advanced players: The game now embraces exploits and will reward players for doing so. - - - Netscript * 'gang.getEquipmentStats' returns the stats of the equipment. * 'gang.getTaskStats' returns the stats of a task. * 'getCrimeStats' returns the stats of a crime. + * Crashes should now print the ns stack trace. + * Log messages are now more consistent. Misc. * Minor formatting under Hacking>Active Scripts + * option menu colors now match the rest of the game, kinda. ` } From d4816ad0c459d9788523d91d0b2c06061d3b134f Mon Sep 17 00:00:00 2001 From: Olivier Gagnon Date: Thu, 11 Mar 2021 17:01:28 -0500 Subject: [PATCH 16/19] Remove remaining shouldLog calls. --- src/NetscriptFunctions.js | 56 +++++++++++++++++---------------------- 1 file changed, 24 insertions(+), 32 deletions(-) diff --git a/src/NetscriptFunctions.js b/src/NetscriptFunctions.js index aae87c2f9..7bca5fc5a 100644 --- a/src/NetscriptFunctions.js +++ b/src/NetscriptFunctions.js @@ -1107,12 +1107,10 @@ function NetscriptFunctions(workerScript) { } if (res) { - if (workerScript.shouldLog("kill")) { - if (killByPid) { - workerScript.log("kill", `Killing script with PID ${filename}`); - } else { - workerScript.log("kill", `Killing ${filename} on ${ip} with args: ${arrayToString(scriptArgs)}.`); - } + if (killByPid) { + workerScript.log("kill", `Killing script with PID ${filename}`); + } else { + workerScript.log("kill", `Killing '${filename}' on '${ip}' with args: ${arrayToString(scriptArgs)}.`); } return true; } else { @@ -1138,7 +1136,7 @@ function NetscriptFunctions(workerScript) { killWorkerScript(server.runningScripts[i], server.ip, false); } WorkerScriptStartStopEventEmitter.emitEvent(); - workerScript.log("killall", `Killing all scripts on ${server.hostname}. May take a few minutes for the scripts to die.`); + workerScript.log("killall", `Killing all scripts on '${server.hostname}'. May take a few minutes for the scripts to die.`); return scriptsRunning; }, @@ -1168,7 +1166,7 @@ function NetscriptFunctions(workerScript) { // Invalid file type if (!isValidFilePath(scriptname)) { - throw makeRuntimeErrorMsg("scp", `Invalid filename: ${scriptname}`); + throw makeRuntimeErrorMsg("scp", `Invalid filename: '${scriptname}'`); } // Invalid file name @@ -1455,10 +1453,10 @@ function NetscriptFunctions(workerScript) { if (failOnHacknetServer(server, "getServerMoneyAvailable")) { return 0; } if (server.hostname == "home") { // Return player's money - workerScript.log("getServerMoneyAvailable", `returned player's money: $${formatNumber(Player.money.toNumber(), 2)}`); + workerScript.log("getServerMoneyAvailable", `returned player's money: ${numeralWrapper.format(Player.money.toNumber(), '$0.000a')}`); return Player.money.toNumber(); } - workerScript.log("getServerMoneyAvailable", `returned ${formatNumber(server.moneyAvailable, 2)} for '${server.hostname}`); + workerScript.log("getServerMoneyAvailable", `returned ${numeralWrapper.format(server.moneyAvailable, '$0.000a')} for '${server.hostname}`); return server.moneyAvailable; }, getServerSecurityLevel: function(ip) { @@ -1493,7 +1491,7 @@ function NetscriptFunctions(workerScript) { updateDynamicRam("getServerMaxMoney", getRamCost("getServerMaxMoney")); const server = safeGetServer(ip, "getServerMaxMoney"); if (failOnHacknetServer(server, "getServerMaxMoney")) { return 0; } - workerScript.log("getServerMaxMoney", `returned ${formatNumber(server.moneyMax, 0)} for '${server.hostname}'`); + workerScript.log("getServerMaxMoney", `returned ${numeralWrapper.format(server.moneyMax, '$0.000a')} for '${server.hostname}'`); return server.moneyMax; }, getServerGrowth: function(ip) { @@ -1901,7 +1899,7 @@ function NetscriptFunctions(workerScript) { } if (Player.money.lt(cost)) { - workerScript.log("purchaseServer", `Not enough money to purchase server. Need $${formatNumber(cost, 2)}`); + workerScript.log("purchaseServer", `Not enough money to purchase server. Need ${numeralWrapper.format(cost, '$0.000a')}`); return ""; } var newServ = safetlyCreateUniqueServer({ @@ -1920,7 +1918,7 @@ function NetscriptFunctions(workerScript) { homeComputer.serversOnNetwork.push(newServ.ip); newServ.serversOnNetwork.push(homeComputer.ip); Player.loseMoney(cost); - workerScript.log("purchaseServer", `Purchased new server with hostname '${newServ.hostname}' for $${formatNumber(cost, 2)}`); + workerScript.log("purchaseServer", `Purchased new server with hostname '${newServ.hostname}' for ${numeralWrapper.format(cost, '$0.000a')}`); return newServ.hostname; }, deleteServer: function(hostname) { @@ -1954,7 +1952,7 @@ function NetscriptFunctions(workerScript) { // Delete all scripts running on server if (server.runningScripts.length > 0) { - workerScript.log("deleteServer", `Cannot delete server ('${server.hostname}') because it still has scripts running.`); + workerScript.log("deleteServer", `Cannot delete server '${server.hostname}' because it still has scripts running.`); return false; } @@ -3340,12 +3338,10 @@ function NetscriptFunctions(workerScript) { updateDynamicRam("recruitMember", getRamCost("gang", "recruitMember")); checkGangApiAccess("recruitMember"); const recruited = Player.gang.recruitMember(name); - if (workerScript.shouldLog("recruitMember")) { - if (recruited) { - workerScript.log("recruitMember", `Successfully recruited Gang Member '${name}'`); - } else { - workerScript.log("recruitMember", `Failed to recruit Gang Member '${name}'`); - } + if (recruited) { + workerScript.log("recruitMember", `Successfully recruited Gang Member '${name}'`); + } else { + workerScript.log("recruitMember", `Failed to recruit Gang Member '${name}'`); } return recruited; @@ -3362,12 +3358,10 @@ function NetscriptFunctions(workerScript) { checkGangApiAccess("setMemberTask"); const member = getGangMember("setMemberTask", memberName); const success = member.assignToTask(taskName); - if (workerScript.shouldLog("setMemberTask")) { - if (success) { - workerScript.log("setMemberTask", `Successfully assigned Gang Member '${memberName}' to '${taskName}' task`); - } else { - workerScript.log("setMemberTask", `Failed to assign Gang Member '${memberName}' to '${taskName}' task. '${memberName}' is now Unassigned`); - } + if (success) { + workerScript.log("setMemberTask", `Successfully assigned Gang Member '${memberName}' to '${taskName}' task`); + } else { + workerScript.log("setMemberTask", `Failed to assign Gang Member '${memberName}' to '${taskName}' task. '${memberName}' is now Unassigned`); } return success; @@ -3409,12 +3403,10 @@ function NetscriptFunctions(workerScript) { checkGangApiAccess("purchaseEquipment"); const member = getGangMember("purchaseEquipment", memberName); const res = member.buyUpgrade(equipName, Player, Player.gang); - if (workerScript.shouldLog("purchaseEquipment")) { - if (res) { - workerScript.log("purchaseEquipment", `Purchased '${equipName}' for Gang member '${memberName}'`); - } else { - workerScript.log("purchaseEquipment", `Failed to purchase '${equipName}' for Gang member '${memberName}'`); - } + if (res) { + workerScript.log("purchaseEquipment", `Purchased '${equipName}' for Gang member '${memberName}'`); + } else { + workerScript.log("purchaseEquipment", `Failed to purchase '${equipName}' for Gang member '${memberName}'`); } return res; From 486d02557265f0d42f11de4dca749650c616beab Mon Sep 17 00:00:00 2001 From: Olivier Gagnon Date: Thu, 11 Mar 2021 20:19:00 -0500 Subject: [PATCH 17/19] Gang ascension is less effective as the multiplier goes up, Gang territory gain scales with Gang power. --- src/Gang.js | 46 +++++++++++++++++++++++++++++++++++----------- 1 file changed, 35 insertions(+), 11 deletions(-) diff --git a/src/Gang.js b/src/Gang.js index b0fa2c82b..0aa0c03a4 100644 --- a/src/Gang.js +++ b/src/Gang.js @@ -270,13 +270,19 @@ Gang.prototype.processGains = function(numCycles=1, player) { } } +function calculateTerritoryGain(winGang, loseGang) { + const powerBonus = Math.max(1, 1+Math.log(AllGangs[winGang].power/AllGangs[loseGang].power)/Math.log(50)); + const gains = Math.min(AllGangs[loseGang].territory, powerBonus*0.0001*(Math.random()+.5)) + return gains; +} + Gang.prototype.processTerritoryAndPowerGains = function(numCycles=1) { this.storedTerritoryAndPowerCycles += numCycles; if (this.storedTerritoryAndPowerCycles < CyclesPerTerritoryAndPowerUpdate) { return; } this.storedTerritoryAndPowerCycles -= CyclesPerTerritoryAndPowerUpdate; // Process power first - var gangName = this.facName; + const gangName = this.facName; for (const name in AllGangs) { if (AllGangs.hasOwnProperty(name)) { if (name == gangName) { @@ -327,12 +333,14 @@ Gang.prototype.processTerritoryAndPowerGains = function(numCycles=1) { const otherPwr = AllGangs[otherGang].power; const thisChance = thisPwr / (thisPwr + otherPwr); + if (Math.random() < thisChance) { if (AllGangs[otherGang].territory <= 0) { return; } - AllGangs[thisGang].territory += 0.0001; - AllGangs[otherGang].territory -= 0.0001; + const territoryGain = calculateTerritoryGain(thisGang, otherGang); + AllGangs[thisGang].territory += territoryGain; + AllGangs[otherGang].territory -= territoryGain; if (thisGang === gangName) { this.clash(true); // Player won AllGangs[otherGang].power *= (1 / 1.01); @@ -345,8 +353,9 @@ Gang.prototype.processTerritoryAndPowerGains = function(numCycles=1) { if (AllGangs[thisGang].territory <= 0) { return; } - AllGangs[thisGang].territory -= 0.0001; - AllGangs[otherGang].territory += 0.0001; + const territoryGain = calculateTerritoryGain(otherGang, thisGang); + AllGangs[thisGang].territory -= territoryGain; + AllGangs[otherGang].territory += territoryGain; if (thisGang === gangName) { this.clash(false); // Player lost } else if (otherGang === gangName) { @@ -790,6 +799,20 @@ GangMember.prototype.ascend = function() { }; } +GangMember.prototype.getAscensionEfficiency = function() { + function formula(mult) { + return 1/(1+Math.log(mult)/Math.log(10)); + } + return { + hack: formula(this.hack_asc_mult), + str: formula(this.str_asc_mult), + def: formula(this.def_asc_mult), + dex: formula(this.dex_asc_mult), + agi: formula(this.agi_asc_mult), + cha: formula(this.cha_asc_mult), + }; +} + // Returns the multipliers that would be gained from ascension GangMember.prototype.getAscensionResults = function() { /** @@ -814,13 +837,14 @@ GangMember.prototype.getAscensionResults = function() { } // Subtract 1 because we're only interested in the actual "bonus" part + const eff = this.getAscensionEfficiency(); return { - hack: (Math.max(0, hack - 1) * AscensionMultiplierRatio), - str: (Math.max(0, str - 1) * AscensionMultiplierRatio), - def: (Math.max(0, def - 1) * AscensionMultiplierRatio), - dex: (Math.max(0, dex - 1) * AscensionMultiplierRatio), - agi: (Math.max(0, agi - 1) * AscensionMultiplierRatio), - cha: (Math.max(0, cha - 1) * AscensionMultiplierRatio), + hack: (Math.max(0, hack - 1) * AscensionMultiplierRatio * eff.hack), + str: (Math.max(0, str - 1) * AscensionMultiplierRatio * eff.str), + def: (Math.max(0, def - 1) * AscensionMultiplierRatio * eff.def), + dex: (Math.max(0, dex - 1) * AscensionMultiplierRatio * eff.dex), + agi: (Math.max(0, agi - 1) * AscensionMultiplierRatio * eff.agi), + cha: (Math.max(0, cha - 1) * AscensionMultiplierRatio * eff.cha), } } From cae28e2d250ec15441caf7f43c55675d4e5b5987 Mon Sep 17 00:00:00 2001 From: Olivier Gagnon Date: Thu, 11 Mar 2021 20:37:58 -0500 Subject: [PATCH 18/19] softReset now accepts a callback script like installAugmentations --- src/Augmentation/AugmentationHelpers.jsx | 20 +------------- src/Constants.ts | 7 ++++- src/NetscriptFunctions.js | 33 ++++++++++++++++++++++-- 3 files changed, 38 insertions(+), 22 deletions(-) diff --git a/src/Augmentation/AugmentationHelpers.jsx b/src/Augmentation/AugmentationHelpers.jsx index fe82cf539..53f417c91 100644 --- a/src/Augmentation/AugmentationHelpers.jsx +++ b/src/Augmentation/AugmentationHelpers.jsx @@ -2054,7 +2054,7 @@ function applyAugmentation(aug, reapply=false) { } } -function installAugmentations(cbScript=null) { +function installAugmentations() { if (Player.queuedAugmentations.length == 0) { dialogBoxCreate("You have not purchased any Augmentations to install!"); return false; @@ -2074,24 +2074,6 @@ function installAugmentations(cbScript=null) { "to install the following Augmentations:
    " + augmentationList + "
    You wake up in your home...you feel different..."); prestigeAugmentation(); - - //Run a script after prestiging - if (cbScript && isString(cbScript)) { - var home = Player.getHomeComputer(); - for (const script of home.scripts) { - if (script.filename === cbScript) { - const ramUsage = script.ramUsage; - const ramAvailable = home.maxRam - home.ramUsed; - if (ramUsage > ramAvailable) { - return; // Not enough RAM - } - const runningScriptObj = new RunningScript(script, []); // No args - runningScriptObj.threads = 1; // Only 1 thread - - startWorkerScript(runningScriptObj, home); - } - } - } } function augmentationExists(name) { diff --git a/src/Constants.ts b/src/Constants.ts index 7120d6594..099b4f038 100644 --- a/src/Constants.ts +++ b/src/Constants.ts @@ -228,19 +228,24 @@ export let CONSTANTS: IMap = { LatestUpdate: ` - v0.49.0 - 2021-XX-XX Source-File -1 + v0.49.0 - 2021-03-11 Source-File -1 ------- Source-File -1 * For advanced players: The game now embraces exploits and will reward players for doing so. + Gang + * ascension is less effective as the ascension multiplier goes up. + * territory gain scales with power difference. + Netscript * 'gang.getEquipmentStats' returns the stats of the equipment. * 'gang.getTaskStats' returns the stats of a task. * 'getCrimeStats' returns the stats of a crime. * Crashes should now print the ns stack trace. * Log messages are now more consistent. + * 'softReset' now accepts a callback script like 'installAugmentations' Misc. * Minor formatting under Hacking>Active Scripts diff --git a/src/NetscriptFunctions.js b/src/NetscriptFunctions.js index 7bca5fc5a..8200244eb 100644 --- a/src/NetscriptFunctions.js +++ b/src/NetscriptFunctions.js @@ -74,6 +74,8 @@ import { AddToAllServers, createUniqueRandomIp, } from "./Server/AllServers"; +import { RunningScript } from "./Script/RunningScript"; +import { startWorkerScript } from "./NetscriptWorker"; import { Server } from "./Server/Server"; import { GetServerByHostname, @@ -529,6 +531,31 @@ function NetscriptFunctions(workerScript) { return Augmentations[name]; } + 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); + } + } + } + } + return { hacknet : { numNodes : function() { @@ -3242,7 +3269,8 @@ function NetscriptFunctions(workerScript) { workerScript.log("softReset", "Soft resetting. This will cause this script to be killed"); setTimeoutRef(() => { - prestigeAugmentation(cbScript); + prestigeAugmentation(); + runAfterReset(cbScript); }, 0); // Prevent workerScript from "finishing execution naturally" @@ -3260,7 +3288,8 @@ function NetscriptFunctions(workerScript) { Player.gainIntelligenceExp(CONSTANTS.IntelligenceSingFnBaseExpGain); workerScript.log("installAugmentations", "Installing Augmentations. This will cause this script to be killed"); setTimeoutRef(() => { - installAugmentations(cbScript); + installAugmentations(); + runAfterReset(cbScript); }, 0); workerScript.running = false; // Prevent workerScript from "finishing execution naturally" From 123628ec0b81383516e727f5a88c7262c99c84cd Mon Sep 17 00:00:00 2001 From: Olivier Gagnon Date: Thu, 11 Mar 2021 20:39:31 -0500 Subject: [PATCH 19/19] update changelog and build 0.49 --- dist/engine.bundle.js | 4 ++-- dist/engineStyle.bundle.js | 2 +- dist/engineStyle.css | 29 +++++++++++++++++++++++++++++ dist/vendor.bundle.js | 22 +++++++++++----------- doc/source/changelog.rst | 27 +++++++++++++++++++++++++++ index.html | 28 ++++++++++++++-------------- 6 files changed, 84 insertions(+), 28 deletions(-) diff --git a/dist/engine.bundle.js b/dist/engine.bundle.js index 3d702753b..c69dd13d6 100644 --- a/dist/engine.bundle.js +++ b/dist/engine.bundle.js @@ -1,4 +1,4 @@ -!function(e){function t(t){for(var r,o,s=t[0],l=t[1],c=t[2],m=0,p=[];m{t.delay=null,n()},e),t.delayResolve=n})}function s(e,t,n=null){var r="";null!=n&&(r=" (Line "+function(e,t){var n=t.scriptRef.codeCode();try{return((n=n.substring(0,e.start)).match(/\n/g)||[]).length+1}catch(e){return-1}}(n,e)+")");return"|"+e.serverIp+"|"+e.name+"|"+t+r}function l(e,t,n){const r=e.scriptRef.threads;if(!n)return isNaN(r)||r<1?1:r;const a=0|n;if(isNaN(n)||a<1)throw s(e,`Invalid thread count passed to ${t}: ${n}. Threads must be a positive number.`);if(n>r)throw s(e,`Too many threads requested by ${t}. Requested: ${n}. Has: ${r}.`);return a}function c(e){if(!Object(i.isString)(e))return!1;let t=e.split("|");if(4!=t.length)return!1;var n=t[1];return!!Object(a.isValidIPAddress)(n)}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});const r=n(111);function a(e,t={}){const n=`color: ${null!=t.color?t.color:"var(--my-font-color)"}; background-color:var(--my-background-color);${void 0===t.id?" white-space:pre-wrap;":""}`,a=`${e}`;r.getElementById("terminal-input").insertAdjacentHTML("beforebegin",a),function(){const e=r.getElementById("terminal-container");e.scrollTop=e.scrollHeight}()}t.post=function(e){a(e)},t.postError=function(e){a(`ERROR: ${e}`,{color:"#ff2929"})},t.hackProgressBarPost=function(e){a(e,{id:"hack-progress-bar"})},t.hackProgressPost=function(e){a(e,{id:"hack-progress"})},t.postContent=a},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});const r=n(49);function a(e){return e.every(r.isString)}t.replaceAt=function(e,t,n){return e.substr(0,t)+n+e.substr(t+n.length)},t.convertTimeMsToTimeElapsedString=function(e){const t=Math.floor(e/1e3),n=Math.floor(t/86400),r=t%86400,a=Math.floor(r/3600),i=r%3600,o=Math.floor(i/60);let s="";return n>0&&(s+=`${n} days `),a>0&&(s+=`${a} hours `),o>0&&(s+=`${o} minutes `),s+=`${i%60} seconds`},t.longestCommonStart=function(e){if(!a(e))return"";if(0===e.length)return"";const t=e.concat().sort(),n=t[0],r=t[t.length-1],i=n.length;let o=0;const s=(e,t)=>e.toUpperCase()===t.toUpperCase();for(;o=0;e--)if(1===n[e].nodeType)return!0;return!1},t.generateRandomString=function(e){let t="";const n="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";for(let r=0;r
    In this game you control a set of Nodes and use them to try and defeat an enemy. Your Nodes are colored blue, while the enemy's are red. There are also other nodes on the map colored gray that initially belong to neither you nor the enemy. The goal of the game is to capture all of the enemy's Database nodes within the time limit. If you fail to do this, you will lose.

    Each Node has three stats: Attack, Defense, and HP. There are five different actions that a Node can take:

    Attack - Targets an enemy Node and lowers its HP. The effectiveness is determined by the owner's Attack, the Player's hacking level, and the enemy's defense.

    Scan - Targets an enemy Node and lowers its Defense. The effectiveness is determined by the owner's Attack, the Player's hacking level, and the enemy's defense.

    Weaken - Targets an enemy Node and lowers its Attack. The effectiveness is determined by the owner's Attack, the Player's hacking level, and the enemy's defense.

    Fortify - Raises the Node's Defense. The effectiveness is determined by your hacking level.

    Overflow - Raises the Node's Attack but lowers its Defense. The effectiveness is determined by your hacking level.

    Note that when determining the effectiveness of the above actions, the TOTAL Attack or Defense of the team is used, not just the Attack/Defense of the individual Node that is performing the action.

    To capture a Node, you must lower its HP down to 0.

    There are six different types of Nodes:

    CPU Core - These are your main Nodes that are used to perform actions. Capable of performing every action

    Firewall - Nodes with high defense. These Nodes can 'Fortify'

    Database - A special type of Node. The player's objective is to conquer all of the enemy's Database Nodes within the time limit. These Nodes cannot perform any actions

    Spam - Conquering one of these Nodes will slow the enemy's trace, giving the player additional time to complete the mission. These Nodes cannot perform any actions

    Transfer - Conquering one of these nodes will increase the Attack of all of your CPU Cores by a small fixed percentage. These Nodes are capable of performing every action except the 'Attack' action

    Shield - Nodes with high defense. These Nodes can 'Fortify'

    To assign an action to a Node, you must first select one of your Nodes. This can be done by simply clicking on it. Double-clicking a node will select all of your Nodes of the same type (e.g. select all CPU Core Nodes or all Transfer Nodes). Note that only Nodes that can perform actions (CPU Core, Transfer, Shield, Firewall) can be selected. Selected Nodes will be denoted with a white highlight. After selecting a Node or multiple Nodes, select its action using the Action Buttons near the top of the screen. Every action also has a corresponding keyboard shortcut.

    For certain actions such as attacking, scanning, and weakening, the Node performing the action must have a target. To target another node, simply click-and-drag from the 'source' Node to a target. A Node can only have one target, and you can target any Node that is adjacent to one of your Nodes (immediately above, below, or to the side. NOT diagonal). Furthermore, only CPU Cores and Transfer Nodes can target, since they are the only ones that can perform the related actions. To remove a target, you can simply click on the line that represents the connection between one of your Nodes and its target. Alternatively, you can select the 'source' Node and click the 'Drop Connection' button, or press 'd'.

    Other Notes:

    -Whenever a miscellenaous Node (not owned by the player or enemy) is conquered, the defense of all remaining miscellaneous Nodes that are not actively being targeted will increase by a fixed percentage.

    -Whenever a Node is conquered, its stats are significantly reduced

    -Miscellaneous Nodes slowly raise their defense over time

    -Nodes slowly regenerate health over time.",MillisecondsPer20Hours:72e6,GameCyclesPer20Hours:36e4,MillisecondsPer10Hours:36e6,GameCyclesPer10Hours:18e4,MillisecondsPer8Hours:288e5,GameCyclesPer8Hours:144e3,MillisecondsPer4Hours:144e5,GameCyclesPer4Hours:72e3,MillisecondsPer2Hours:72e5,GameCyclesPer2Hours:36e3,MillisecondsPerHour:36e5,GameCyclesPerHour:18e3,MillisecondsPerHalfHour:18e5,GameCyclesPerHalfHour:9e3,MillisecondsPerQuarterHour:9e5,GameCyclesPerQuarterHour:4500,MillisecondsPerFiveMinutes:3e5,GameCyclesPerFiveMinutes:1500,FactionWorkHacking:"Faction Hacking Work",FactionWorkField:"Faction Field Work",FactionWorkSecurity:"Faction Security Work",WorkTypeCompany:"Working for Company",WorkTypeCompanyPartTime:"Working for Company part-time",WorkTypeFaction:"Working for Faction",WorkTypeCreateProgram:"Working on Create a Program",WorkTypeStudyClass:"Studying or Taking a class at university",WorkTypeCrime:"Committing a crime",ClassStudyComputerScience:"studying Computer Science",ClassDataStructures:"taking a Data Structures course",ClassNetworks:"taking a Networks course",ClassAlgorithms:"taking an Algorithms course",ClassManagement:"taking a Management course",ClassLeadership:"taking a Leadership course",ClassGymStrength:"training your strength at a gym",ClassGymDefense:"training your defense at a gym",ClassGymDexterity:"training your dexterity at a gym",ClassGymAgility:"training your agility at a gym",ClassDataStructuresBaseCost:40,ClassNetworksBaseCost:80,ClassAlgorithmsBaseCost:320,ClassManagementBaseCost:160,ClassLeadershipBaseCost:320,ClassGymBaseCost:120,ClassStudyComputerScienceBaseExp:.5,ClassDataStructuresBaseExp:1,ClassNetworksBaseExp:2,ClassAlgorithmsBaseExp:4,ClassManagementBaseExp:2,ClassLeadershipBaseExp:4,CrimeShoplift:"shoplift",CrimeRobStore:"rob a store",CrimeMug:"mug someone",CrimeLarceny:"commit larceny",CrimeDrugs:"deal drugs",CrimeBondForgery:"forge corporate bonds",CrimeTraffickArms:"traffick illegal arms",CrimeHomicide:"commit homicide",CrimeGrandTheftAuto:"commit grand theft auto",CrimeKidnap:"kidnap someone for ransom",CrimeAssassination:"assassinate a high-profile target",CrimeHeist:"pull off the ultimate heist",CodingContractBaseFactionRepGain:2500,CodingContractBaseCompanyRepGain:4e3,CodingContractBaseMoneyGain:75e6,TotalNumBitNodes:24,LatestUpdate:"\n v0.48.0 - ASCII\n -------\n\n ASCII\n * Travel Agency now displays a world map\n * Cities are now top view of metro station maps\n\n Netscript\n * 'softReset' is a new netscript function that performs a soft reset\n regardless of if the player has bought augmentations or not.\n * 'getAugmentationStats' is a new netscript function that returns the stats of\n an augmentation.\n * getCharacterInformation now additionally returns exp\n * pid resets back to 1 when installing or destroying a BitNode.\n * New '.ns' scripts start with a main function.\n * 'hacknet.maxNumNodes' returns the maximum number of hacknet nodes.\n\n Bladeburner\n * Current stamina will scale as max stamina increases, this prevents players\n from having very high penalty when they gain huge amount of exp at the \n start of a reset.\n\n Misc.\n * Fixed an issue where SF3 was listed as infinitly repeatable and SF12 as\n having a limit of 3.\n * Fixed an issue where the gang equipment screen would freeze the game if a \n script installed augmentations while it is open.\n * All BonusTime now displays in the 'H M S' format.\n * Donation textbox style updated to match the rest of the game.\n * Corporation name style updated to match the rest of the game.\n * minor formatting under Hacking>Active Scripts\n * typo in BN12 description\n * BN12 now reduces contract money\n * Character>Stats percentages are aligned, server and hacknet limit are\n displayed, if the player has SF5 the reduces stats are shown.\n * Character>Augmentations now displays by how much the player stats will\n increase.\n * Character>Augmentations has a badge indicating how many augs the player\n has bought but not installed\n * Character>Factions has a badge indicating how many factions have pending\n invites.\n "}},function(e,t,n){"use strict";n.r(t),function(e){n.d(t,"dialogBoxCreate",function(){return s}),n.d(t,"dialogBoxOpened",function(){return o});var r=n(27);let a=[];function i(){o&&0!==a.length&&(a[0].remove(),a.shift(),0==a.length?o=!1:a[0].style.visibility="visible")}e(document).click(function(t){o&&a.length>=1&&(e(t.target).closest(a[0]).length||i())}),e(document).on("click",".dialog-box-close-button",function(e){i()}),document.addEventListener("keydown",function(e){e.keyCode==r.KEY.ESC&&o&&(i(),e.preventDefault())});let o=!1;function s(e,t=!1){var n=document.createElement("div");n.setAttribute("class","dialog-box-container");var r=document.createElement("div");r.setAttribute("class","dialog-box-content");var i,s=document.createElement("span");s.setAttribute("class","dialog-box-close-button"),s.innerHTML="×",t?(i=document.createElement("pre")).innerHTML=e:(i=document.createElement("p")).innerHTML=e.replace(/(?:\r\n|\r|\n)/g,"
    "),r.appendChild(s),r.appendChild(i),n.appendChild(r),document.body.appendChild(n),a.length>=1&&(n.style.visibility="hidden"),a.push(n),setTimeout(function(){o=!0},400)}}.call(this,n(85))},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.RamCostConstants={ScriptBaseRamCost:1.6,ScriptDomRamCost:25,ScriptHackRamCost:.1,ScriptHackAnalyzeRamCost:1,ScriptGrowRamCost:.15,ScriptGrowthAnalyzeRamCost:1,ScriptWeakenRamCost:.15,ScriptScanRamCost:.2,ScriptPortProgramRamCost:.05,ScriptRunRamCost:1,ScriptExecRamCost:1.3,ScriptSpawnRamCost:2,ScriptScpRamCost:.6,ScriptKillRamCost:.5,ScriptHasRootAccessRamCost:.05,ScriptGetHostnameRamCost:.05,ScriptGetHackingLevelRamCost:.05,ScriptGetMultipliersRamCost:4,ScriptGetServerRamCost:.1,ScriptFileExistsRamCost:.1,ScriptIsRunningRamCost:.1,ScriptHacknetNodesRamCost:4,ScriptHNUpgLevelRamCost:.4,ScriptHNUpgRamRamCost:.6,ScriptHNUpgCoreRamCost:.8,ScriptGetStockRamCost:2,ScriptBuySellStockRamCost:2.5,ScriptGetPurchaseServerRamCost:.25,ScriptPurchaseServerRamCost:2.25,ScriptGetPurchasedServerLimit:.05,ScriptGetPurchasedServerMaxRam:.05,ScriptRoundRamCost:.05,ScriptReadWriteRamCost:1,ScriptArbScriptRamCost:1,ScriptGetScriptRamCost:.1,ScriptGetHackTimeRamCost:.05,ScriptGetFavorToDonate:.1,ScriptCodingContractBaseRamCost:10,ScriptSleeveBaseRamCost:4,ScriptSingularityFn1RamCost:2,ScriptSingularityFn2RamCost:3,ScriptSingularityFn3RamCost:5,ScriptGangApiBaseRamCost:4,ScriptBladeburnerApiBaseRamCost:4},t.RamCosts={hacknet:{numNodes:()=>0,purchaseNode:()=>0,getPurchaseNodeCost:()=>0,getNodeStats:()=>0,upgradeLevel:()=>0,upgradeRam:()=>0,upgradeCore:()=>0,upgradeCache:()=>0,getLevelUpgradeCost:()=>0,getRamUpgradeCost:()=>0,getCoreUpgradeCost:()=>0,getCacheUpgradeCost:()=>0,numHashes:()=>0,hashCost:()=>0,spendHashes:()=>0},sprintf:()=>0,vsprintf:()=>0,scan:()=>t.RamCostConstants.ScriptScanRamCost,hack:()=>t.RamCostConstants.ScriptHackRamCost,hackAnalyzeThreads:()=>t.RamCostConstants.ScriptHackAnalyzeRamCost,hackAnalyzePercent:()=>t.RamCostConstants.ScriptHackAnalyzeRamCost,hackChance:()=>t.RamCostConstants.ScriptHackAnalyzeRamCost,sleep:()=>0,grow:()=>t.RamCostConstants.ScriptGrowRamCost,growthAnalyze:()=>t.RamCostConstants.ScriptGrowthAnalyzeRamCost,weaken:()=>t.RamCostConstants.ScriptWeakenRamCost,print:()=>0,tprint:()=>0,clearLog:()=>0,disableLog:()=>0,enableLog:()=>0,isLogEnabled:()=>0,getScriptLogs:()=>0,nuke:()=>t.RamCostConstants.ScriptPortProgramRamCost,brutessh:()=>t.RamCostConstants.ScriptPortProgramRamCost,ftpcrack:()=>t.RamCostConstants.ScriptPortProgramRamCost,relaysmtp:()=>t.RamCostConstants.ScriptPortProgramRamCost,httpworm:()=>t.RamCostConstants.ScriptPortProgramRamCost,sqlinject:()=>t.RamCostConstants.ScriptPortProgramRamCost,run:()=>t.RamCostConstants.ScriptRunRamCost,exec:()=>t.RamCostConstants.ScriptExecRamCost,spawn:()=>t.RamCostConstants.ScriptSpawnRamCost,kill:()=>t.RamCostConstants.ScriptKillRamCost,killall:()=>t.RamCostConstants.ScriptKillRamCost,exit:()=>0,scp:()=>t.RamCostConstants.ScriptScpRamCost,ls:()=>t.RamCostConstants.ScriptScanRamCost,ps:()=>t.RamCostConstants.ScriptScanRamCost,hasRootAccess:()=>t.RamCostConstants.ScriptHasRootAccessRamCost,getIp:()=>t.RamCostConstants.ScriptGetHostnameRamCost,getHostname:()=>t.RamCostConstants.ScriptGetHostnameRamCost,getHackingLevel:()=>t.RamCostConstants.ScriptGetHackingLevelRamCost,getHackingMultipliers:()=>t.RamCostConstants.ScriptGetMultipliersRamCost,getHacknetMultipliers:()=>t.RamCostConstants.ScriptGetMultipliersRamCost,getBitNodeMultipliers:()=>t.RamCostConstants.ScriptGetMultipliersRamCost,getServerMoneyAvailable:()=>t.RamCostConstants.ScriptGetServerRamCost,getServerSecurityLevel:()=>t.RamCostConstants.ScriptGetServerRamCost,getServerBaseSecurityLevel:()=>t.RamCostConstants.ScriptGetServerRamCost,getServerMinSecurityLevel:()=>t.RamCostConstants.ScriptGetServerRamCost,getServerRequiredHackingLevel:()=>t.RamCostConstants.ScriptGetServerRamCost,getServerMaxMoney:()=>t.RamCostConstants.ScriptGetServerRamCost,getServerGrowth:()=>t.RamCostConstants.ScriptGetServerRamCost,getServerNumPortsRequired:()=>t.RamCostConstants.ScriptGetServerRamCost,getServerRam:()=>t.RamCostConstants.ScriptGetServerRamCost,serverExists:()=>t.RamCostConstants.ScriptGetServerRamCost,fileExists:()=>t.RamCostConstants.ScriptFileExistsRamCost,isRunning:()=>t.RamCostConstants.ScriptIsRunningRamCost,getStockSymbols:()=>t.RamCostConstants.ScriptGetStockRamCost,getStockPrice:()=>t.RamCostConstants.ScriptGetStockRamCost,getStockAskPrice:()=>t.RamCostConstants.ScriptGetStockRamCost,getStockBidPrice:()=>t.RamCostConstants.ScriptGetStockRamCost,getStockPosition:()=>t.RamCostConstants.ScriptGetStockRamCost,getStockMaxShares:()=>t.RamCostConstants.ScriptGetStockRamCost,getStockPurchaseCost:()=>t.RamCostConstants.ScriptGetStockRamCost,getStockSaleGain:()=>t.RamCostConstants.ScriptGetStockRamCost,buyStock:()=>t.RamCostConstants.ScriptBuySellStockRamCost,sellStock:()=>t.RamCostConstants.ScriptBuySellStockRamCost,shortStock:()=>t.RamCostConstants.ScriptBuySellStockRamCost,sellShort:()=>t.RamCostConstants.ScriptBuySellStockRamCost,placeOrder:()=>t.RamCostConstants.ScriptBuySellStockRamCost,cancelOrder:()=>t.RamCostConstants.ScriptBuySellStockRamCost,getOrders:()=>t.RamCostConstants.ScriptBuySellStockRamCost,getStockVolatility:()=>t.RamCostConstants.ScriptBuySellStockRamCost,getStockForecast:()=>t.RamCostConstants.ScriptBuySellStockRamCost,purchase4SMarketData:()=>t.RamCostConstants.ScriptBuySellStockRamCost,purchase4SMarketDataTixApi:()=>t.RamCostConstants.ScriptBuySellStockRamCost,getPurchasedServerLimit:()=>t.RamCostConstants.ScriptGetPurchasedServerLimit,getPurchasedServerMaxRam:()=>t.RamCostConstants.ScriptGetPurchasedServerMaxRam,getPurchasedServerCost:()=>t.RamCostConstants.ScriptGetPurchaseServerRamCost,purchaseServer:()=>t.RamCostConstants.ScriptPurchaseServerRamCost,deleteServer:()=>t.RamCostConstants.ScriptPurchaseServerRamCost,getPurchasedServers:()=>t.RamCostConstants.ScriptPurchaseServerRamCost,write:()=>t.RamCostConstants.ScriptReadWriteRamCost,tryWrite:()=>t.RamCostConstants.ScriptReadWriteRamCost,read:()=>t.RamCostConstants.ScriptReadWriteRamCost,peek:()=>t.RamCostConstants.ScriptReadWriteRamCost,clear:()=>t.RamCostConstants.ScriptReadWriteRamCost,getPortHandle:()=>10*t.RamCostConstants.ScriptReadWriteRamCost,rm:()=>t.RamCostConstants.ScriptReadWriteRamCost,scriptRunning:()=>t.RamCostConstants.ScriptArbScriptRamCost,scriptKill:()=>t.RamCostConstants.ScriptArbScriptRamCost,getScriptName:()=>0,getScriptRam:()=>t.RamCostConstants.ScriptGetScriptRamCost,getHackTime:()=>t.RamCostConstants.ScriptGetHackTimeRamCost,getGrowTime:()=>t.RamCostConstants.ScriptGetHackTimeRamCost,getWeakenTime:()=>t.RamCostConstants.ScriptGetHackTimeRamCost,getScriptIncome:()=>t.RamCostConstants.ScriptGetScriptRamCost,getScriptExpGain:()=>t.RamCostConstants.ScriptGetScriptRamCost,nFormat:()=>0,getTimeSinceLastAug:()=>t.RamCostConstants.ScriptGetHackTimeRamCost,prompt:()=>0,wget:()=>0,getFavorToDonate:()=>t.RamCostConstants.ScriptGetFavorToDonate,universityCourse:()=>t.RamCostConstants.ScriptSingularityFn1RamCost,gymWorkout:()=>t.RamCostConstants.ScriptSingularityFn1RamCost,travelToCity:()=>t.RamCostConstants.ScriptSingularityFn1RamCost,purchaseTor:()=>t.RamCostConstants.ScriptSingularityFn1RamCost,purchaseProgram:()=>t.RamCostConstants.ScriptSingularityFn1RamCost,getStats:()=>t.RamCostConstants.ScriptSingularityFn1RamCost/4,getCharacterInformation:()=>t.RamCostConstants.ScriptSingularityFn1RamCost/4,isBusy:()=>t.RamCostConstants.ScriptSingularityFn1RamCost/4,stopAction:()=>t.RamCostConstants.ScriptSingularityFn1RamCost/2,upgradeHomeRam:()=>t.RamCostConstants.ScriptSingularityFn2RamCost,getUpgradeHomeRamCost:()=>t.RamCostConstants.ScriptSingularityFn2RamCost/2,workForCompany:()=>t.RamCostConstants.ScriptSingularityFn2RamCost,applyToCompany:()=>t.RamCostConstants.ScriptSingularityFn2RamCost,getCompanyRep:()=>t.RamCostConstants.ScriptSingularityFn2RamCost/3,getCompanyFavor:()=>t.RamCostConstants.ScriptSingularityFn2RamCost/3,getCompanyFavorGain:()=>t.RamCostConstants.ScriptSingularityFn2RamCost/4,checkFactionInvitations:()=>t.RamCostConstants.ScriptSingularityFn2RamCost,joinFaction:()=>t.RamCostConstants.ScriptSingularityFn2RamCost,workForFaction:()=>t.RamCostConstants.ScriptSingularityFn2RamCost,getFactionRep:()=>t.RamCostConstants.ScriptSingularityFn2RamCost/3,getFactionFavor:()=>t.RamCostConstants.ScriptSingularityFn2RamCost/3,getFactionFavorGain:()=>t.RamCostConstants.ScriptSingularityFn2RamCost/4,donateToFaction:()=>t.RamCostConstants.ScriptSingularityFn3RamCost,createProgram:()=>t.RamCostConstants.ScriptSingularityFn3RamCost,commitCrime:()=>t.RamCostConstants.ScriptSingularityFn3RamCost,getCrimeChance:()=>t.RamCostConstants.ScriptSingularityFn3RamCost,getOwnedAugmentations:()=>t.RamCostConstants.ScriptSingularityFn3RamCost,getOwnedSourceFiles:()=>t.RamCostConstants.ScriptSingularityFn3RamCost,getAugmentationsFromFaction:()=>t.RamCostConstants.ScriptSingularityFn3RamCost,getAugmentationPrereq:()=>t.RamCostConstants.ScriptSingularityFn3RamCost,getAugmentationCost:()=>t.RamCostConstants.ScriptSingularityFn3RamCost,getAugmentationStats:()=>t.RamCostConstants.ScriptSingularityFn3RamCost,purchaseAugmentation:()=>t.RamCostConstants.ScriptSingularityFn3RamCost,softReset:()=>t.RamCostConstants.ScriptSingularityFn3RamCost,installAugmentations:()=>t.RamCostConstants.ScriptSingularityFn3RamCost,gang:{getMemberNames:()=>t.RamCostConstants.ScriptGangApiBaseRamCost/4,getGangInformation:()=>t.RamCostConstants.ScriptGangApiBaseRamCost/2,getOtherGangInformation:()=>t.RamCostConstants.ScriptGangApiBaseRamCost/2,getMemberInformation:()=>t.RamCostConstants.ScriptGangApiBaseRamCost/2,canRecruitMember:()=>t.RamCostConstants.ScriptGangApiBaseRamCost/4,recruitMember:()=>t.RamCostConstants.ScriptGangApiBaseRamCost/2,getTaskNames:()=>t.RamCostConstants.ScriptGangApiBaseRamCost/4,setMemberTask:()=>t.RamCostConstants.ScriptGangApiBaseRamCost/2,getEquipmentNames:()=>t.RamCostConstants.ScriptGangApiBaseRamCost/4,getEquipmentCost:()=>t.RamCostConstants.ScriptGangApiBaseRamCost/2,getEquipmentType:()=>t.RamCostConstants.ScriptGangApiBaseRamCost/2,purchaseEquipment:()=>t.RamCostConstants.ScriptGangApiBaseRamCost,ascendMember:()=>t.RamCostConstants.ScriptGangApiBaseRamCost,setTerritoryWarfare:()=>t.RamCostConstants.ScriptGangApiBaseRamCost/2,getChanceToWinClash:()=>t.RamCostConstants.ScriptGangApiBaseRamCost,getBonusTime:()=>0},bladeburner:{getContractNames:()=>t.RamCostConstants.ScriptBladeburnerApiBaseRamCost/10,getOperationNames:()=>t.RamCostConstants.ScriptBladeburnerApiBaseRamCost/10,getBlackOpNames:()=>t.RamCostConstants.ScriptBladeburnerApiBaseRamCost/10,getBlackOpRank:()=>t.RamCostConstants.ScriptBladeburnerApiBaseRamCost/2,getGeneralActionNames:()=>t.RamCostConstants.ScriptBladeburnerApiBaseRamCost/10,getSkillNames:()=>t.RamCostConstants.ScriptBladeburnerApiBaseRamCost/10,startAction:()=>t.RamCostConstants.ScriptBladeburnerApiBaseRamCost,stopBladeburnerAction:()=>t.RamCostConstants.ScriptBladeburnerApiBaseRamCost/2,getCurrentAction:()=>t.RamCostConstants.ScriptBladeburnerApiBaseRamCost/4,getActionTime:()=>t.RamCostConstants.ScriptBladeburnerApiBaseRamCost,getActionEstimatedSuccessChance:()=>t.RamCostConstants.ScriptBladeburnerApiBaseRamCost,getActionRepGain:()=>t.RamCostConstants.ScriptBladeburnerApiBaseRamCost,getActionCountRemaining:()=>t.RamCostConstants.ScriptBladeburnerApiBaseRamCost,getActionMaxLevel:()=>t.RamCostConstants.ScriptBladeburnerApiBaseRamCost,getActionCurrentLevel:()=>t.RamCostConstants.ScriptBladeburnerApiBaseRamCost,getActionAutolevel:()=>t.RamCostConstants.ScriptBladeburnerApiBaseRamCost,setActionAutolevel:()=>t.RamCostConstants.ScriptBladeburnerApiBaseRamCost,setActionLevel:()=>t.RamCostConstants.ScriptBladeburnerApiBaseRamCost,getRank:()=>t.RamCostConstants.ScriptBladeburnerApiBaseRamCost,getSkillPoints:()=>t.RamCostConstants.ScriptBladeburnerApiBaseRamCost,getSkillLevel:()=>t.RamCostConstants.ScriptBladeburnerApiBaseRamCost,getSkillUpgradeCost:()=>t.RamCostConstants.ScriptBladeburnerApiBaseRamCost,upgradeSkill:()=>t.RamCostConstants.ScriptBladeburnerApiBaseRamCost,getTeamSize:()=>t.RamCostConstants.ScriptBladeburnerApiBaseRamCost,setTeamSize:()=>t.RamCostConstants.ScriptBladeburnerApiBaseRamCost,getCityEstimatedPopulation:()=>t.RamCostConstants.ScriptBladeburnerApiBaseRamCost,getCityEstimatedCommunities:()=>t.RamCostConstants.ScriptBladeburnerApiBaseRamCost,getCityChaos:()=>t.RamCostConstants.ScriptBladeburnerApiBaseRamCost,getCity:()=>t.RamCostConstants.ScriptBladeburnerApiBaseRamCost,switchCity:()=>t.RamCostConstants.ScriptBladeburnerApiBaseRamCost,getStamina:()=>t.RamCostConstants.ScriptBladeburnerApiBaseRamCost,joinBladeburnerFaction:()=>t.RamCostConstants.ScriptBladeburnerApiBaseRamCost,joinBladeburnerDivision:()=>t.RamCostConstants.ScriptBladeburnerApiBaseRamCost,getBonusTime:()=>0},codingcontract:{attempt:()=>t.RamCostConstants.ScriptCodingContractBaseRamCost,getContractType:()=>t.RamCostConstants.ScriptCodingContractBaseRamCost/2,getData:()=>t.RamCostConstants.ScriptCodingContractBaseRamCost/2,getDescription:()=>t.RamCostConstants.ScriptCodingContractBaseRamCost/2,getNumTriesRemaining:()=>t.RamCostConstants.ScriptCodingContractBaseRamCost/5},sleeve:{getNumSleeves:()=>t.RamCostConstants.ScriptSleeveBaseRamCost,setToShockRecovery:()=>t.RamCostConstants.ScriptSleeveBaseRamCost,setToSynchronize:()=>t.RamCostConstants.ScriptSleeveBaseRamCost,setToCommitCrime:()=>t.RamCostConstants.ScriptSleeveBaseRamCost,setToUniversityCourse:()=>t.RamCostConstants.ScriptSleeveBaseRamCost,travel:()=>t.RamCostConstants.ScriptSleeveBaseRamCost,setToCompanyWork:()=>t.RamCostConstants.ScriptSleeveBaseRamCost,setToFactionWork:()=>t.RamCostConstants.ScriptSleeveBaseRamCost,setToGymWorkout:()=>t.RamCostConstants.ScriptSleeveBaseRamCost,getSleeveStats:()=>t.RamCostConstants.ScriptSleeveBaseRamCost,getTask:()=>t.RamCostConstants.ScriptSleeveBaseRamCost,getInformation:()=>t.RamCostConstants.ScriptSleeveBaseRamCost,getSleeveAugmentations:()=>t.RamCostConstants.ScriptSleeveBaseRamCost,getSleevePurchasableAugs:()=>t.RamCostConstants.ScriptSleeveBaseRamCost,purchaseSleeveAug:()=>t.RamCostConstants.ScriptSleeveBaseRamCost},heart:{break:()=>0}},t.getRamCost=function(...e){if(0===e.length)return console.warn("No arguments passed to getRamCost()"),0;let n=t.RamCosts[e[0]];for(let t=1;t(ce.loadFactionContent(),Object(f.displayFactionContent)(n),!1)})),e.appendChild(Object(te.createElement)("br"))}();ce.Display.factionsContent.appendChild(e),ce.Display.factionsContent.appendChild(Object(te.createElement)("br")),ce.Display.factionsContent.appendChild(Object(te.createElement)("h1",{innerText:"Outstanding Faction Invitations"})),ce.Display.factionsContent.appendChild(Object(te.createElement)("p",{width:"70%",innerText:"Lists factions you have been invited to, as well as factions you have previously rejected. You can accept these faction invitations at any time."}));var n=Object(te.createElement)("ul");for(t=0;t{if(!t.isTrusted)return!1;Object(f.joinFaction)(y.Factions[e]);for(var n=0;n0&&(ce._lastUpdate=e-n,x.Player.lastUpdate=e-n,ce.updateGame(t)),window.requestAnimationFrame(ce.idleTimer)},updateGame:function(e=1){var t=e*ce._idleSpeed;null==x.Player.totalPlaytime&&(x.Player.totalPlaytime=0),null==x.Player.playtimeSinceLastAug&&(x.Player.playtimeSinceLastAug=0),null==x.Player.playtimeSinceLastBitnode&&(x.Player.playtimeSinceLastBitnode=0),x.Player.totalPlaytime+=t,x.Player.playtimeSinceLastAug+=t,x.Player.playtimeSinceLastBitnode+=t,!0===F.a.actionStarted&&(ce._totalActionTime=F.a.actionTime,ce._actionTimeLeft=F.a.actionTime,ce._actionInProgress=!0,ce._actionProgressBarCount=1,ce._actionProgressStr="[ ]",ce._actionTimeStr="Time left: ",F.a.actionStarted=!1),x.Player.isWorking&&(x.Player.workType==g.CONSTANTS.WorkTypeFaction?x.Player.workForFaction(e):x.Player.workType==g.CONSTANTS.WorkTypeCreateProgram?x.Player.createProgramWork(e):x.Player.workType==g.CONSTANTS.WorkTypeStudyClass?x.Player.takeClass(e):x.Player.workType==g.CONSTANTS.WorkTypeCrime?x.Player.commitCrime(e):x.Player.workType==g.CONSTANTS.WorkTypeCompanyPartTime?x.Player.workPartTime(e):x.Player.work(e)),x.Player.hasWseAccount&&Object(j.processStockPrices)(e),x.Player.inGang()&&x.Player.gang.process(e,x.Player),S.c&&S.b&&S.b.process(e),x.Player.corporation instanceof d.c&&x.Player.corporation.storeCycles(e),x.Player.bladeburner instanceof c.a&&x.Player.bladeburner.storeCycles(e);for(let t=0;t0?(t.innerHTML=e,t.setAttribute("class","notification-on")):(t.innerHTML="",t.setAttribute("class","notification-off")),ce.Counters.createProgramNotifications=10}if(ce.Counters.augmentationsNotifications<=0){e=x.Player.queuedAugmentations.length,t=document.getElementById("augmentations-notification");e>0?(t.innerHTML=e,t.setAttribute("class","notification-on")):(t.innerHTML="",t.setAttribute("class","notification-off")),ce.Counters.augmentationsNotifications=10}if(ce.Counters.checkFactionInvitations<=0){var n=x.Player.checkForFactionInvitations();if(n.length>0){!1===x.Player.firstFacInvRecvd&&(x.Player.firstFacInvRecvd=!0,document.getElementById("factions-tab").style.display="list-item",document.getElementById("character-menu-header").click(),document.getElementById("character-menu-header").click());var r=n[Math.floor(Math.random()*n.length)];Object(f.inviteToFaction)(r)}const e=x.Player.factionInvitations.length,t=document.getElementById("factions-notification");e>0?(t.innerHTML=e,t.setAttribute("class","notification-on")):(t.innerHTML="",t.setAttribute("class","notification-off")),ce.Counters.checkFactionInvitations=100}if(ce.Counters.passiveFactionGrowth<=0){var o=Math.floor(600-ce.Counters.passiveFactionGrowth);Object(f.processPassiveFactionRepGain)(o),ce.Counters.passiveFactionGrowth=600}if(ce.Counters.messages<=0&&(Object(P.b)(),i.Augmentations[s.AugmentationNames.TheRedPill].owned?ce.Counters.messages=4500:ce.Counters.messages=150),ce.Counters.mechanicProcess<=0){if(x.Player.corporation instanceof d.c&&x.Player.corporation.process(),x.Player.bladeburner instanceof c.a)try{x.Player.bladeburner.process()}catch(e){Object(ne.exceptionAlert)("Exception caught in Bladeburner.process(): "+e)}ce.Counters.mechanicProcess=5}ce.Counters.contractGeneration<=0&&(Math.random()<=.25&&Object(p.b)(),ce.Counters.contractGeneration=3e3)},_totalActionTime:0,_actionTimeLeft:0,_actionTimeStr:"Time left: ",_actionProgressStr:"[ ]",_actionProgressBarCount:1,_actionInProgress:!1,updateHackProgress:function(e=1){var t=e*ce._idleSpeed;ce._actionTimeLeft-=t/1e3,ce._actionTimeLeft=Math.max(ce._actionTimeLeft,0);for(var n=Math.round(100*(1-ce._actionTimeLeft/ce._totalActionTime));2*ce._actionProgressBarCount<=n;)ce._actionProgressStr=Object(r.replaceAt)(ce._actionProgressStr,ce._actionProgressBarCount,"|"),ce._actionProgressBarCount+=1;ce._actionTimeStr="Time left: "+Math.max(0,Math.round(ce._actionTimeLeft)).toString()+"s",document.getElementById("hack-progress").innerHTML=ce._actionTimeStr,document.getElementById("hack-progress-bar").innerHTML=ce._actionProgressStr.replace(/ /g," "),n>=100&&(ce._actionInProgress=!1,F.a.finishAction())},closeMainMenuHeader:function(e){for(var t=0;t"+Y.numeralWrapper.formatMoney(K)+" and your Hacknet Nodes generated "+e+"");var V=[t,n,a,s,p,_,A,R,B];x.Player.firstFacInvRecvd?V.push(u):u.style.display="none",x.Player.firstAugPurchased?V.push(m):m.style.display="none",""!==x.Player.companyName?V.push(C):C.style.display="none",x.Player.firstTimeTraveled?V.push(b):b.style.display="none",x.Player.firstProgramAvailable?V.push(i):i.style.display="none",x.Player.hasWseAccount?V.push(O):O.style.display="none",x.Player.bladeburner instanceof c.a?V.push(S):S.style.display="none",x.Player.corporation instanceof d.c?V.push(T):T.style.display="none",x.Player.inGang()?V.push(w):w.style.display="none",ce.closeMainMenuHeader(V)}else{console.log("Initializing new game"),Object(l.initBitNodeMultipliers)(x.Player),Object(W.initSpecialServerIps)(),ce.setDisplayElements(),ce.start(),x.Player.init(),Object(I.initForeignServers)(x.Player.getHomeComputer()),Object(h.initCompanies)(),Object(y.initFactions)(),Object(o.d)(),Object(P.c)(),Object(k.a)(),Object(L.updateSourceFileFlags)(x.Player),document.getElementById("hacking-menu-header").classList.toggle("opened"),document.getElementById("character-menu-header").classList.toggle("opened"),document.getElementById("world-menu-header").classList.toggle("opened"),document.getElementById("help-menu-header").classList.toggle("opened"),u.style.display="none",m.style.display="none",C.style.display="none",O.style.display="none",b.style.display="none",i.style.display="none",S.style.display="none",T.style.display="none",w.style.display="none",B.style.display="none",ce.openMainMenuHeader([t,n,a,s,p,_,A,R]),Object(v.c)(),Object(re.removeLoadingScreen)()}Object(z.a)(),Object(D.d)(),F.a.resetTerminalInput()},setDisplayElements:function(){if(ce.Display.terminalContent=document.getElementById("terminal-container"),$.routing.navigateTo($.Page.Terminal),ce.Display.characterContent=document.getElementById("character-container"),ce.Display.characterContent.style.display="none",ce.Display.scriptEditorContent=document.getElementById("script-editor-container"),ce.Display.scriptEditorContent.style.display="none",ce.Display.activeScriptsContent=document.getElementById("active-scripts-container"),ce.Display.activeScriptsContent.style.display="none",ce.Display.hacknetNodesContent=document.getElementById("hacknet-nodes-container"),ce.Display.hacknetNodesContent.style.display="none",ce.Display.createProgramContent=document.getElementById("create-program-container"),ce.Display.createProgramContent.style.display="none",ce.Display.factionsContent=document.getElementById("factions-container"),ce.Display.factionsContent.style.display="none",ce.Display.factionContent=document.getElementById("faction-container"),ce.Display.factionContent.style.display="none",ce.Display.augmentationsContent=document.getElementById("augmentations-container"),ce.Display.augmentationsContent.style.display="none",ce.Display.tutorialContent=document.getElementById("tutorial-container"),ce.Display.tutorialContent.style.display="none",ce.Display.infiltrationContent=document.getElementById("infiltration-container"),ce.Display.infiltrationContent.style.display="none",ce.Display.stockMarketContent=document.getElementById("stock-market-container"),ce.Display.stockMarketContent.style.display="none",ce.Display.missionContent=document.getElementById("mission-container"),ce.Display.missionContent.style.display="none",ce.Display.characterInfo=document.getElementById("character-content"),ce.Display.locationContent=document.getElementById("location-container"),ce.Display.locationContent.style.display="none",ce.Display.workInProgressContent=document.getElementById("work-in-progress-container"),ce.Display.workInProgressContent.style.display="none",ce.Display.redPillContent=document.getElementById("red-pill-container"),ce.Display.redPillContent.style.display="none",ce.Display.cinematicTextContent=document.getElementById("cinematic-text-container"),ce.Display.cinematicTextContent.style.display="none",!Object(X.initializeMainMenuLinks)()){const e="Failed to initialize Main Menu Links. Please try refreshing the page. If that doesn't work, report the issue to the developer";return Object(ne.exceptionAlert)(new Error(e)),void console.error(e)}},init:function(){if(document.getElementById("import-game-link").onclick=function(){N.b.importGame()},!Object(J.initializeMainMenuHeaders)(x.Player,!1)){const e="Failed to initialize Main Menu Headers. Please try refreshing the page. If that doesn't work, report the issue to the developer";return Object(ne.exceptionAlert)(new Error(e)),void console.error(e)}(X.MainMenuLinks.Terminal.addEventListener("click",function(){return ce.loadTerminalContent(),!1}),X.MainMenuLinks.ScriptEditor.addEventListener("click",function(){return ce.loadScriptEditorContent(),!1}),X.MainMenuLinks.ActiveScripts.addEventListener("click",function(){return ce.loadActiveScriptsContent(),!1}),X.MainMenuLinks.CreateProgram.addEventListener("click",function(){return ce.loadCreateProgramContent(),!1}),X.MainMenuLinks.Stats.addEventListener("click",function(){return ce.loadCharacterContent(),!1}),X.MainMenuLinks.Factions.addEventListener("click",function(){return ce.loadFactionsContent(),!1}),X.MainMenuLinks.Augmentations.addEventListener("click",function(){return ce.loadAugmentationsContent(),!1}),X.MainMenuLinks.HacknetNodes.addEventListener("click",function(){return ce.loadHacknetNodesContent(),!1}),X.MainMenuLinks.Sleeves.addEventListener("click",function(){return ce.loadSleevesContent(),X.MainMenuLinks.Sleeves.classList.add("active"),!1}),X.MainMenuLinks.City.addEventListener("click",function(){return ce.loadLocationContent(),!1}),X.MainMenuLinks.Travel.addEventListener("click",function(){return ce.loadTravelContent(),!1}),X.MainMenuLinks.Job.addEventListener("click",function(){return ce.loadJobContent(),!1}),X.MainMenuLinks.StockMarket.addEventListener("click",function(){return ce.loadStockMarketContent(),X.MainMenuLinks.StockMarket.classList.add("active"),!1}),X.MainMenuLinks.Bladeburner.addEventListener("click",function(){return ce.loadBladeburnerContent(),!1}),X.MainMenuLinks.Corporation.addEventListener("click",function(){return ce.loadCorporationContent(),X.MainMenuLinks.Corporation.classList.add("active"),!1}),X.MainMenuLinks.Gang.addEventListener("click",function(){return ce.loadGangContent(),!1}),X.MainMenuLinks.Tutorial.addEventListener("click",function(){return ce.loadTutorialContent(),!1}),X.MainMenuLinks.DevMenu.addEventListener("click",function(){return!1}),ce.ActiveScriptsList=document.getElementById("active-scripts-list"),ce.Clickables.saveMainMenuButton=document.getElementById("save-game-link"),ce.Clickables.saveMainMenuButton.addEventListener("click",function(){return N.b.saveGame(ue),!1}),ce.Clickables.deleteMainMenuButton=document.getElementById("delete-game-link"),ce.Clickables.deleteMainMenuButton.addEventListener("click",function(){return N.b.deleteGame(ue),!1}),document.getElementById("export-game-link").addEventListener("click",function(){return N.b.exportGame(),!1}),document.getElementById("character-overview-save-button").addEventListener("click",function(){return N.b.saveGame(ue),!1}),document.getElementById("character-overview-options-button").addEventListener("click",function(){return Object(Z.b)(),!1}),Object(A.c)(),Object(F.b)(),x.Player.isWorking)&&(document.getElementById("work-in-progress-cancel-button").addEventListener("click",function(){if(x.Player.workType==g.CONSTANTS.WorkTypeFaction){y.Factions[x.Player.currentWorkFactionName];x.Player.finishFactionWork(!0)}else x.Player.workType==g.CONSTANTS.WorkTypeCreateProgram?x.Player.finishCreateProgramWork(!0):x.Player.workType==g.CONSTANTS.WorkTypeStudyClass?x.Player.finishClass():x.Player.workType==g.CONSTANTS.WorkTypeCrime?x.Player.finishCrime(!0):x.Player.workType==g.CONSTANTS.WorkTypeCompanyPartTime?x.Player.finishWorkPartTime():x.Player.finishWork(!0)}),ce.loadWorkInProgressContent());document.getElementById("character-overview-container").style.display="block",document.getElementById("terminal-menu-link").removeAttribute("class"),document.getElementById("stats-menu-link").removeAttribute("class"),document.getElementById("create-script-menu-link").removeAttribute("class"),document.getElementById("active-scripts-menu-link").removeAttribute("class"),document.getElementById("hacknet-nodes-menu-link").removeAttribute("class"),document.getElementById("city-menu-link").removeAttribute("class"),document.getElementById("tutorial-menu-link").removeAttribute("class"),document.getElementById("copy-save-to-clipboard-link").addEventListener("click",function(){const e=N.b.getSaveString();if(navigator.clipboard)navigator.clipboard.writeText(e).then(function(){Object(K.createStatusText)("Copied save to clipboard")},function(e){console.error("Unable to copy save data to clipboard using Async API"),Object(K.createStatusText)("Failed to copy save")});else{const t=document.createElement("textarea");t.value=e,t.setAttribute("readonly",""),t.style.position="absolute",t.left="-9999px",document.body.appendChild(t),t.focus(),t.select();try{document.execCommand("copy")?Object(K.createStatusText)("Copied save to clipboard"):Object(K.createStatusText)("Failed to copy save")}catch(e){console.error("Unable to copy save data to clipboard using document.execCommand('copy')"),Object(K.createStatusText)("Failed to copy save")}document.body.removeChild(t)}}),document.getElementById("debug-delete-scripts-link").addEventListener("click",function(){return console.log("Deleting running scripts on home computer"),x.Player.getHomeComputer().runningScripts=[],Object(Q.dialogBoxCreate)("Forcefully deleted all running scripts on home computer. Please save and refresh page"),Object(Z.a)(),!1}),document.getElementById("debug-soft-reset").addEventListener("click",function(){return Object(Q.dialogBoxCreate)("Soft Reset!"),Object(w.a)(),Object(Z.a)(),!1})},start:function(){ce.idleTimer()}};var ue,me;window.onload=function(){if(!window.indexedDB)return ce.load(null);(me=window.indexedDB.open("bitburnerSave",1)).onerror=function(e){return console.error("Error opening indexedDB: "),console.error(e),ce.load(null)},me.onsuccess=function(e){var t=(ue=e.target.result).transaction(["savestring"]).objectStore("savestring").get("save");t.onerror=function(e){return console.error("Error in Database request to get savestring: "+e),ce.load(null)},t.onsuccess=function(e){ce.load(t.result)}},me.onupgradeneeded=function(e){e.target.result.createObjectStore("savestring")}}}.call(this,n(85))},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});const r=n(8);t.SourceFileFlags=Array(r.CONSTANTS.TotalNumBitNodes+1),t.updateSourceFileFlags=function(e){for(let e=0;e{switch(typeof e){case"number":return e;case"object":return s.getRandomInt(e.min,e.max);default:throw Error(`Do not know how to convert the type '${typeof e}' to a number`)}};for(const e of i.serverMetadata){const i={hostname:e.hostname,ip:u(),numOpenPortsRequired:e.numOpenPortsRequired,organizationName:e.organizationName};void 0!==e.maxRamExponent&&(i.maxRam=Math.pow(2,o(e.maxRamExponent)));for(const t of n)void 0!==e[t]&&(i[t]=o(e[t]));const s=new r.Server(i);for(const t of e.literature||[])s.messages.push(t);void 0!==e.specialName&&a.SpecialServerIps.addIp(e.specialName,s.ip),m(s),void 0!==e.networkLayer&&t[o(e.networkLayer)-1].push(s)}const l=(e,t)=>{e.serversOnNetwork.push(t.ip),t.serversOnNetwork.push(e.ip)},c=e=>e[Math.floor(Math.random()*e.length)],p=(e,t)=>{for(const n of e)l(n,t())};p(t[0],()=>e);for(let e=1;ec(t[e-1]))},t.prestigeAllServers=function(){for(var e in t.AllServers)delete t.AllServers[e];t.AllServers={}},t.loadAllServers=function(e){t.AllServers=JSON.parse(e,l.Reviver)}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.EmployeePositions={Operations:"Operations",Engineer:"Engineer",Business:"Business",Management:"Management",RandD:"Research & Development",Training:"Training",Unassigned:"Unassigned"}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});const r=n(21),a=n(112),i=n(20),o=n(8),s=n(33),l=n(651),c=n(149);function u(e,t,n){let r=1+(o.CONSTANTS.ServerBaseGrowthRate-1)/e.hackDifficulty;r>o.CONSTANTS.ServerMaxGrowthRate&&(r=o.CONSTANTS.ServerMaxGrowthRate);const a=e.serverGrowth/100;return Math.log(t)/(Math.log(r)*n.hacking_grow_mult*a*i.BitNodeMultipliers.ServerGrowthRate)}function m(e){for(var t in r.AllServers)if(r.AllServers.hasOwnProperty(t)&&r.AllServers[t].hostname==e)return r.AllServers[t];return null}t.safetlyCreateUniqueServer=function(e){if(null!=e.ip&&r.ipExists(e.ip)&&(e.ip=r.createUniqueRandomIp()),null!=m(e.hostname)){let t=e.hostname;for(let n=0;n<200&&null!=m(t=`${e.hostname}-${n}`);++n);e.hostname=t}return new a.Server(e)},t.numCycleForGrowth=u,t.processSingleServerGrowth=function(e,t,n){const r=Math.max(Math.floor(t/450),0);var a=1+(o.CONSTANTS.ServerBaseGrowthRate-1)/e.hackDifficulty;a>o.CONSTANTS.ServerMaxGrowthRate&&(a=o.CONSTANTS.ServerMaxGrowthRate);const s=r*(e.serverGrowth/100)*i.BitNodeMultipliers.ServerGrowthRate;let c=Math.pow(a,s*n.hacking_grow_mult);c<1&&(console.log("WARN: serverGrowth calculated to be less than 1"),c=1);const m=e.moneyAvailable;if(e.moneyAvailable*=c,l.isValidNumber(e.moneyMax)&&isNaN(e.moneyAvailable)&&(e.moneyAvailable=e.moneyMax),l.isValidNumber(e.moneyMax)&&e.moneyAvailable>e.moneyMax&&(e.moneyAvailable=e.moneyMax),m!==e.moneyAvailable){let t=u(e,e.moneyAvailable/m,n);t=Math.max(0,t),e.fortify(2*o.CONSTANTS.ServerFortifyAmount*Math.ceil(t))}return e.moneyAvailable/m},t.prestigeHomeComputer=function(e){const t=e.programs.includes(s.Programs.BitFlume.name);e.programs.length=0,e.runningScripts=[],e.serversOnNetwork=[],e.isConnectedTo=!0,e.ramUsed=0,e.programs.push(s.Programs.NukeProgram.name),t&&e.programs.push(s.Programs.BitFlume.name),e.scripts.forEach(function(t){t.updateRamUsage(e.scripts)}),e.messages.length=0,e.messages.push("hackers-starting-handbook.lit")},t.GetServerByHostname=m,t.getServer=function(e){return c.isValidIPAddress(e)?void 0!==r.AllServers[e]?r.AllServers[e]:null:m(e)},t.getServerOnNetwork=function(e,t){if(!(t>e.serversOnNetwork.length))return r.AllServers[e.serversOnNetwork[t]];console.error("Tried to get server on network that was out of range")}},function(e,t,n){"use strict";n.d(t,"h",function(){return E}),n.d(t,"m",function(){return v}),n.d(t,"i",function(){return k}),n.d(t,"b",function(){return C}),n.d(t,"c",function(){return O}),n.d(t,"f",function(){return P}),n.d(t,"g",function(){return S}),n.d(t,"e",function(){return T}),n.d(t,"d",function(){return M}),n.d(t,"o",function(){return x}),n.d(t,"p",function(){return w}),n.d(t,"l",function(){return A}),n.d(t,"k",function(){return R}),n.d(t,"q",function(){return N}),n.d(t,"a",function(){return D}),n.d(t,"j",function(){return I}),n.d(t,"r",function(){return L}),n.d(t,"n",function(){return W});var r=n(54),a=n(34),i=n(104),o=n(137),s=n(117),l=n(40),c=n(0),u=n(21),m=n(23),p=n(15),h=n(12),d=(n(111),n(1)),g=n.n(d),_=n(52),y=n.n(_),f=n(173);let b;function E(){return 9===c.Player.bitNodeN||p.SourceFileFlags[9]>0}function v(){if(l.a.isRunning){if(l.a.currStep!==l.d.HacknetNodesIntroduction)return;Object(l.b)()}const e=c.Player.hacknetNodes.length;if(E()){const t=O();if(isNaN(t))throw new Error("Calculated cost of purchasing HacknetServer is NaN");if(!c.Player.canAfford(t))return-1;c.Player.loseMoney(t);c.Player.createHacknetServer();return L(),e}{const t=C();if(isNaN(t))throw new Error("Calculated cost of purchasing HacknetNode is NaN");if(!c.Player.canAfford(t))return-1;const n="hacknet-node-"+e,a=new r.HacknetNode(n,c.Player.hacknet_node_money_mult);return c.Player.loseMoney(t),c.Player.hacknetNodes.push(a),e}}function k(){return E()&&c.Player.hacknetNodes.length>=a.MaxNumberHacknetServers}function C(){const e=c.Player.hacknetNodes.length,t=r.HacknetNodePurchaseNextMult;return r.BaseCostForHacknetNode*Math.pow(t,e)*c.Player.hacknet_node_purchase_cost_mult}function O(){const e=c.Player.hacknetNodes.length,t=a.HacknetServerPurchaseMult;return e>a.MaxNumberHacknetServers?1/0:a.BaseCostForHacknetServer*Math.pow(t,e)*c.Player.hacknet_node_purchase_cost_mult}function P(e,t){if(null==t)throw new Error("getMaxNumberLevelUpgrades() called without maxLevel arg");if(c.Player.money.lt(e.calculateLevelUpgradeCost(1,c.Player.hacknet_node_level_cost_mult)))return 0;let n=1,r=t-1,a=t-e.level;if(c.Player.money.gt(e.calculateLevelUpgradeCost(a,c.Player.hacknet_node_level_cost_mult)))return a;for(;n<=r;){var i=(n+r)/2|0;if(i!==t&&c.Player.money.gt(e.calculateLevelUpgradeCost(i,c.Player.hacknet_node_level_cost_mult))&&c.Player.money.lt(e.calculateLevelUpgradeCost(i+1,c.Player.hacknet_node_level_cost_mult)))return Math.min(a,i);if(c.Player.money.lt(e.calculateLevelUpgradeCost(i,c.Player.hacknet_node_level_cost_mult)))r=i-1;else{if(!c.Player.money.gt(e.calculateLevelUpgradeCost(i,c.Player.hacknet_node_level_cost_mult)))return Math.min(a,i);n=i+1}}return 0}function S(e,t){if(null==t)throw new Error("getMaxNumberRamUpgrades() called without maxLevel arg");if(c.Player.money.lt(e.calculateRamUpgradeCost(1,c.Player.hacknet_node_ram_cost_mult)))return 0;let n;if(n=e instanceof a.HacknetServer?Math.round(Math.log2(t/e.maxRam)):Math.round(Math.log2(t/e.ram)),c.Player.money.gt(e.calculateRamUpgradeCost(n,c.Player.hacknet_node_ram_cost_mult)))return n;for(let t=n-1;t>=0;--t)if(c.Player.money.gt(e.calculateRamUpgradeCost(t,c.Player.hacknet_node_ram_cost_mult)))return t;return 0}function T(e,t){if(null==t)throw new Error("getMaxNumberCoreUpgrades() called without maxLevel arg");if(c.Player.money.lt(e.calculateCoreUpgradeCost(1,c.Player.hacknet_node_core_cost_mult)))return 0;let n=1,r=t-1;const a=t-e.cores;if(c.Player.money.gt(e.calculateCoreUpgradeCost(a,c.Player.hacknet_node_core_cost_mult)))return a;for(;n<=r;){let i=(n+r)/2|0;if(i!=t&&c.Player.money.gt(e.calculateCoreUpgradeCost(i,c.Player.hacknet_node_core_cost_mult))&&c.Player.money.lt(e.calculateCoreUpgradeCost(i+1,c.Player.hacknet_node_core_cost_mult)))return Math.min(a,i);if(c.Player.money.lt(e.calculateCoreUpgradeCost(i,c.Player.hacknet_node_core_cost_mult)))r=i-1;else{if(!c.Player.money.gt(e.calculateCoreUpgradeCost(i,c.Player.hacknet_node_core_cost_mult)))return Math.min(a,i);n=i+1}}return 0}function M(e,t){if(null==t)throw new Error("getMaxNumberCacheUpgrades() called without maxLevel arg");if(!c.Player.canAfford(e.calculateCacheUpgradeCost(1)))return 0;let n=1,r=t-1;const a=t-e.cache;if(c.Player.canAfford(e.calculateCacheUpgradeCost(a)))return a;for(;n<=r;){let i=(n+r)/2|0;if(i!=t&&c.Player.canAfford(e.calculateCacheUpgradeCost(i))&&!c.Player.canAfford(e.calculateCacheUpgradeCost(i+1)))return Math.min(a,i);if(c.Player.canAfford(e.calculateCacheUpgradeCost(i))){if(!c.Player.canAfford(e.calculateCacheUpgradeCost(i)))return Math.min(a,i);n=i+1}else r=i-1}return 0}function x(e,t=1){const n=Math.round(t),i=e.calculateLevelUpgradeCost(n,c.Player.hacknet_node_level_cost_mult);if(isNaN(i)||i<=0||n<0)return!1;const o=e instanceof a.HacknetServer;if(e.level>=(o?a.HacknetServerMaxLevel:r.HacknetNodeMaxLevel))return!1;if(e.level+n>(o?a.HacknetServerMaxLevel:r.HacknetNodeMaxLevel)){return x(e,Math.max(0,(o?a.HacknetServerMaxLevel:r.HacknetNodeMaxLevel)-e.level))}return!!c.Player.canAfford(i)&&(c.Player.loseMoney(i),e.upgradeLevel(n,c.Player.hacknet_node_money_mult),!0)}function w(e,t=1){const n=Math.round(t),i=e.calculateRamUpgradeCost(n,c.Player.hacknet_node_ram_cost_mult);if(isNaN(i)||i<=0||n<0)return!1;const o=e instanceof a.HacknetServer;if(e.ram>=(o?a.HacknetServerMaxRam:r.HacknetNodeMaxRam))return!1;if(o){if(e.maxRam*Math.pow(2,n)>a.HacknetServerMaxRam){return w(e,Math.max(0,Math.log2(Math.round(a.HacknetServerMaxRam/e.maxRam))))}}else if(e.ram*Math.pow(2,n)>r.HacknetNodeMaxRam){return w(e,Math.max(0,Math.log2(Math.round(r.HacknetNodeMaxRam/e.ram))))}return!!c.Player.canAfford(i)&&(c.Player.loseMoney(i),e.upgradeRam(n,c.Player.hacknet_node_money_mult),!0)}function A(e,t=1){const n=Math.round(t),i=e.calculateCoreUpgradeCost(n,c.Player.hacknet_node_core_cost_mult);if(isNaN(i)||i<=0||n<0)return!1;const o=e instanceof a.HacknetServer;if(e.cores>=(o?a.HacknetServerMaxCores:r.HacknetNodeMaxCores))return!1;if(e.cores+n>(o?a.HacknetServerMaxCores:r.HacknetNodeMaxCores)){return A(e,Math.max(0,(o?a.HacknetServerMaxCores:r.HacknetNodeMaxCores)-e.cores))}return!!c.Player.canAfford(i)&&(c.Player.loseMoney(i),e.upgradeCore(n,c.Player.hacknet_node_money_mult),!0)}function R(e,t=1){const n=Math.round(t),r=e.calculateCacheUpgradeCost(n);if(isNaN(r)||r<=0||n<0)return!1;if(!(e instanceof a.HacknetServer))return console.warn("purchaseCacheUpgrade() called for a non-HacknetNode"),!1;if(e.cache+n>a.HacknetServerMaxCache){return R(e,Math.max(0,a.HacknetServerMaxCache-e.cache))}return!!c.Player.canAfford(r)&&(c.Player.loseMoney(r),e.upgradeCache(n),!0)}function N(){h.routing.isOn(h.Page.HacknetNodes)&&y.a.render(g.a.createElement(f.a,null),b)}function D(){b instanceof HTMLElement&&y.a.unmountComponentAtNode(b),b.style.display="none"}function I(e){return 0===c.Player.hacknetNodes.length?0:E()?function(e){if(!(c.Player.hashManager instanceof i.HashManager))throw new Error("Player does not have a HashManager (should be in 'hashManager' prop)");let t=0;for(let n=0;n{!function(e){null!=t.Companies[e.name]&&console.warn(`Duplicate Company Position being defined: ${e.name}`),t.Companies[e.name]=new a.Company(e)}(e)});for(const n in t.Companies){const r=t.Companies[n];e[n]instanceof a.Company?(r.favor=e[n].favor,isNaN(r.favor)&&(r.favor=0)):r.favor=0}},t.loadCompanies=function(e){t.Companies=JSON.parse(e,i.Reviver)},t.companyExists=function(e){return t.Companies.hasOwnProperty(e)}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});const r=n(692),a=n(2);t.Industries={Energy:"Energy",Utilities:"Water Utilities",Agriculture:"Agriculture",Fishing:"Fishing",Mining:"Mining",Food:"Food",Tobacco:"Tobacco",Chemical:"Chemical",Pharmaceutical:"Pharmaceutical",Computer:"Computer Hardware",Robotics:"Robotics",Software:"Software",Healthcare:"Healthcare",RealEstate:"RealEstate"},t.IndustryStartingCosts={Energy:225e9,Utilities:15e10,Agriculture:4e10,Fishing:8e10,Mining:3e11,Food:1e10,Tobacco:2e10,Chemical:7e10,Pharmaceutical:2e11,Computer:5e11,Robotics:1e12,Software:25e9,Healthcare:75e10,RealEstate:6e11},t.IndustryDescriptions={Energy:"Engage in the production and distribution of energy.

    Starting cost: "+a.numeralWrapper.format(t.IndustryStartingCosts.Energy,"$0.000a")+"
    Recommended starting Industry: NO",Utilities:"Distribute water and provide wastewater services.

    Starting cost: "+a.numeralWrapper.format(t.IndustryStartingCosts.Utilities,"$0.000a")+"
    Recommended starting Industry: NO",Agriculture:"Cultivate crops and breed livestock to produce food.

    Starting cost: "+a.numeralWrapper.format(t.IndustryStartingCosts.Agriculture,"$0.000a")+"
    Recommended starting Industry: YES",Fishing:"Produce food through the breeding and processing of fish and fish products.

    Starting cost: "+a.numeralWrapper.format(t.IndustryStartingCosts.Fishing,"$0.000a")+"
    Recommended starting Industry: NO",Mining:"Extract and process metals from the earth.

    Starting cost: "+a.numeralWrapper.format(t.IndustryStartingCosts.Mining,"$0.000a")+"
    Recommended starting Industry: NO",Food:"Create your own restaurants all around the world.

    Starting cost: "+a.numeralWrapper.format(t.IndustryStartingCosts.Food,"$0.000a")+"
    Recommended starting Industry: YES",Tobacco:"Create and distribute tobacco and tobacco-related products.

    Starting cost: "+a.numeralWrapper.format(t.IndustryStartingCosts.Tobacco,"$0.000a")+"
    Recommended starting Industry: YES",Chemical:"Produce industrial chemicals.

    Starting cost: "+a.numeralWrapper.format(t.IndustryStartingCosts.Chemical,"$0.000a")+"
    Recommended starting Industry: NO",Pharmaceutical:"Discover, develop, and create new pharmaceutical drugs.

    Starting cost: "+a.numeralWrapper.format(t.IndustryStartingCosts.Pharmaceutical,"$0.000a")+"
    Recommended starting Industry: NO",Computer:"Develop and manufacture new computer hardware and networking infrastructures.

    Starting cost: "+a.numeralWrapper.format(t.IndustryStartingCosts.Computer,"$0.000a")+"
    Recommended starting Industry: NO",Robotics:"Develop and create robots.

    Starting cost: "+a.numeralWrapper.format(t.IndustryStartingCosts.Robotics,"$0.000a")+"
    Recommended starting Industry: NO",Software:"Develop computer software and create AI Cores.

    Starting cost: "+a.numeralWrapper.format(t.IndustryStartingCosts.Software,"$0.000a")+"
    Recommended starting Industry: YES",Healthcare:"Create and manage hospitals.

    Starting cost: "+a.numeralWrapper.format(t.IndustryStartingCosts.Healthcare,"$0.000a")+"
    Recommended starting Industry: NO",RealEstate:"Develop and manage real estate properties.

    Starting cost: "+a.numeralWrapper.format(t.IndustryStartingCosts.RealEstate,"$0.000a")+"
    Recommended starting Industry: NO"},t.IndustryResearchTrees={Energy:r.getBaseResearchTreeCopy(),Utilities:r.getBaseResearchTreeCopy(),Agriculture:r.getBaseResearchTreeCopy(),Fishing:r.getBaseResearchTreeCopy(),Mining:r.getBaseResearchTreeCopy(),Food:r.getProductIndustryResearchTreeCopy(),Tobacco:r.getProductIndustryResearchTreeCopy(),Chemical:r.getBaseResearchTreeCopy(),Pharmaceutical:r.getProductIndustryResearchTreeCopy(),Computer:r.getProductIndustryResearchTreeCopy(),Robotics:r.getProductIndustryResearchTreeCopy(),Software:r.getProductIndustryResearchTreeCopy(),Healthcare:r.getProductIndustryResearchTreeCopy(),RealEstate:r.getProductIndustryResearchTreeCopy()},t.resetIndustryResearchTrees=function(){t.IndustryResearchTrees.Energy=r.getBaseResearchTreeCopy(),t.IndustryResearchTrees.Utilities=r.getBaseResearchTreeCopy(),t.IndustryResearchTrees.Agriculture=r.getBaseResearchTreeCopy(),t.IndustryResearchTrees.Fishing=r.getBaseResearchTreeCopy(),t.IndustryResearchTrees.Mining=r.getBaseResearchTreeCopy(),t.IndustryResearchTrees.Food=r.getBaseResearchTreeCopy(),t.IndustryResearchTrees.Tobacco=r.getBaseResearchTreeCopy(),t.IndustryResearchTrees.Chemical=r.getBaseResearchTreeCopy(),t.IndustryResearchTrees.Pharmaceutical=r.getBaseResearchTreeCopy(),t.IndustryResearchTrees.Computer=r.getBaseResearchTreeCopy(),t.IndustryResearchTrees.Robotics=r.getBaseResearchTreeCopy(),t.IndustryResearchTrees.Software=r.getBaseResearchTreeCopy(),t.IndustryResearchTrees.Healthcare=r.getBaseResearchTreeCopy(),t.IndustryResearchTrees.RealEstate=r.getBaseResearchTreeCopy()}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.KEY={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}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});const r=n(111),a=n(82);t.removeElementById=function(e){try{const t=r.getElementById(e);a.removeElement(t)}catch(e){}}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),function(e){e.Aevum="Aevum",e.Chongqing="Chongqing",e.Ishima="Ishima",e.NewTokyo="New Tokyo",e.Sector12="Sector-12",e.Volhaven="Volhaven"}(t.CityName||(t.CityName={}))},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});const r=n(111);t.clearEventListeners=function(e){try{let t;const n=(t="string"==typeof e?r.getElementById(e):e).cloneNode(!0);return null!==t.parentNode&&t.parentNode.replaceChild(n,t),n}catch(e){return console.error(e),null}}},function(module,__webpack_exports__,__webpack_require__){"use strict";(function($){__webpack_require__.d(__webpack_exports__,"f",function(){return IssueNewSharesCooldown}),__webpack_require__.d(__webpack_exports__,"k",function(){return SellSharesCooldown}),__webpack_require__.d(__webpack_exports__,"m",function(){return WarehouseInitialCost}),__webpack_require__.d(__webpack_exports__,"n",function(){return WarehouseInitialSize}),__webpack_require__.d(__webpack_exports__,"o",function(){return WarehouseUpgradeBaseCost}),__webpack_require__.d(__webpack_exports__,"g",function(){return OfficeInitialCost}),__webpack_require__.d(__webpack_exports__,"h",function(){return OfficeInitialSize}),__webpack_require__.d(__webpack_exports__,"a",function(){return BribeThreshold}),__webpack_require__.d(__webpack_exports__,"b",function(){return BribeToRepRatio}),__webpack_require__.d(__webpack_exports__,"j",function(){return ProductProductionCostRatio}),__webpack_require__.d(__webpack_exports__,"d",function(){return DividendMaxPercentage}),__webpack_require__.d(__webpack_exports__,"c",function(){return Corporation}),__webpack_require__.d(__webpack_exports__,"e",function(){return Industry}),__webpack_require__.d(__webpack_exports__,"i",function(){return OfficeSpace});var _CorporationState__WEBPACK_IMPORTED_MODULE_0__=__webpack_require__(210),_CorporationState__WEBPACK_IMPORTED_MODULE_0___default=__webpack_require__.n(_CorporationState__WEBPACK_IMPORTED_MODULE_0__),_data_CorporationUnlockUpgrades__WEBPACK_IMPORTED_MODULE_1__=__webpack_require__(176),_data_CorporationUnlockUpgrades__WEBPACK_IMPORTED_MODULE_1___default=__webpack_require__.n(_data_CorporationUnlockUpgrades__WEBPACK_IMPORTED_MODULE_1__),_data_CorporationUpgrades__WEBPACK_IMPORTED_MODULE_2__=__webpack_require__(175),_data_CorporationUpgrades__WEBPACK_IMPORTED_MODULE_2___default=__webpack_require__.n(_data_CorporationUpgrades__WEBPACK_IMPORTED_MODULE_2__),_EmployeePositions__WEBPACK_IMPORTED_MODULE_3__=__webpack_require__(22),_EmployeePositions__WEBPACK_IMPORTED_MODULE_3___default=__webpack_require__.n(_EmployeePositions__WEBPACK_IMPORTED_MODULE_3__),_IndustryData__WEBPACK_IMPORTED_MODULE_4__=__webpack_require__(26),_IndustryData__WEBPACK_IMPORTED_MODULE_4___default=__webpack_require__.n(_IndustryData__WEBPACK_IMPORTED_MODULE_4__),_IndustryUpgrades__WEBPACK_IMPORTED_MODULE_5__=__webpack_require__(156),_IndustryUpgrades__WEBPACK_IMPORTED_MODULE_5___default=__webpack_require__.n(_IndustryUpgrades__WEBPACK_IMPORTED_MODULE_5__),_Material__WEBPACK_IMPORTED_MODULE_6__=__webpack_require__(150),_Material__WEBPACK_IMPORTED_MODULE_6___default=__webpack_require__.n(_Material__WEBPACK_IMPORTED_MODULE_6__),_MaterialSizes__WEBPACK_IMPORTED_MODULE_7__=__webpack_require__(95),_MaterialSizes__WEBPACK_IMPORTED_MODULE_7___default=__webpack_require__.n(_MaterialSizes__WEBPACK_IMPORTED_MODULE_7__),_Product__WEBPACK_IMPORTED_MODULE_8__=__webpack_require__(130),_Product__WEBPACK_IMPORTED_MODULE_8___default=__webpack_require__.n(_Product__WEBPACK_IMPORTED_MODULE_8__),_ResearchMap__WEBPACK_IMPORTED_MODULE_9__=__webpack_require__(168),_ResearchMap__WEBPACK_IMPORTED_MODULE_9___default=__webpack_require__.n(_ResearchMap__WEBPACK_IMPORTED_MODULE_9__),_Warehouse__WEBPACK_IMPORTED_MODULE_10__=__webpack_require__(90),_Warehouse__WEBPACK_IMPORTED_MODULE_10___default=__webpack_require__.n(_Warehouse__WEBPACK_IMPORTED_MODULE_10__);__webpack_require__.d(__webpack_exports__,"l",function(){return _Warehouse__WEBPACK_IMPORTED_MODULE_10__.Warehouse});var _BitNode_BitNodeMultipliers__WEBPACK_IMPORTED_MODULE_11__=__webpack_require__(20),_BitNode_BitNodeMultipliers__WEBPACK_IMPORTED_MODULE_11___default=__webpack_require__.n(_BitNode_BitNodeMultipliers__WEBPACK_IMPORTED_MODULE_11__),_Constants__WEBPACK_IMPORTED_MODULE_12__=__webpack_require__(8),_Constants__WEBPACK_IMPORTED_MODULE_12___default=__webpack_require__.n(_Constants__WEBPACK_IMPORTED_MODULE_12__),_Faction_Factions__WEBPACK_IMPORTED_MODULE_13__=__webpack_require__(13),_Faction_Factions__WEBPACK_IMPORTED_MODULE_13___default=__webpack_require__.n(_Faction_Factions__WEBPACK_IMPORTED_MODULE_13__),_Literature__WEBPACK_IMPORTED_MODULE_14__=__webpack_require__(129),_Locations_Cities__WEBPACK_IMPORTED_MODULE_15__=__webpack_require__(101),_Locations_Cities__WEBPACK_IMPORTED_MODULE_15___default=__webpack_require__.n(_Locations_Cities__WEBPACK_IMPORTED_MODULE_15__),_Locations_data_CityNames__WEBPACK_IMPORTED_MODULE_16__=__webpack_require__(29),_Locations_data_CityNames__WEBPACK_IMPORTED_MODULE_16___default=__webpack_require__.n(_Locations_data_CityNames__WEBPACK_IMPORTED_MODULE_16__),_Player__WEBPACK_IMPORTED_MODULE_17__=__webpack_require__(0),_ui_numeralFormat__WEBPACK_IMPORTED_MODULE_18__=__webpack_require__(2),_ui_numeralFormat__WEBPACK_IMPORTED_MODULE_18___default=__webpack_require__.n(_ui_numeralFormat__WEBPACK_IMPORTED_MODULE_18__),_ui_navigationTracking__WEBPACK_IMPORTED_MODULE_19__=__webpack_require__(12),_ui_navigationTracking__WEBPACK_IMPORTED_MODULE_19___default=__webpack_require__.n(_ui_navigationTracking__WEBPACK_IMPORTED_MODULE_19__),_utils_calculateEffectWithFactors__WEBPACK_IMPORTED_MODULE_20__=__webpack_require__(303),_utils_calculateEffectWithFactors__WEBPACK_IMPORTED_MODULE_20___default=__webpack_require__.n(_utils_calculateEffectWithFactors__WEBPACK_IMPORTED_MODULE_20__),_utils_DialogBox__WEBPACK_IMPORTED_MODULE_21__=__webpack_require__(9),_utils_uiHelpers_clearSelector__WEBPACK_IMPORTED_MODULE_22__=__webpack_require__(202),_utils_uiHelpers_clearSelector__WEBPACK_IMPORTED_MODULE_22___default=__webpack_require__.n(_utils_uiHelpers_clearSelector__WEBPACK_IMPORTED_MODULE_22__),_utils_JSONReviver__WEBPACK_IMPORTED_MODULE_23__=__webpack_require__(18),_utils_uiHelpers_appendLineBreaks__WEBPACK_IMPORTED_MODULE_24__=__webpack_require__(78),_utils_uiHelpers_appendLineBreaks__WEBPACK_IMPORTED_MODULE_24___default=__webpack_require__.n(_utils_uiHelpers_appendLineBreaks__WEBPACK_IMPORTED_MODULE_24__),_utils_uiHelpers_createElement__WEBPACK_IMPORTED_MODULE_25__=__webpack_require__(3),_utils_uiHelpers_createElement__WEBPACK_IMPORTED_MODULE_25___default=__webpack_require__.n(_utils_uiHelpers_createElement__WEBPACK_IMPORTED_MODULE_25__),_utils_uiHelpers_createPopup__WEBPACK_IMPORTED_MODULE_26__=__webpack_require__(37),_utils_uiHelpers_createPopup__WEBPACK_IMPORTED_MODULE_26___default=__webpack_require__.n(_utils_uiHelpers_createPopup__WEBPACK_IMPORTED_MODULE_26__),_utils_uiHelpers_createPopupCloseButton__WEBPACK_IMPORTED_MODULE_27__=__webpack_require__(57),_utils_uiHelpers_createPopupCloseButton__WEBPACK_IMPORTED_MODULE_27___default=__webpack_require__.n(_utils_uiHelpers_createPopupCloseButton__WEBPACK_IMPORTED_MODULE_27__),_utils_StringHelperFunctions__WEBPACK_IMPORTED_MODULE_28__=__webpack_require__(7),_utils_StringHelperFunctions__WEBPACK_IMPORTED_MODULE_28___default=__webpack_require__.n(_utils_StringHelperFunctions__WEBPACK_IMPORTED_MODULE_28__),_utils_helpers_getRandomInt__WEBPACK_IMPORTED_MODULE_29__=__webpack_require__(16),_utils_helpers_getRandomInt__WEBPACK_IMPORTED_MODULE_29___default=__webpack_require__.n(_utils_helpers_getRandomInt__WEBPACK_IMPORTED_MODULE_29__),_utils_helpers_isString__WEBPACK_IMPORTED_MODULE_30__=__webpack_require__(49),_utils_helpers_isString__WEBPACK_IMPORTED_MODULE_30___default=__webpack_require__.n(_utils_helpers_isString__WEBPACK_IMPORTED_MODULE_30__),_utils_helpers_keyCodes__WEBPACK_IMPORTED_MODULE_31__=__webpack_require__(27),_utils_helpers_keyCodes__WEBPACK_IMPORTED_MODULE_31___default=__webpack_require__.n(_utils_helpers_keyCodes__WEBPACK_IMPORTED_MODULE_31__),_utils_uiHelpers_removeElement__WEBPACK_IMPORTED_MODULE_32__=__webpack_require__(82),_utils_uiHelpers_removeElement__WEBPACK_IMPORTED_MODULE_32___default=__webpack_require__.n(_utils_uiHelpers_removeElement__WEBPACK_IMPORTED_MODULE_32__),_utils_uiHelpers_removeElementById__WEBPACK_IMPORTED_MODULE_33__=__webpack_require__(28),_utils_uiHelpers_removeElementById__WEBPACK_IMPORTED_MODULE_33___default=__webpack_require__.n(_utils_uiHelpers_removeElementById__WEBPACK_IMPORTED_MODULE_33__),_utils_YesNoBox__WEBPACK_IMPORTED_MODULE_34__=__webpack_require__(45),_utils_YesNoBox__WEBPACK_IMPORTED_MODULE_34___default=__webpack_require__.n(_utils_YesNoBox__WEBPACK_IMPORTED_MODULE_34__),react__WEBPACK_IMPORTED_MODULE_35__=__webpack_require__(1),react__WEBPACK_IMPORTED_MODULE_35___default=__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_35__),react_dom__WEBPACK_IMPORTED_MODULE_36__=__webpack_require__(52),react_dom__WEBPACK_IMPORTED_MODULE_36___default=__webpack_require__.n(react_dom__WEBPACK_IMPORTED_MODULE_36__),_ui_CorporationUIEventHandler__WEBPACK_IMPORTED_MODULE_37__=__webpack_require__(302),_ui_Root__WEBPACK_IMPORTED_MODULE_38__=__webpack_require__(301),_ui_Routing__WEBPACK_IMPORTED_MODULE_39__=__webpack_require__(136),_ui_Routing__WEBPACK_IMPORTED_MODULE_39___default=__webpack_require__.n(_ui_Routing__WEBPACK_IMPORTED_MODULE_39__),decimal_js__WEBPACK_IMPORTED_MODULE_40__=__webpack_require__(43);const INITIALSHARES=1e9,SHARESPERPRICEUPDATE=1e6,IssueNewSharesCooldown=216e3,SellSharesCooldown=18e3,CyclesPerMarketCycle=50,CyclesPerIndustryStateCycle=CyclesPerMarketCycle/_CorporationState__WEBPACK_IMPORTED_MODULE_0__.AllCorporationStates.length,SecsPerMarketCycle=CyclesPerMarketCycle/5,Cities=["Aevum","Chongqing","Sector-12","New Tokyo","Ishima","Volhaven"],WarehouseInitialCost=5e9,WarehouseInitialSize=100,WarehouseUpgradeBaseCost=1e9,OfficeInitialCost=4e9,OfficeInitialSize=3,OfficeUpgradeBaseCost=1e9,BribeThreshold=1e14,BribeToRepRatio=1e9,ProductProductionCostRatio=5,DividendMaxPercentage=50,EmployeeSalaryMultiplier=3,CyclesPerEmployeeRaise=400,EmployeeRaiseAmount=50,BaseMaxProducts=3;let researchTreeBoxOpened=!1,researchTreeBox=null;$(document).mousedown(function(e){researchTreeBoxOpened&&null==$(e.target).closest("#corporation-research-popup-box-content").get(0)&&(Object(_utils_uiHelpers_removeElement__WEBPACK_IMPORTED_MODULE_32__.removeElement)(researchTreeBox),researchTreeBox=null,researchTreeBoxOpened=!1)});var empManualAssignmentModeActive=!1;function Industry(e={}){this.offices={[_Locations_data_CityNames__WEBPACK_IMPORTED_MODULE_16__.CityName.Aevum]:0,[_Locations_data_CityNames__WEBPACK_IMPORTED_MODULE_16__.CityName.Chongqing]:0,[_Locations_data_CityNames__WEBPACK_IMPORTED_MODULE_16__.CityName.Sector12]:new OfficeSpace({loc:_Locations_data_CityNames__WEBPACK_IMPORTED_MODULE_16__.CityName.Sector12,size:OfficeInitialSize}),[_Locations_data_CityNames__WEBPACK_IMPORTED_MODULE_16__.CityName.NewTokyo]:0,[_Locations_data_CityNames__WEBPACK_IMPORTED_MODULE_16__.CityName.Ishima]:0,[_Locations_data_CityNames__WEBPACK_IMPORTED_MODULE_16__.CityName.Volhaven]:0},this.name=e.name?e.name:0,this.type=e.type?e.type:0,this.sciResearch=new _Material__WEBPACK_IMPORTED_MODULE_6__.Material({name:"Scientific Research"}),this.researched={},this.reqMats={},this.prodMats=[],this.products={},this.makesProducts=!1,this.awareness=0,this.popularity=0,this.startingCost=0,this.reFac=0,this.sciFac=0,this.hwFac=0,this.robFac=0,this.aiFac=0,this.advFac=0,this.prodMult=0,this.lastCycleRevenue=new decimal_js__WEBPACK_IMPORTED_MODULE_40__.a(0),this.lastCycleExpenses=new decimal_js__WEBPACK_IMPORTED_MODULE_40__.a(0),this.thisCycleRevenue=new decimal_js__WEBPACK_IMPORTED_MODULE_40__.a(0),this.thisCycleExpenses=new decimal_js__WEBPACK_IMPORTED_MODULE_40__.a(0);var t=Object.keys(_IndustryUpgrades__WEBPACK_IMPORTED_MODULE_5__.IndustryUpgrades).length;this.upgrades=Array(t).fill(0),this.state="START",this.newInd=!0,this.warehouses={[_Locations_data_CityNames__WEBPACK_IMPORTED_MODULE_16__.CityName.Aevum]:0,[_Locations_data_CityNames__WEBPACK_IMPORTED_MODULE_16__.CityName.Chonqing]:0,[_Locations_data_CityNames__WEBPACK_IMPORTED_MODULE_16__.CityName.Sector12]:new _Warehouse__WEBPACK_IMPORTED_MODULE_10__.Warehouse({corp:e.corp,industry:this,loc:_Locations_data_CityNames__WEBPACK_IMPORTED_MODULE_16__.CityName.Sector12,size:WarehouseInitialSize}),[_Locations_data_CityNames__WEBPACK_IMPORTED_MODULE_16__.CityName.NewTokyo]:0,[_Locations_data_CityNames__WEBPACK_IMPORTED_MODULE_16__.CityName.Ishima]:0,[_Locations_data_CityNames__WEBPACK_IMPORTED_MODULE_16__.CityName.Volhaven]:0},this.init()}function Employee(e={}){if(!(this instanceof Employee))return new Employee(e);this.name=e.name?e.name:"Bobby",this.mor=e.morale?e.morale:Object(_utils_helpers_getRandomInt__WEBPACK_IMPORTED_MODULE_29__.getRandomInt)(50,100),this.hap=e.happiness?e.happiness:Object(_utils_helpers_getRandomInt__WEBPACK_IMPORTED_MODULE_29__.getRandomInt)(50,100),this.ene=e.energy?e.energy:Object(_utils_helpers_getRandomInt__WEBPACK_IMPORTED_MODULE_29__.getRandomInt)(50,100),this.int=e.intelligence?e.intelligence:Object(_utils_helpers_getRandomInt__WEBPACK_IMPORTED_MODULE_29__.getRandomInt)(10,50),this.cha=e.charisma?e.charisma:Object(_utils_helpers_getRandomInt__WEBPACK_IMPORTED_MODULE_29__.getRandomInt)(10,50),this.exp=e.experience?e.experience:Object(_utils_helpers_getRandomInt__WEBPACK_IMPORTED_MODULE_29__.getRandomInt)(10,50),this.cre=e.creativity?e.creativity:Object(_utils_helpers_getRandomInt__WEBPACK_IMPORTED_MODULE_29__.getRandomInt)(10,50),this.eff=e.efficiency?e.efficiency:Object(_utils_helpers_getRandomInt__WEBPACK_IMPORTED_MODULE_29__.getRandomInt)(10,50),this.sal=e.salary?e.salary:Object(_utils_helpers_getRandomInt__WEBPACK_IMPORTED_MODULE_29__.getRandomInt)(.1,5),this.pro=0,this.cyclesUntilRaise=CyclesPerEmployeeRaise,this.loc=e.loc?e.loc:"",this.pos=_EmployeePositions__WEBPACK_IMPORTED_MODULE_3__.EmployeePositions.Unassigned}Industry.prototype.init=function(){switch(this.startingCost=_IndustryData__WEBPACK_IMPORTED_MODULE_4__.IndustryStartingCosts[this.type],this.type){case _IndustryData__WEBPACK_IMPORTED_MODULE_4__.Industries.Energy:this.reFac=.65,this.sciFac=.7,this.robFac=.05,this.aiFac=.3,this.advFac=.08,this.reqMats={Hardware:.1,Metal:.2},this.prodMats=["Energy"];break;case _IndustryData__WEBPACK_IMPORTED_MODULE_4__.Industries.Utilities:case"Utilities":this.reFac=.5,this.sciFac=.6,this.robFac=.4,this.aiFac=.4,this.advFac=.08,this.reqMats={Hardware:.1,Metal:.1},this.prodMats=["Water"];break;case _IndustryData__WEBPACK_IMPORTED_MODULE_4__.Industries.Agriculture:this.reFac=.72,this.sciFac=.5,this.hwFac=.2,this.robFac=.3,this.aiFac=.3,this.advFac=.04,this.reqMats={Water:.5,Energy:.5},this.prodMats=["Plants","Food"];break;case _IndustryData__WEBPACK_IMPORTED_MODULE_4__.Industries.Fishing:this.reFac=.15,this.sciFac=.35,this.hwFac=.35,this.robFac=.5,this.aiFac=.2,this.advFac=.08,this.reqMats={Energy:.5},this.prodMats=["Food"];break;case _IndustryData__WEBPACK_IMPORTED_MODULE_4__.Industries.Mining:this.reFac=.3,this.sciFac=.26,this.hwFac=.4,this.robFac=.45,this.aiFac=.45,this.advFac=.06,this.reqMats={Energy:.8},this.prodMats=["Metal"];break;case _IndustryData__WEBPACK_IMPORTED_MODULE_4__.Industries.Food:this.sciFac=.12,this.hwFac=.15,this.robFac=.3,this.aiFac=.25,this.advFac=.25,this.reFac=.05,this.reqMats={Food:.5,Water:.5,Energy:.2},this.makesProducts=!0;break;case _IndustryData__WEBPACK_IMPORTED_MODULE_4__.Industries.Tobacco:this.reFac=.15,this.sciFac=.75,this.hwFac=.15,this.robFac=.2,this.aiFac=.15,this.advFac=.2,this.reqMats={Plants:1,Water:.2},this.makesProducts=!0;break;case _IndustryData__WEBPACK_IMPORTED_MODULE_4__.Industries.Chemical:this.reFac=.25,this.sciFac=.75,this.hwFac=.2,this.robFac=.25,this.aiFac=.2,this.advFac=.07,this.reqMats={Plants:1,Energy:.5,Water:.5},this.prodMats=["Chemicals"];break;case _IndustryData__WEBPACK_IMPORTED_MODULE_4__.Industries.Pharmaceutical:this.reFac=.05,this.sciFac=.8,this.hwFac=.15,this.robFac=.25,this.aiFac=.2,this.advFac=.16,this.reqMats={Chemicals:2,Energy:1,Water:.5},this.prodMats=["Drugs"],this.makesProducts=!0;break;case _IndustryData__WEBPACK_IMPORTED_MODULE_4__.Industries.Computer:case"Computer":this.reFac=.2,this.sciFac=.62,this.robFac=.36,this.aiFac=.19,this.advFac=.17,this.reqMats={Metal:2,Energy:1},this.prodMats=["Hardware"],this.makesProducts=!0;break;case _IndustryData__WEBPACK_IMPORTED_MODULE_4__.Industries.Robotics:this.reFac=.32,this.sciFac=.65,this.aiFac=.36,this.advFac=.18,this.hwFac=.19,this.reqMats={Hardware:5,Energy:3},this.prodMats=["Robots"],this.makesProducts=!0;break;case _IndustryData__WEBPACK_IMPORTED_MODULE_4__.Industries.Software:this.sciFac=.62,this.advFac=.16,this.hwFac=.25,this.reFac=.15,this.aiFac=.18,this.robFac=.05,this.reqMats={Hardware:.5,Energy:.5},this.prodMats=["AICores"],this.makesProducts=!0;break;case _IndustryData__WEBPACK_IMPORTED_MODULE_4__.Industries.Healthcare:this.reFac=.1,this.sciFac=.75,this.advFac=.11,this.hwFac=.1,this.robFac=.1,this.aiFac=.1,this.reqMats={Robots:10,AICores:5,Energy:5,Water:5},this.makesProducts=!0;break;case _IndustryData__WEBPACK_IMPORTED_MODULE_4__.Industries.RealEstate:this.robFac=.6,this.aiFac=.6,this.advFac=.25,this.sciFac=.05,this.hwFac=.05,this.reqMats={Metal:5,Energy:5,Water:2,Hardware:4},this.prodMats=["RealEstate"],this.makesProducts=!0;break;default:return void console.log("ERR: Invalid Industry Type passed into Industry.init(): "+this.type)}},Industry.prototype.getProductDescriptionText=function(){if(this.makesProducts)switch(this.type){case _IndustryData__WEBPACK_IMPORTED_MODULE_4__.Industries.Food:return"create and manage restaurants";case _IndustryData__WEBPACK_IMPORTED_MODULE_4__.Industries.Tobacco:return"create tobacco and tobacco-related products";case _IndustryData__WEBPACK_IMPORTED_MODULE_4__.Industries.Pharmaceutical:return"develop new pharmaceutical drugs";case _IndustryData__WEBPACK_IMPORTED_MODULE_4__.Industries.Computer:case"Computer":return"create new computer hardware and networking infrastructures";case _IndustryData__WEBPACK_IMPORTED_MODULE_4__.Industries.Robotics:return"build specialized robots and robot-related products";case _IndustryData__WEBPACK_IMPORTED_MODULE_4__.Industries.Software:return"develop computer software";case _IndustryData__WEBPACK_IMPORTED_MODULE_4__.Industries.Healthcare:return"build and manage hospitals";case _IndustryData__WEBPACK_IMPORTED_MODULE_4__.Industries.RealEstate:return"develop and manage real estate properties";default:return console.log("ERROR: Invalid industry type in Industry.getProductDescriptionText"),""}},Industry.prototype.getMaximumNumberProducts=function(){if(!this.makesProducts)return 0;let e=0;return this.hasResearch("uPgrade: Capacity.I")&&++e,this.hasResearch("uPgrade: Capacity.II")&&++e,BaseMaxProducts+e},Industry.prototype.hasMaximumNumberProducts=function(){return Object.keys(this.products).length>=this.getMaximumNumberProducts()},Industry.prototype.calculateProductionFactors=function(){for(var e=0,t=0;t0&&(e.breakdown+=t+": "+Object(_utils_StringHelperFunctions__WEBPACK_IMPORTED_MODULE_28__.formatNumber)(n.data[e.loc][0]*n.siz,0)+"
    ")}},Industry.prototype.process=function(e=1,t,n){if(this.state=t,"START"===t){(isNaN(this.thisCycleRevenue)||isNaN(this.thisCycleExpenses))&&(console.log("ERROR: NaN in Corporation's computed revenue/expenses"),console.log(this.thisCycleRevenue.toString()),console.log(this.thisCycleExpenses.toString()),Object(_utils_DialogBox__WEBPACK_IMPORTED_MODULE_21__.dialogBoxCreate)("Something went wrong when compting Corporation's revenue/expenses. This is a bug. Please report to game developer"),this.thisCycleRevenue=new decimal_js__WEBPACK_IMPORTED_MODULE_40__.a(0),this.thisCycleExpenses=new decimal_js__WEBPACK_IMPORTED_MODULE_40__.a(0)),this.lastCycleRevenue=this.thisCycleRevenue.dividedBy(e*SecsPerMarketCycle),this.lastCycleExpenses=this.thisCycleExpenses.dividedBy(e*SecsPerMarketCycle),this.thisCycleRevenue=new decimal_js__WEBPACK_IMPORTED_MODULE_40__.a(0),this.thisCycleExpenses=new decimal_js__WEBPACK_IMPORTED_MODULE_40__.a(0),this.lastCycleRevenue.gt(0)&&(this.newInd=!1);var r=0;for(var a in this.offices)this.offices[a]instanceof OfficeSpace&&(r+=this.offices[a].process(e,{industry:this,corporation:n}));this.thisCycleExpenses=this.thisCycleExpenses.plus(r),this.processMaterialMarket(e),this.processProductMarket(e),this.popularity-=1e-4*e,this.popularity=Math.max(0,this.popularity);var i=n.getDreamSenseGain(),o=4*i;return void(i>0&&(this.popularity+=i*e,this.awareness+=o*e))}let s=this.processMaterials(e,n);Array.isArray(s)&&(this.thisCycleRevenue=this.thisCycleRevenue.plus(s[0]),this.thisCycleExpenses=this.thisCycleExpenses.plus(s[1])),s=this.processProducts(e,n),Array.isArray(s)&&(this.thisCycleRevenue=this.thisCycleRevenue.plus(s[0]),this.thisCycleExpenses=this.thisCycleExpenses.plus(s[1]))},Industry.prototype.processMaterialMarket=function(e=1){for(var t=this.reqMats,n=this.prodMats,r=0;r0&&(a.qty+=r,expenses+=r*a.bCost)}(matName,industry),this.updateWarehouseSizeUsed(warehouse));break;case"PRODUCTION":if(warehouse.smartSupplyStore=0,this.prodMats.length>0){var mat=warehouse.materials[this.prodMats[0]],maxProd=this.getOfficeProductivity(office)*this.prodMult*company.getProductionMultiplier()*this.getProductionMultiplier();let e;e=mat.prdman[0]?Math.min(maxProd,mat.prdman[1]):maxProd,e*=SecsPerMarketCycle*marketCycles;var totalMatSize=0;for(let e=0;e0){var maxAmt=Math.floor((warehouse.size-warehouse.sizeUsed)/totalMatSize);e=Math.min(maxAmt,e)}e<0&&(e=0),warehouse.smartSupplyStore+=e/(SecsPerMarketCycle*marketCycles);var producableFrac=1;for(var reqMatName in this.reqMats)if(this.reqMats.hasOwnProperty(reqMatName)){var req=this.reqMats[reqMatName]*e;warehouse.materials[reqMatName].qty0&&e>0){for(const t in this.reqMats){var reqMatQtyNeeded=this.reqMats[t]*e*producableFrac;warehouse.materials[t].qty-=reqMatQtyNeeded,warehouse.materials[t].prd=0,warehouse.materials[t].prd-=reqMatQtyNeeded/(SecsPerMarketCycle*marketCycles)}for(let t=0;tmat.bCost?sCost-mat.bCost>markupLimit&&(markup=Math.pow(markupLimit/(sCost-mat.bCost),2)):sCost=0?(mat.qty-=sellAmt,revenue+=sellAmt*sCost,mat.sll=sellAmt/(SecsPerMarketCycle*marketCycles)):mat.sll=0}break;case"EXPORT":for(var matName in warehouse.materials)if(warehouse.materials.hasOwnProperty(matName)){var mat=warehouse.materials[matName];mat.totalExp=0;for(var expI=0;expI=expWarehouse.size)return[0,0];var maxAmt=Math.floor((expWarehouse.size-expWarehouse.sizeUsed)/_MaterialSizes__WEBPACK_IMPORTED_MODULE_7__.MaterialSizes[matName]);amt=Math.min(maxAmt,amt),expWarehouse.materials[matName].imp+=amt/(SecsPerMarketCycle*marketCycles),expWarehouse.materials[matName].qty+=amt,expWarehouse.materials[matName].qlt=mat.qlt,mat.qty-=amt,mat.totalExp+=amt,expIndustry.updateWarehouseSizeUsed(expWarehouse);break}}}mat.totalExp/=SecsPerMarketCycle*marketCycles}break;case"START":break;default:console.log("ERROR: Invalid state: "+this.state)}this.updateWarehouseSizeUsed(warehouse)}office instanceof OfficeSpace&&(this.sciResearch.qty+=.004*Math.pow(office.employeeProd[_EmployeePositions__WEBPACK_IMPORTED_MODULE_3__.EmployeePositions.RandD],.5)*company.getScientificResearchMultiplier()*this.getScientificResearchMultiplier())}return[revenue,expenses]},Industry.prototype.processProducts=function(e=1,t){var n=0;if("PRODUCTION"===this.state)for(const t in this.products){const n=this.products[t];if(!n.fin){const t=n.createCity,r=this.offices[t],a=r.employeeProd[_EmployeePositions__WEBPACK_IMPORTED_MODULE_3__.EmployeePositions.Engineer],i=r.employeeProd[_EmployeePositions__WEBPACK_IMPORTED_MODULE_3__.EmployeePositions.Management],o=r.employeeProd[_EmployeePositions__WEBPACK_IMPORTED_MODULE_3__.EmployeePositions.Operations],s=a+i+o;if(s<=0)break;const l=1+i/(1.2*s),c=(Math.pow(a,.34)+Math.pow(o,.2))*l;n.createProduct(e,c),n.prog>=100&&n.finishProduct(r.employeeProd,this);break}}for(var r in this.products)if(this.products.hasOwnProperty(r)){var a=this.products[r];a instanceof _Product__WEBPACK_IMPORTED_MODULE_8__.Product&&a.fin&&(n+=this.processProduct(e,a,t))}return[n,0]},Industry.prototype.processProduct=function(marketCycles=1,product,corporation){let totalProfit=0;for(let i=0;i0){var maxAmt=Math.floor((warehouse.size-warehouse.sizeUsed)/netStorageSize);prod=Math.min(maxAmt,prod)}warehouse.smartSupplyStore+=prod/(SecsPerMarketCycle*marketCycles);var producableFrac=1;for(var reqMatName in product.reqMats)if(product.reqMats.hasOwnProperty(reqMatName)){var req=product.reqMats[reqMatName]*prod;warehouse.materials[reqMatName].qty0&&prod>0){for(var reqMatName in product.reqMats)if(product.reqMats.hasOwnProperty(reqMatName)){var reqMatQtyNeeded=product.reqMats[reqMatName]*prod*producableFrac;warehouse.materials[reqMatName].qty-=reqMatQtyNeeded,warehouse.materials[reqMatName].prd-=reqMatQtyNeeded/(SecsPerMarketCycle*marketCycles)}product.data[city][0]+=prod*producableFrac}product.data[city][1]=prod*producableFrac/(SecsPerMarketCycle*marketCycles);break;case"SALE":for(var reqMatName in product.pCost=0,product.reqMats)product.reqMats.hasOwnProperty(reqMatName)&&(product.pCost+=product.reqMats[reqMatName]*warehouse.materials[reqMatName].bCost);product.pCost*=ProductProductionCostRatio;const businessFactor=this.getBusinessFactor(office),advertisingFactor=this.getAdvertisingFactors()[0],marketFactor=this.getMarketFactor(product),markupLimit=product.rat/product.mku;var sCost;if(product.marketTa2){const e=product.data[city][1],t=markupLimit,n=e,r=.5*Math.pow(product.rat,.65)*marketFactor*corporation.getSalesMultiplier()*businessFactor*advertisingFactor*this.getSalesMultiplier(),a=Math.sqrt(n/r);let i;0===r||0===a?0===n?i=0:(i=product.pCost+markupLimit,console.warn("In Corporation, found illegal 0s when trying to calculate MarketTA2 sale cost")):i=t/a+product.pCost,product.marketTa2Price[city]=i,sCost=i}else product.marketTa1?sCost=product.pCost+markupLimit:Object(_utils_helpers_isString__WEBPACK_IMPORTED_MODULE_30__.isString)(product.sCost)?(sCost=product.sCost.replace(/MP/g,product.pCost+product.rat/product.mku),sCost=eval(sCost)):sCost=product.sCost;var markup=1;sCost>product.pCost&&sCost-product.pCost>markupLimit&&(markup=markupLimit/(sCost-product.pCost));var maxSell=.5*Math.pow(product.rat,.65)*marketFactor*corporation.getSalesMultiplier()*Math.pow(markup,2)*businessFactor*advertisingFactor*this.getSalesMultiplier(),sellAmt;if(product.sllman[city][0]&&Object(_utils_helpers_isString__WEBPACK_IMPORTED_MODULE_30__.isString)(product.sllman[city][1])){var tmp=product.sllman[city][1].replace(/MAX/g,maxSell);tmp=tmp.replace(/PROD/g,product.data[city][1]);try{tmp=eval(tmp)}catch(e){Object(_utils_DialogBox__WEBPACK_IMPORTED_MODULE_21__.dialogBoxCreate)("Error evaluating your sell price expression for "+product.name+" in "+this.name+"'s "+city+" office. Sell price is being set to MAX"),tmp=maxSell}sellAmt=Math.min(maxSell,tmp)}else sellAmt=product.sllman[city][0]&&product.sllman[city][1]>0?Math.min(maxSell,product.sllman[city][1]):!1===product.sllman[city][0]?0:maxSell;sellAmt<0&&(sellAmt=0),sellAmt=sellAmt*SecsPerMarketCycle*marketCycles,sellAmt=Math.min(product.data[city][0],sellAmt),sellAmt&&sCost?(product.data[city][0]-=sellAmt,totalProfit+=sellAmt*sCost,product.data[city][2]=sellAmt/(SecsPerMarketCycle*marketCycles)):product.data[city][2]=0;break;case"START":case"PURCHASE":case"EXPORT":break;default:console.log("ERROR: Invalid State: "+this.state)}}return totalProfit},Industry.prototype.discontinueProduct=function(e){for(var t in this.products)this.products.hasOwnProperty(t)&&e===this.products[t]&&delete this.products[t]},Industry.prototype.upgrade=function(e,t){var n=t.corporation,r=(t.division,t.office),a=e[0];for(e[1],e[2],e[3];this.upgrades.length<=a;)this.upgrades.push(0);switch(++this.upgrades[a],a){case 0:for(let e=0;e{if(this.sciResearch.qty>=n.cost)return this.sciResearch.qty-=n.cost,t.research(r[e]),this.researched[r[e]]=!0,Object(_utils_DialogBox__WEBPACK_IMPORTED_MODULE_21__.dialogBoxCreate)(`Researched ${r[e]}. It may take a market cycle `+`(~${SecsPerMarketCycle} seconds) before the effects of `+"the Research apply."),this.createResearchBox();Object(_utils_DialogBox__WEBPACK_IMPORTED_MODULE_21__.dialogBoxCreate)(`You do not have enough Scientific Research for ${n.name}`)}):console.warn(`Could not find Research Tree div for ${a}`)}const a=document.getElementById(`${e}-content`);null!=a&&(Object(_utils_uiHelpers_appendLineBreaks__WEBPACK_IMPORTED_MODULE_24__.appendLineBreaks)(a,2),a.appendChild(Object(_utils_uiHelpers_createElement__WEBPACK_IMPORTED_MODULE_25__.createElement)("pre",{display:"block",innerText:"Multipliers from research:\n"+` * Advertising Multiplier: x${t.getAdvertisingMultiplier()}\n`+` * Employee Charisma Multiplier: x${t.getEmployeeChaMultiplier()}\n`+` * Employee Creativity Multiplier: x${t.getEmployeeCreMultiplier()}\n`+` * Employee Efficiency Multiplier: x${t.getEmployeeEffMultiplier()}\n`+` * Employee Intelligence Multiplier: x${t.getEmployeeIntMultiplier()}\n`+` * Production Multiplier: x${t.getProductionMultiplier()}\n`+` * Sales Multiplier: x${t.getSalesMultiplier()}\n`+` * Scientific Research Multiplier: x${t.getScientificResearchMultiplier()}\n`+` * Storage Multiplier: x${t.getStorageMultiplier()}`})),a.appendChild(Object(_utils_uiHelpers_createPopupCloseButton__WEBPACK_IMPORTED_MODULE_27__.createPopupCloseButton)(researchTreeBox,{class:"std-button",display:"block",innerText:"Close"}))),researchTreeBoxOpened=!0},Industry.prototype.toJSON=function(){return Object(_utils_JSONReviver__WEBPACK_IMPORTED_MODULE_23__.Generic_toJSON)("Industry",this)},Industry.fromJSON=function(e){return Object(_utils_JSONReviver__WEBPACK_IMPORTED_MODULE_23__.Generic_fromJSON)(Industry,e.data)},_utils_JSONReviver__WEBPACK_IMPORTED_MODULE_23__.Reviver.constructors.Industry=Industry,Employee.prototype.process=function(e=1,t){var n=.003*e,r=n*Math.random();this.exp+=n,this.cyclesUntilRaise-=e,this.cyclesUntilRaise<=0&&(this.salary+=EmployeeRaiseAmount,this.cyclesUntilRaise+=CyclesPerEmployeeRaise);var a=n*Math.random();return this.pos===_EmployeePositions__WEBPACK_IMPORTED_MODULE_3__.EmployeePositions.Training&&(this.cha+=a,this.exp+=a,this.eff+=a),this.ene-=r,this.hap-=r,this.eneHappiness: "+Object(_utils_StringHelperFunctions__WEBPACK_IMPORTED_MODULE_28__.formatNumber)(this.hap,3)+"
    Energy: "+Object(_utils_StringHelperFunctions__WEBPACK_IMPORTED_MODULE_28__.formatNumber)(this.ene,3)+"
    Intelligence: "+Object(_utils_StringHelperFunctions__WEBPACK_IMPORTED_MODULE_28__.formatNumber)(i,3)+"
    Charisma: "+Object(_utils_StringHelperFunctions__WEBPACK_IMPORTED_MODULE_28__.formatNumber)(a,3)+"
    Experience: "+Object(_utils_StringHelperFunctions__WEBPACK_IMPORTED_MODULE_28__.formatNumber)(this.exp,3)+"
    Creativity: "+Object(_utils_StringHelperFunctions__WEBPACK_IMPORTED_MODULE_28__.formatNumber)(r,3)+"
    Efficiency: "+Object(_utils_StringHelperFunctions__WEBPACK_IMPORTED_MODULE_28__.formatNumber)(o,3)+"
    Salary: "+_ui_numeralFormat__WEBPACK_IMPORTED_MODULE_18__.numeralWrapper.format(this.sal,"$0.000a")+"/ s
    "}));var s=Object(_utils_uiHelpers_createElement__WEBPACK_IMPORTED_MODULE_25__.createElement)("select",{});for(var l in _EmployeePositions__WEBPACK_IMPORTED_MODULE_3__.EmployeePositions)_EmployeePositions__WEBPACK_IMPORTED_MODULE_3__.EmployeePositions.hasOwnProperty(l)&&s.add(Object(_utils_uiHelpers_createElement__WEBPACK_IMPORTED_MODULE_25__.createElement)("option",{text:_EmployeePositions__WEBPACK_IMPORTED_MODULE_3__.EmployeePositions[l],value:_EmployeePositions__WEBPACK_IMPORTED_MODULE_3__.EmployeePositions[l]}));s.addEventListener("change",()=>{this.pos=s.options[s.selectedIndex].value});for(var c=0;c=this.size},OfficeSpace.prototype.process=function(e=1,t){t.corporation;var n=t.industry;if(n.hasResearch("HRBuddy-Recruitment")&&!this.atCapacity()){const e=this.hireRandomEmployee();n.hasResearch("HRBuddy-Training")&&(e.pos=_EmployeePositions__WEBPACK_IMPORTED_MODULE_3__.EmployeePositions.Training)}this.maxEne=100,this.maxHap=100,this.maxMor=100,n.hasResearch("Go-Juice")&&(this.maxEne+=10),n.hasResearch("JoyWire")&&(this.maxHap+=10),n.hasResearch("Sti.mu")&&(this.maxMor+=10);var r=1;n.funds<0&&n.lastCycleRevenue<0?r=Math.pow(.99,e):n.funds>0&&n.lastCycleRevenue>0&&(r=Math.pow(1.01,e));const a=n.hasResearch("AutoBrew"),i=n.hasResearch("AutoPartyManager");var o=0;for(let t=0;tCharisma: "+Object(_utils_StringHelperFunctions__WEBPACK_IMPORTED_MODULE_28__.formatNumber)(t.cha,1)+"
    Experience: "+Object(_utils_StringHelperFunctions__WEBPACK_IMPORTED_MODULE_28__.formatNumber)(t.exp,1)+"
    Creativity: "+Object(_utils_StringHelperFunctions__WEBPACK_IMPORTED_MODULE_28__.formatNumber)(t.cre,1)+"
    Efficiency: "+Object(_utils_StringHelperFunctions__WEBPACK_IMPORTED_MODULE_28__.formatNumber)(t.eff,1)+"
    Salary: "+_ui_numeralFormat__WEBPACK_IMPORTED_MODULE_18__.numeralWrapper.format(t.sal,"$0.000a")+" s
    ",clickListener:()=>(n.hireEmployee(t,e),Object(_utils_uiHelpers_removeElementById__WEBPACK_IMPORTED_MODULE_33__.removeElementById)("cmpy-mgmt-hire-employee-popup"),!1)})},g=Object(_utils_uiHelpers_createElement__WEBPACK_IMPORTED_MODULE_25__.createElement)("a",{class:"a-link-button",innerText:"Cancel",float:"right",clickListener:()=>(Object(_utils_uiHelpers_removeElementById__WEBPACK_IMPORTED_MODULE_33__.removeElementById)("cmpy-mgmt-hire-employee-popup"),!1)}),_=[h,d(u,this),d(m,this),d(p,this),g];Object(_utils_uiHelpers_createPopup__WEBPACK_IMPORTED_MODULE_26__.createPopup)("cmpy-mgmt-hire-employee-popup",_)}},OfficeSpace.prototype.hireEmployee=function(e,t){var n=t.corporation,r=(t.industry,Object(_utils_YesNoBox__WEBPACK_IMPORTED_MODULE_34__.yesNoTxtInpBoxGetYesButton)()),a=Object(_utils_YesNoBox__WEBPACK_IMPORTED_MODULE_34__.yesNoTxtInpBoxGetNoButton)();r.innerHTML="Hire",a.innerHTML="Cancel",r.addEventListener("click",()=>{for(var t=Object(_utils_YesNoBox__WEBPACK_IMPORTED_MODULE_34__.yesNoTxtInpBoxGetInput)(),r=0;rObject(_utils_YesNoBox__WEBPACK_IMPORTED_MODULE_34__.yesNoTxtInpBoxClose)()),Object(_utils_YesNoBox__WEBPACK_IMPORTED_MODULE_34__.yesNoTxtInpBoxCreate)("Give your employee a nickname!")},OfficeSpace.prototype.hireRandomEmployee=function(){if(!this.atCapacity()&&null==document.getElementById("cmpy-mgmt-hire-employee-popup")){var e=Object(_utils_helpers_getRandomInt__WEBPACK_IMPORTED_MODULE_29__.getRandomInt)(76,100)/100,t=Object(_utils_helpers_getRandomInt__WEBPACK_IMPORTED_MODULE_29__.getRandomInt)(50,100),n=Object(_utils_helpers_getRandomInt__WEBPACK_IMPORTED_MODULE_29__.getRandomInt)(50,100),r=Object(_utils_helpers_getRandomInt__WEBPACK_IMPORTED_MODULE_29__.getRandomInt)(50,100),a=Object(_utils_helpers_getRandomInt__WEBPACK_IMPORTED_MODULE_29__.getRandomInt)(50,100),i=Object(_utils_helpers_getRandomInt__WEBPACK_IMPORTED_MODULE_29__.getRandomInt)(50,100),o=new Employee({intelligence:t*e,charisma:n*e,experience:r*e,creativity:a*e,efficiency:i*e,salary:EmployeeSalaryMultiplier*(t+n+r+a+i)*e}),s=Object(_utils_StringHelperFunctions__WEBPACK_IMPORTED_MODULE_28__.generateRandomString)(7);for(let e=0;e=CyclesPerIndustryStateCycle){const t=this.getState(),n=1,r=n*CyclesPerIndustryStateCycle;if(this.storedCycles-=r,this.divisions.forEach(function(r){r.process(n,t,e)}),this.shareSaleCooldown>0&&(this.shareSaleCooldown-=r),this.issueNewSharesCooldown>0&&(this.issueNewSharesCooldown-=r),"START"===t){this.revenue=new decimal_js__WEBPACK_IMPORTED_MODULE_40__.a(0),this.expenses=new decimal_js__WEBPACK_IMPORTED_MODULE_40__.a(0),this.divisions.forEach(e=>{e.lastCycleRevenue!==-1/0&&e.lastCycleRevenue!==1/0&&e.lastCycleExpenses!==-1/0&&e.lastCycleExpenses!==1/0&&(this.revenue=this.revenue.plus(e.lastCycleRevenue),this.expenses=this.expenses.plus(e.lastCycleExpenses))});const e=this.revenue.minus(this.expenses).times(n*SecsPerMarketCycle);if(isNaN(this.funds)&&(Object(_utils_DialogBox__WEBPACK_IMPORTED_MODULE_21__.dialogBoxCreate)("There was an error calculating your Corporations funds and they got reset to 0. This is a bug. Please report to game developer.

    (Your funds have been set to $150b for the inconvenience)"),this.funds=new decimal_js__WEBPACK_IMPORTED_MODULE_40__.a(15e10)),this.dividendPercentage>0&&e>0)if(isNaN(this.dividendPercentage)||this.dividendPercentage<0||this.dividendPercentage>DividendMaxPercentage)console.error(`Invalid Corporation dividend percentage: ${this.dividendPercentage}`);else{const t=this.dividendPercentage/100*e,n=e-t,r=t/this.totalShares,a=this.numShares*r*(1-this.dividendTaxPercentage/100);_Player__WEBPACK_IMPORTED_MODULE_17__.Player.gainMoney(a),_Player__WEBPACK_IMPORTED_MODULE_17__.Player.recordMoneySource(a,"corporation"),this.funds=this.funds.plus(n)}else this.funds=this.funds.plus(e);this.updateSharePrice()}this.state.nextState(),_ui_navigationTracking__WEBPACK_IMPORTED_MODULE_19__.routing.isOn(_ui_navigationTracking__WEBPACK_IMPORTED_MODULE_19__.Page.Corporation)&&this.rerender()}},Corporation.prototype.determineValuation=function(){var e,t=this.revenue.minus(this.expenses).toNumber();return this.public?(this.dividendPercentage>0&&(t*=(100-this.dividendPercentage)/100),e=this.funds.toNumber()+85e3*t,e*=Math.pow(1.1,this.divisions.length),e=Math.max(e,0)):(e=1e10+Math.max(this.funds.toNumber(),0)/3,t>0?(e+=315e3*t,e*=Math.pow(1.1,this.divisions.length)):e=1e10*Math.pow(1.1,this.divisions.length),e-=e%1e6),e*_BitNode_BitNodeMultipliers__WEBPACK_IMPORTED_MODULE_11__.BitNodeMultipliers.CorporationValuation},Corporation.prototype.getInvestment=function(){var e,t=this.determineValuation();let n=4;switch(this.fundingRound){case 0:e=.1,n=4;break;case 1:e=.35,n=3;break;case 2:e=.25,n=3;break;case 3:e=.2,n=2.5;break;case 4:return}var r=t*e*n,a=Math.floor(INITIALSHARES*e),i=Object(_utils_YesNoBox__WEBPACK_IMPORTED_MODULE_34__.yesNoBoxGetYesButton)(),o=Object(_utils_YesNoBox__WEBPACK_IMPORTED_MODULE_34__.yesNoBoxGetNoButton)();i.innerHTML="Accept",o.innerHML="Reject",i.addEventListener("click",()=>(++this.fundingRound,this.funds=this.funds.plus(r),this.numShares-=a,this.rerender(),Object(_utils_YesNoBox__WEBPACK_IMPORTED_MODULE_34__.yesNoBoxClose)())),o.addEventListener("click",()=>Object(_utils_YesNoBox__WEBPACK_IMPORTED_MODULE_34__.yesNoBoxClose)()),Object(_utils_YesNoBox__WEBPACK_IMPORTED_MODULE_34__.yesNoBoxCreate)("An investment firm has offered you "+_ui_numeralFormat__WEBPACK_IMPORTED_MODULE_18__.numeralWrapper.format(r,"$0.000a")+" in funding in exchange for a "+_ui_numeralFormat__WEBPACK_IMPORTED_MODULE_18__.numeralWrapper.format(100*e,"0.000a")+"% stake in the company ("+_ui_numeralFormat__WEBPACK_IMPORTED_MODULE_18__.numeralWrapper.format(a,"0.000a")+" shares).

    Do you accept or reject this offer?

    Hint: Investment firms will offer more money if your corporation is turning a profit")},Corporation.prototype.goPublic=function(){var e,t=this.determineValuation()/this.totalShares,n=Object(_utils_uiHelpers_createElement__WEBPACK_IMPORTED_MODULE_25__.createElement)("p",{innerHTML:"Enter the number of shares you would like to issue for your IPO. These shares will be publicly sold and you will no longer own them. Your Corporation will receive "+_ui_numeralFormat__WEBPACK_IMPORTED_MODULE_18__.numeralWrapper.format(t,"$0.000a")+" per share (the IPO money will be deposited directly into your Corporation's funds).

    You have a total of "+_ui_numeralFormat__WEBPACK_IMPORTED_MODULE_18__.numeralWrapper.format(this.numShares,"0.000a")+" of shares that you can issue."}),r=Object(_utils_uiHelpers_createElement__WEBPACK_IMPORTED_MODULE_25__.createElement)("input",{type:"number",placeholder:"Shares to issue",onkeyup:t=>{t.preventDefault(),t.keyCode===_utils_helpers_keyCodes__WEBPACK_IMPORTED_MODULE_31__.KEY.ENTER&&e.click()}}),a=Object(_utils_uiHelpers_createElement__WEBPACK_IMPORTED_MODULE_25__.createElement)("br",{});e=Object(_utils_uiHelpers_createElement__WEBPACK_IMPORTED_MODULE_25__.createElement)("a",{class:"a-link-button",innerText:"Go Public",clickListener:()=>{var e=Math.round(r.value),t=this.determineValuation()/this.totalShares;return isNaN(e)?(Object(_utils_DialogBox__WEBPACK_IMPORTED_MODULE_21__.dialogBoxCreate)("Invalid value for number of issued shares"),!1):e>this.numShares?(Object(_utils_DialogBox__WEBPACK_IMPORTED_MODULE_21__.dialogBoxCreate)("Error: You don't have that many shares to issue!"),!1):(this.public=!0,this.sharePrice=t,this.issuedShares=e,this.numShares-=e,this.funds=this.funds.plus(e*t),this.rerender(),Object(_utils_uiHelpers_removeElementById__WEBPACK_IMPORTED_MODULE_33__.removeElementById)("cmpy-mgmt-go-public-popup"),Object(_utils_DialogBox__WEBPACK_IMPORTED_MODULE_21__.dialogBoxCreate)(`You took your ${this.name} public and earned `+`${_ui_numeralFormat__WEBPACK_IMPORTED_MODULE_18__.numeralWrapper.formatMoney(e*t)} in your IPO`),!1)}});var i=Object(_utils_uiHelpers_createElement__WEBPACK_IMPORTED_MODULE_25__.createElement)("a",{class:"a-link-button",innerText:"Cancel",clickListener:()=>(Object(_utils_uiHelpers_removeElementById__WEBPACK_IMPORTED_MODULE_33__.removeElementById)("cmpy-mgmt-go-public-popup"),!1)});Object(_utils_uiHelpers_createPopup__WEBPACK_IMPORTED_MODULE_26__.createPopup)("cmpy-mgmt-go-public-popup",[n,a,r,e,i])},Corporation.prototype.getTargetSharePrice=function(){return this.determineValuation()/(2*(this.totalShares-this.numShares)+1)},Corporation.prototype.updateSharePrice=function(){const e=this.getTargetSharePrice();this.sharePrice<=e?this.sharePrice*=1+.01*Math.random():this.sharePrice*=1-.01*Math.random(),this.sharePrice<=.01&&(this.sharePrice=.01)},Corporation.prototype.immediatelyUpdateSharePrice=function(){this.sharePrice=this.getTargetSharePrice()},Corporation.prototype.calculateShareSale=function(e){let t=e,n=this.shareSalesUntilPriceUpdate,r=this.sharePrice,a=0,i=0;const o=Math.ceil(e/SHARESPERPRICEUPDATE);if(!(isNaN(o)||o>1e7)){for(let e=0;e3600?`${Math.floor(t/3600)} hour(s)`:t>60?`${Math.floor(t/60)} minute(s)`:`${Math.floor(t)} second(s)`},Corporation.prototype.unlock=function(e){const t=e[0],n=e[1];for(;this.unlockUpgrades.length<=t;)this.unlockUpgrades.push(0);this.funds.lt(n)?Object(_utils_DialogBox__WEBPACK_IMPORTED_MODULE_21__.dialogBoxCreate)("You don't have enough funds to unlock this!"):(this.unlockUpgrades[t]=1,this.funds=this.funds.minus(n),5===t?this.dividendTaxPercentage-=5:6===t&&(this.dividendTaxPercentage-=10))},Corporation.prototype.upgrade=function(e){for(var t=e[0],n=e[1],r=e[2],a=e[3];this.upgrades.length<=t;)this.upgrades.push(0);for(;this.upgradeMultipliers.length<=t;)this.upgradeMultipliers.push(1);var i=n*Math.pow(r,this.upgrades[t]);if(this.funds.lt(i))Object(_utils_DialogBox__WEBPACK_IMPORTED_MODULE_21__.dialogBoxCreate)("You don't have enough funds to purchase this!");else if(++this.upgrades[t],this.funds=this.funds.minus(i),this.upgradeMultipliers[t]=1+this.upgrades[t]*a,1===t)for(var o=0;o=t.HacknetServerMaxCache)return 1/0;const r=t.HacknetServerUpgradeCacheMult;let a=0,i=this.cache;for(let e=0;e=t.HacknetServerMaxCores)return 1/0;const a=t.HacknetServerUpgradeCoreMult;let i=0,o=this.cores;for(let e=0;e=t.HacknetServerMaxLevel)return 1/0;const a=t.HacknetServerUpgradeLevelMult;let i=0,o=this.level;for(let e=0;e=t.HacknetServerMaxRam)return 1/0;let a=0,i=Math.round(Math.log2(this.maxRam)),o=this.maxRam;for(let e=0;e
    automate [var] [val] [hi/low] Configure simple automation for Bladeburner tasks
    clear/cls Clear the console
    help [cmd] Display this help text, or help text for a specific command
    log [en/dis] [type] Enable or disable logging for events and actions
    skill [action] [name] Level or display info about your Bladeburner skills
    start [type] [name] Start a Bladeburner action/task
    stop Stops your current Bladeburner action/task
    ",automate:'automate [var] [val] [hi/low]

    A simple way to automate your Bladeburner actions. This console command can be used to automatically start an action when your stamina rises above a certain threshold, and automatically switch to another action when your stamina drops below another threshold.

    automate status - Check the current status of your automation and get a brief description of what it\'ll do
    automate en - Enable the automation feature
    automate dis - Disable the automation feature

    There are four properties that must be set for this automation to work properly. Here is how to set them:

    automate stamina 100 high
    automate contract Tracking high
    automate stamina 50 low
    automate general "Field Analysis" low

    Using the four console commands above will set the automation to perform Tracking contracts if your stamina is 100 or higher, and then switch to Field Analysis if your stamina drops below 50. Note that when setting the action, the name of the action is CASE-SENSITIVE. It must exactly match whatever the name is in the UI.',clear:"clear

    Clears the console",cls:"cls

    Clears the console",help:"help [command]

    Running 'help' with no arguments displays the general help text, which lists all console commands and a brief description of what they do. A command can be specified to get more specific help text about that particular command. For example:

    help automate

    will display specific information about using the automate console command",log:"log [en/dis] [type]

    Enable or disable logging. By default, the results of completing actions such as contracts/operations are logged in the console. There are also random events that are logged in the console as well. The five categories of things that get logged are:

    [general, contracts, ops, blackops, events]

    The logging for these categories can be enabled or disabled like so:

    log dis contracts - Disables logging that occurs when contracts are completed
    log en contracts - Enables logging that occurs when contracts are completed
    log dis events - Disables logging for Bladeburner random events

    Logging can be universally enabled/disabled using the 'all' keyword:

    log dis all
    log en all",skill:'skill [action] [name]

    Level or display information about your skills.

    To display information about all of your skills and your multipliers, use:

    skill list

    To display information about a specific skill, specify the name of the skill afterwards. Note that the name of the skill is case-sensitive. Enter it exactly as seen in the UI. If the name of the skill has whitespace, enclose the name of the skill in double quotation marks:

    skill list Reaper
    skill list "Digital Observer"

    This console command can also be used to level up skills:

    skill level [skill name]',start:'start [type] [name]

    Start an action. An action is specified by its type and its name. The name is case-sensitive. It must appear exactly as it does in the UI. If the name of the action has whitespace, enclose it in double quotation marks. Valid action types include:

    [general, contract, op, blackop]

    Examples:

    start contract Tracking
    start op "Undercover Operation"
    ',stop:"stop

    Stop your current action and go idle"};function j(e={}){this.name=e.name?e.name:D[2],this.pop=e.pop?e.pop:Object(C.getRandomInt)(I,1.5*I),this.popEst=this.pop*(Math.random()+.5),this.comms=e.comms?e.comms:Object(C.getRandomInt)(5,150),this.commsEst=this.comms+Object(C.getRandomInt)(-5,5),this.commsEst<0&&(this.commsEst=0),this.chaos=0}function F(e={name:"foo",desc:"foo"}){if(!e.name)throw new Error("Failed to initialize Bladeburner Skill. No name was specified in ctor");if(this.name=e.name,!e.desc)throw new Error("Failed to initialize Bladeburner Skills. No desc was specified in ctor");this.desc=e.desc,this.baseCost=e.baseCost?e.baseCost:1,this.costInc=e.costInc?e.costInc:1,e.maxLvl&&(this.maxLvl=e.maxLvl),e.successChanceAll&&(this.successChanceAll=e.successChanceAll),e.successChanceStealth&&(this.successChanceStealth=e.successChanceStealth),e.successChanceKill&&(this.successChanceKill=e.successChanceKill),e.successChanceContract&&(this.successChanceContract=e.successChanceContract),e.successChanceOperation&&(this.successChanceOperation=e.successChanceOperation),e.successChanceEstimate&&(this.successChanceEstimate=e.successChanceEstimate),e.actionTime&&(this.actionTime=e.actionTime),e.effHack&&(this.effHack=e.effHack),e.effStr&&(this.effStr=e.effStr),e.effDef&&(this.effDef=e.effDef),e.effDex&&(this.effDex=e.effDex),e.effAgi&&(this.effAgi=e.effAgi),e.effCha&&(this.effCha=e.effCha),e.stamina&&(this.stamina=e.stamina),e.money&&(this.money=e.money),e.expGain&&(this.expGain=e.expGain),e.weaponAbility&&(this.weaponAbility=e.weaponAbility),e.gunAbility&&(this.gunAbility=e.gunAbility)}e(document).keydown(function(e){if(h.routing.isOn(h.Page.Bladeburner)){if(!(m.Player.bladeburner instanceof X))return;let i=m.Player.bladeburner.consoleHistory;if(e.keyCode===P.KEY.ENTER){e.preventDefault();var t=Q.consoleInput.value;t.length>0&&(m.Player.bladeburner.postToConsole("> "+t),m.Player.bladeburner.resetConsoleInput(),m.Player.bladeburner.executeConsoleCommands(t))}if(e.keyCode===P.KEY.UPARROW){if(null==Q.consoleInput)return;var n=L;if(0===(a=i.length))return;(n<0||n>a)&&(L=a),0!==n&&--L;var r=i[L];Q.consoleInput.value=r,Object(y.setTimeoutRef)(function(){Q.consoleInput.selectionStart=Q.consoleInput.selectionEnd=1e4},0)}if(e.keyCode===P.KEY.DOWNARROW){if(null==Q.consoleInput)return;var a;n=L;if(0==(a=i.length))return;if((n<0||n>a)&&(L=a),n==a||n==a-1)L=a,Q.consoleInput.value="";else{r=i[++L];Q.consoleInput.value=r}}}}),j.prototype.improvePopulationEstimateByCount=function(e){if(isNaN(e))throw new Error("NaN passeed into City.improvePopulationEstimateByCount()");this.popEstthis.pop&&(this.popEst=this.pop)):this.popEst>this.pop&&(this.popEst-=e,this.popEstthis.pop&&(this.popEst=this.pop)):this.popEst>this.pop&&(this.popEst*=1-e/100,this.popEstthis.comms&&(this.commsEst=this.comms)):this.commsEst>this.comms&&(this.commsEst-=e,this.commsEst0?1:-1),this.pop+=n,t.changeEstEqually&&(this.popEst+=n,this.popEst<0&&(this.popEst=0)),n}},j.prototype.changeChaosByCount=function(e){if(isNaN(e))throw new Error("NaN passed into City.changeChaosByCount()");0!==e&&(this.chaos+=e,this.chaos<0&&(this.chaos=0))},j.prototype.changeChaosByPercentage=function(e){if(isNaN(e))throw new Error("NaN passed into City.chaosChaosByPercentage()");if(0!==e){var t=this.chaos*(e/100);this.chaos+=t,this.chaos<0&&(this.chaos=0)}},j.prototype.toJSON=function(){return Object(_.Generic_toJSON)("City",this)},j.fromJSON=function(e){return Object(_.Generic_fromJSON)(j,e.data)},_.Reviver.constructors.City=j,F.prototype.calculateCost=function(e){return Math.floor((this.baseCost+e*this.costInc)*i.BitNodeMultipliers.BladeburnerSkillCost)};const U={},H={BladesIntuition:"Blade's Intuition",Cloak:"Cloak",Marksman:"Marksman",WeaponProficiency:"Weapon Proficiency",ShortCircuit:"Short-Circuit",DigitalObserver:"Digital Observer",Tracer:"Tracer",Overclock:"Overclock",Reaper:"Reaper",EvasiveSystem:"Evasive System",Datamancer:"Datamancer",CybersEdge:"Cyber's Edge",HandsOfMidas:"Hands of Midas",Hyperdrive:"Hyperdrive"};function G(e={}){this.name=e.name?e.name:"",this.desc=e.desc?e.desc:"",this.level=1,this.maxLevel=1,this.autoLevel=!0,this.baseDifficulty=e.baseDifficulty?Object(b.addOffset)(e.baseDifficulty,10):100,this.difficultyFac=e.difficultyFac?e.difficultyFac:1.01,this.rewardFac=e.rewardFac?e.rewardFac:1.02,this.successes=0,this.failures=0,this.rankGain=e.rankGain?e.rankGain:0,e.rankLoss&&(this.rankLoss=e.rankLoss),e.hpLoss&&(this.hpLoss=e.hpLoss,this.hpLost=0),this.isStealth=!!e.isStealth,this.isKill=!!e.isKill,this.count=e.count?e.count:Object(C.getRandomInt)(1e3,25e3),this.countGrowth=e.countGrowth?e.countGrowth:Object(C.getRandomInt)(1,5);this.weights=e.weights?e.weights:{hack:1/7,str:1/7,def:1/7,dex:1/7,agi:1/7,cha:1/7,int:1/7};let t=0;for(const e in this.weights)this.weights.hasOwnProperty(e)&&(t+=this.weights[e]);if(t-1>=10*Number.EPSILON)throw new Error("Invalid weights when constructing Action "+this.name+". The weights should sum up to 1. They sum up to :1");this.decays=e.decays?e.decays:{hack:.9,str:.9,def:.9,dex:.9,agi:.9,cha:.9,int:.9};for(const e in this.decays)if(this.decays.hasOwnProperty(e)&&this.decays[e]>1)throw new Error("Invalid decays when constructing Action "+this.name+". Decay value cannot be greater than 1")}G.prototype.getDifficulty=function(){var e=this.baseDifficulty*Math.pow(this.difficultyFac,this.level-1);if(isNaN(e))throw new Error("Calculated NaN in Action.getDifficulty()");return e},G.prototype.getSuccessChance=function(e,t={}){if(null==e)throw new Error("Invalid Bladeburner instance passed into Action.getSuccessChance");var n=this.getDifficulty(),r=0;for(var a in this.weights)if(this.weights.hasOwnProperty(a)){var i=m.Player.queryStatFromString(a),o="eff"+a.charAt(0).toUpperCase()+a.slice(1),s=e.skillMultipliers[o];null==s&&(console.log("ERROR: Failed to find Bladeburner Skill multiplier for: "+a),s=1),r+=this.weights[a]*Math.pow(s*i,this.decays[a])}(r*=e.calculateStaminaPenalty(),this instanceof z||this instanceof V)&&(this.teamCount&&this.teamCount>0&&(this.teamCount=Math.min(this.teamCount,e.teamSize),r*=Math.pow(this.teamCount,.05)));if(!(this instanceof V)){var l=e.getCurrentCity();if(t.est?r*=Math.pow(l.popEst/I,.7):r*=Math.pow(l.pop/I,.7),l.chaos>50){var c=l.chaos-50+1;n*=Math.pow(c,.1)}if(this instanceof z&&"Raid"===this.name&&l.comms<=0)return 0}if(r*=e.skillMultipliers.successChanceAll,(this instanceof z||this instanceof V)&&(r*=e.skillMultipliers.successChanceOperation),this instanceof Y&&(r*=e.skillMultipliers.successChanceContract),this.isStealth&&(r*=e.skillMultipliers.successChanceStealth),this.isKill&&(r*=e.skillMultipliers.successChanceKill),r*=m.Player.bladeburner_success_chance_mult,isNaN(r))throw new Error("Competence calculated as NaN in Action.getSuccessChance()");return Math.min(1,r/n)},G.prototype.attempt=function(e){return Math.random()=this.getSuccessesNeededForNextLevel(e)&&++this.maxLevel},G.prototype.toJSON=function(){return Object(_.Generic_toJSON)("Action",this)},G.fromJSON=function(e){return Object(_.Generic_fromJSON)(G,e.data)},_.Reviver.constructors.Action=G;const K={},q=Object.freeze({Idle:1,Contract:2,Operation:3,BlackOp:4,BlackOperation:4,Training:5,Recruitment:6,FieldAnalysis:7,"Field Analysis":7,Diplomacy:8,"Hyperbolic Regeneration Chamber":9});function $(e={}){e.name&&(this.name=e.name),e.type&&(this.type=e.type)}function Y(e={}){G.call(this,e)}function z(e={}){G.call(this,e),this.reqdRank=e.reqdRank?e.reqdRank:100,this.teamCount=e.teamCount?e.teamCount:0}function V(e={}){z.call(this,e),this.count=1,this.countGrowth=0}$.prototype.toJSON=function(){return Object(_.Generic_toJSON)("ActionIdentifier",this)},$.fromJSON=function(e){return Object(_.Generic_fromJSON)($,e.data)},_.Reviver.constructors.ActionIdentifier=$,Y.prototype=Object.create(G.prototype),Y.prototype.toJSON=function(){return Object(_.Generic_toJSON)("Contract",this)},Y.fromJSON=function(e){return Object(_.Generic_fromJSON)(Y,e.data)},_.Reviver.constructors.Contract=Y,z.prototype=Object.create(G.prototype),z.prototype.toJSON=function(){return Object(_.Generic_toJSON)("Operation",this)},z.fromJSON=function(e){return Object(_.Generic_fromJSON)(z,e.data)},_.Reviver.constructors.Operation=z,V.prototype=Object.create(G.prototype),V.prototype.toJSON=function(){return Object(_.Generic_toJSON)("BlackOperation",this)},V.fromJSON=function(e){return Object(_.Generic_fromJSON)(V,e.data)},_.Reviver.constructors.BlackOperation=V;const J={};function X(e={}){this.numHosp=0,this.moneyLost=0,this.rank=0,this.maxRank=0,this.skillPoints=0,this.totalSkillPoints=0,this.teamSize=0,this.teamLost=0,this.storedCycles=0,this.randomEventCounter=Object(C.getRandomInt)(240,600),this.actionTimeToComplete=0,this.actionTimeCurrent=0;var t=q.Idle;this.action=new $({type:t}),this.cities={};for(var n=0;n
    Does NOT require stamina."}),K[e="Recruitment"]=new G({name:e,desc:"Attempt to recruit members for your Bladeburner team. These members can help you conduct operations.

    Does NOT require stamina."}),K[e="Diplomacy"]=new G({name:e,desc:"Improve diplomatic relations with the Synthoid population. Completing this action will reduce the Chaos level in your current city.

    Does NOT require stamina."}),K[e="Hyperbolic Regeneration Chamber"]=new G({name:e,desc:"Enter cryogenic stasis using the Bladeburner division's hi-tech Regeneration Chamber. This will slowly heal your wounds and slightly increase your stamina.

    "}),J["Operation Typhoon"]=new V({name:"Operation Typhoon",desc:"Obadiah Zenyatta is the leader of a RedWater PMC. It has long been known among the intelligence community that Zenyatta, along with the rest of the PMC, is a Synthoid.

    The goal of Operation Typhoon is to find and eliminate Zenyatta and RedWater by any means necessary. After the task is completed, the actions must be covered up from the general public.",baseDifficulty:2e3,reqdRank:2500,rankGain:50,rankLoss:10,hpLoss:100,weights:{hack:.1,str:.2,def:.2,dex:.2,agi:.2,cha:0,int:.1},decays:{hack:.6,str:.8,def:.8,dex:.8,agi:.8,cha:0,int:.75},isKill:!0}),J["Operation Zero"]=new V({name:"Operation Zero",desc:"AeroCorp is one of the world's largest defense contractors. It's leader, Steve Watataki, is thought to be a supporter of Synthoid rights. He must be removed.

    The goal of Operation Zero is to covertly infiltrate AeroCorp and uncover any incriminating evidence or information against Watataki that will cause him to be removed from his position at AeroCorp. Incriminating evidence can be fabricated as a last resort. Be warned that AeroCorp has some of the most advanced security measures in the world.",baseDifficulty:2500,reqdRank:5e3,rankGain:60,rankLoss:15,hpLoss:50,weights:{hack:.2,str:.15,def:.15,dex:.2,agi:.2,cha:0,int:.1},decays:{hack:.6,str:.8,def:.8,dex:.8,agi:.8,cha:0,int:.75},isStealth:!0}),J["Operation X"]=new V({name:"Operation X",desc:"We have recently discovered an underground publication group called Samizdat. Even though most of their publications are nonsensical conspiracy theories, the average human is gullible enough to believe them. Many of their works discuss Synthoids and pose a threat to society. The publications are spreading rapidly in China and other Eastern countries.

    Samizdat has done a good job of keeping hidden and anonymous. However, we've just received intelligence that their base of operations is in Ishima's underground sewer systems. Your task is to investigate the sewer systems, and eliminate Samizdat. They must never publish anything again.",baseDifficulty:3e3,reqdRank:7500,rankGain:75,rankLoss:15,hpLoss:100,weights:{hack:.1,str:.2,def:.2,dex:.2,agi:.2,cha:0,int:.1},decays:{hack:.6,str:.8,def:.8,dex:.8,agi:.8,cha:0,int:.75},isKill:!0}),J["Operation Titan"]=new V({name:"Operation Titan",desc:"Several months ago Titan Laboratories' Bioengineering department was infiltrated by Synthoids. As far as we know, Titan Laboratories' management has no knowledge about this. We don't know what the Synthoids are up to, but the research that they could be conducting using Titan Laboraties' vast resources is potentially very dangerous.

    Your goal is to enter and destroy the Bioengineering department's facility in Aevum. The task is not just to retire the Synthoids there, but also to destroy any information or research at the facility that is relevant to the Synthoids and their goals.",baseDifficulty:4e3,reqdRank:1e4,rankGain:100,rankLoss:20,hpLoss:100,weights:{hack:.1,str:.2,def:.2,dex:.2,agi:.2,cha:0,int:.1},decays:{hack:.6,str:.8,def:.8,dex:.8,agi:.8,cha:0,int:.75},isKill:!0}),J["Operation Ares"]=new V({name:"Operation Ares",desc:"One of our undercover agents, Agent Carter, has informed us of a massive weapons deal going down in Dubai between rogue Russian militants and a radical Synthoid community. These weapons are next-gen plasma and energy weapons. It is critical for the safety of humanity that this deal does not happen.

    Your task is to intercept the deal. Leave no survivors.",baseDifficulty:5e3,reqdRank:12500,rankGain:125,rankLoss:20,hpLoss:200,weights:{hack:0,str:.25,def:.25,dex:.25,agi:.25,cha:0,int:0},decays:{hack:0,str:.8,def:.8,dex:.8,agi:.8,cha:0,int:.75},isKill:!0}),J["Operation Archangel"]=new V({name:"Operation Archangel",desc:"Our analysts have discovered that the popular Red Rabbit brothel in Amsterdam is run and 'staffed' by MK-VI Synthoids. Intelligence suggests that the profit from this brothel is used to fund a large black market arms trafficking operation.

    The goal of this operation is to take out the leaders that are running the Red Rabbit brothel. Try to limit the number of other casualties, but do what you must to complete the mission.",baseDifficulty:7500,reqdRank:15e3,rankGain:200,rankLoss:20,hpLoss:25,weights:{hack:0,str:.2,def:.2,dex:.3,agi:.3,cha:0,int:0},decays:{hack:0,str:.8,def:.8,dex:.8,agi:.8,cha:0,int:.75},isKill:!0}),J["Operation Juggernaut"]=new V({name:"Operation Juggernaut",desc:"The CIA has just encountered a new security threat. A new criminal group, lead by a shadowy operative who calls himself Juggernaut, has been smuggling drugs and weapons (including suspected bioweapons) into Sector-12. We also have reason to believe the tried to break into one of Universal Energy's facilities in order to cause a city-wide blackout. The CIA suspects that Juggernaut is a heavily-augmented Synthoid, and have thus enlisted our help.

    Your mission is to eradicate Juggernaut and his followers.",baseDifficulty:1e4,reqdRank:2e4,rankGain:300,rankLoss:40,hpLoss:300,weights:{hack:0,str:.25,def:.25,dex:.25,agi:.25,cha:0,int:0},decays:{hack:0,str:.8,def:.8,dex:.8,agi:.8,cha:0,int:.75},isKill:!0}),J["Operation Red Dragon"]=new V({name:"Operation Red Dragon",desc:"The Tetrads criminal organization is suspected of reverse-engineering the MK-VI Synthoid design. We believe they altered and possibly improved the design and began manufacturing their own Synthoid models in order to bolster their criminal activities.

    Your task is to infiltrate and destroy the Tetrads' base of operations in Los Angeles. Intelligence tells us that their base houses one of their Synthoid manufacturing units.",baseDifficulty:12500,reqdRank:25e3,rankGain:500,rankLoss:50,hpLoss:500,weights:{hack:.05,str:.2,def:.2,dex:.25,agi:.25,cha:0,int:.05},decays:{hack:.6,str:.8,def:.8,dex:.8,agi:.8,cha:0,int:.75},isKill:!0}),J["Operation K"]=new V({name:"Operation K",desc:"CODE RED SITUATION. Our intelligence tells us that VitaLife has discovered a new android cloning technology. This technology is supposedly capable of cloning Synthoid, not only physically but also their advanced AI modules. We do not believe that VitaLife is trying to use this technology illegally or maliciously, but if any Synthoids were able to infiltrate the corporation and take advantage of this technology then the results would be catastrophic.

    We do not have the power or jurisdiction to shutdown this down through legal or political means, so we must resort to a covert operation. Your goal is to destroy this technology and eliminate anyone who was involved in its creation.",baseDifficulty:15e3,reqdRank:3e4,rankGain:750,rankLoss:60,hpLoss:1e3,weights:{hack:.05,str:.2,def:.2,dex:.25,agi:.25,cha:0,int:.05},decays:{hack:.6,str:.8,def:.8,dex:.8,agi:.8,cha:0,int:.75},isKill:!0}),J["Operation Deckard"]=new V({name:"Operation Deckard",desc:"Despite your success in eliminating VitaLife's new android-replicating technology in Operation K, we've discovered that a small group of MK-VI Synthoids were able to make off with the schematics and design of the technology before the Operation. It is almost a certainty that these Synthoids are some of the rogue MK-VI ones from the Synthoid Uprising.The goal of Operation Deckard is to hunt down these Synthoids and retire them. I don't need to tell you how critical this mission is.",baseDifficulty:2e4,reqdRank:4e4,rankGain:1e3,rankLoss:75,hpLoss:200,weights:{hack:0,str:.24,def:.24,dex:.24,agi:.24,cha:0,int:.04},decays:{hack:0,str:.8,def:.8,dex:.8,agi:.8,cha:0,int:.75},isKill:!0}),J["Operation Tyrell"]=new V({name:"Operation Tyrell",desc:"A week ago Blade Industries reported a small break-in at one of their Aevum Augmentation storage facitilities. We figured out that The Dark Army was behind the heist, and didn't think any more of it. However, we've just discovered that several known MK-VI Synthoids were part of that break-in group.

    We cannot have Synthoids upgrading their already-enhanced abilities with Augmentations. Your task is to hunt down the associated Dark Army members and eliminate them.",baseDifficulty:25e3,reqdRank:5e4,rankGain:1500,rankLoss:100,hpLoss:500,weights:{hack:.1,str:.2,def:.2,dex:.2,agi:.2,cha:0,int:.1},decays:{hack:.6,str:.8,def:.8,dex:.8,agi:.8,cha:0,int:.75},isKill:!0}),J["Operation Wallace"]=new V({name:"Operation Wallace",desc:"Based on information gathered from Operation Tyrell, we've discovered that The Dark Army was well aware that there were Synthoids amongst their ranks. Even worse, we believe that The Dark Army is working together with other criminal organizations such as The Syndicate and that they are planning some sort of large-scale takeover of multiple major cities, most notably Aevum. We suspect that Synthoids have infiltrated the ranks of these criminal factions and are trying to stage another Synthoid uprising.

    The best way to deal with this is to prevent it before it even happens. The goal of Operation Wallace is to destroy the Dark Army and Syndicate factions in Aevum immediately. Leave no survivors.",baseDifficulty:3e4,reqdRank:75e3,rankGain:2e3,rankLoss:150,hpLoss:1500,weights:{hack:0,str:.24,def:.24,dex:.24,agi:.24,cha:0,int:.04},decays:{hack:.6,str:.8,def:.8,dex:.8,agi:.8,cha:0,int:.75},isKill:!0}),J["Operation Shoulder of Orion"]=new V({name:"Operation Shoulder of Orion",desc:"China's Solaris Space Systems is secretly launching the first manned spacecraft in over a decade using Synthoids. We believe China is trying to establish the first off-world colonies.

    The mission is to prevent this launch without instigating an international conflict. When you accept this mission you will be officially disavowed by the NSA and the national government until after you successfully return. In the event of failure, all of the operation's team members must not let themselves be captured alive.",baseDifficulty:35e3,reqdRank:1e5,rankGain:2500,rankLoss:500,hpLoss:1500,weights:{hack:.1,str:.2,def:.2,dex:.2,agi:.2,cha:0,int:.1},decays:{hack:.6,str:.8,def:.8,dex:.8,agi:.8,cha:0,int:.75},isStealth:!0}),J["Operation Hyron"]=new V({name:"Operation Hyron",desc:"Our intelligence tells us that Fulcrum Technologies is developing a quantum supercomputer using human brains as core processors. This supercomputer is rumored to be able to store vast amounts of data and perform computations unmatched by any other supercomputer on the planet. But more importantly, the use of organic human brains means that the supercomputer may be able to reason abstractly and become self-aware.

    I do not need to remind you why sentient-level AIs pose a serious thread to all of mankind.

    The research for this project is being conducted at one of Fulcrum Technologies secret facilities in Aevum, codenamed 'Alpha Ranch'. Infiltrate the compound, delete and destroy the work, and then find and kill the project lead.",baseDifficulty:4e4,reqdRank:125e3,rankGain:3e3,rankLoss:1e3,hpLoss:500,weights:{hack:.1,str:.2,def:.2,dex:.2,agi:.2,cha:0,int:.1},decays:{hack:.6,str:.8,def:.8,dex:.8,agi:.8,cha:0,int:.75},isKill:!0}),J["Operation Morpheus"]=new V({name:"Operation Morpheus",desc:"DreamSense Technologies is an advertising company that uses special technology to transmit their ads into the peoples dreams and subconcious. They do this using broadcast transmitter towers. Based on information from our agents and informants in Chonqging, we have reason to believe that one of the broadcast towers there has been compromised by Synthoids and is being used to spread pro-Synthoid propaganda.

    The mission is to destroy this broadcast tower. Speed and stealth are of the upmost important for this.",baseDifficulty:45e3,reqdRank:15e4,rankGain:4e3,rankLoss:1e3,hpLoss:100,weights:{hack:.05,str:.15,def:.15,dex:.3,agi:.3,cha:0,int:.05},decays:{hack:.6,str:.8,def:.8,dex:.8,agi:.8,cha:0,int:.75},isStealth:!0}),J["Operation Ion Storm"]=new V({name:"Operation Ion Storm",desc:"Our analysts have uncovered a gathering of MK-VI Synthoids that have taken up residence in the Sector-12 Slums. We don't know if they are rogue Synthoids from the Uprising, but we do know that they have been stockpiling weapons, money, and other resources. This makes them dangerous.

    This is a full-scale assault operation to find and retire all of these Synthoids in the Sector-12 Slums.",baseDifficulty:5e4,reqdRank:175e3,rankGain:5e3,rankLoss:1e3,hpLoss:5e3,weights:{hack:0,str:.24,def:.24,dex:.24,agi:.24,cha:0,int:.04},decays:{hack:.6,str:.8,def:.8,dex:.8,agi:.8,cha:0,int:.75},isKill:!0}),J["Operation Annihilus"]=new V({name:"Operation Annihilus",desc:"Our superiors have ordered us to eradicate everything and everyone in an underground facility located in Aevum. They tell us that the facility houses many dangerous Synthoids and belongs to a terrorist organization called 'The Covenant'. We have no prior intelligence about this organization, so you are going in blind.",baseDifficulty:55e3,reqdRank:2e5,rankGain:7500,rankLoss:1e3,hpLoss:1e4,weights:{hack:0,str:.24,def:.24,dex:.24,agi:.24,cha:0,int:.04},decays:{hack:.6,str:.8,def:.8,dex:.8,agi:.8,cha:0,int:.75},isKill:!0}),J["Operation Ultron"]=new V({name:"Operation Ultron",desc:"OmniTek Incorporated, the original designer and manufacturer of Synthoids, has notified us of a malfunction in their AI design. This malfunction, when triggered, causes MK-VI Synthoids to become radicalized and seek out the destruction of humanity. They say that this bug affects all MK-VI Synthoids, not just the rogue ones from the Uprising.

    OmniTek has also told us they they believe someone has triggered this malfunction in a large group of MK-VI Synthoids, and that these newly-radicalized Synthoids are now amassing in Volhaven to form a terrorist group called Ultron.

    Intelligence suggests Ultron is heavily armed and that their members are augmented. We believe Ultron is making moves to take control of and weaponize DeltaOne's Tactical High-Energy Satellite Laser Array (THESLA).

    Your task is to find and destroy Ultron.",baseDifficulty:6e4,reqdRank:25e4,rankGain:1e4,rankLoss:2e3,hpLoss:1e4,weights:{hack:.1,str:.2,def:.2,dex:.2,agi:.2,cha:0,int:.1},decays:{hack:.6,str:.8,def:.8,dex:.8,agi:.8,cha:0,int:.75},isKill:!0}),J["Operation Centurion"]=new V({name:"Operation Centurion",desc:"D)@#)($M)C0293c40($*)@#D0JUMP3Rm0C<*@#)*$)#02c94830c(#$*D)

    Throughout all of humanity's history, we have relied on technology to survive, conquer, and progress. Its advancement became our primary goal. And at the peak of human civilization technology turned into power. Global, absolute power.

    It seems that the universe is not without a sense of irony.

    D)@#)($M)C0293c40($*)@#D0JUMP3Rm0C<*@#)*$)#02c94830c(#$*D)",baseDifficulty:7e4,reqdRank:3e5,rankGain:15e3,rankLoss:5e3,hpLoss:1e4,weights:{hack:.1,str:.2,def:.2,dex:.2,agi:.2,cha:0,int:.1},decays:{hack:.6,str:.8,def:.8,dex:.8,agi:.8,cha:0,int:.75}}),J["Operation Vindictus"]=new V({name:"Operation Vindictus",desc:"D)@#)($M)C0293c40($*)@#D0JUMP3Rm0C<*@#)*$)#02c94830c(#$*D)

    The bits are all around us. The daemons that hold the Node together can manifest themselves in many different ways.

    D)@#)($M)C0293c40($*)@#D0JUMP3Rm0C<*@#)*$)#02c94830c(#$*D)",baseDifficulty:75e3,reqdRank:35e4,rankGain:2e4,rankLoss:2e4,hpLoss:2e4,weights:{hack:.1,str:.2,def:.2,dex:.2,agi:.2,cha:0,int:.1},decays:{hack:.6,str:.8,def:.8,dex:.8,agi:.8,cha:0,int:.75}}),J["Operation Daedalus"]=new V({name:"Operation Daedalus",desc:"Yesterday we obeyed kings and bent our neck to emperors. Today we kneel only to truth.",baseDifficulty:8e4,reqdRank:4e5,rankGain:4e4,rankLoss:1e4,hpLoss:1e5,weights:{hack:.1,str:.2,def:.2,dex:.2,agi:.2,cha:0,int:.1},decays:{hack:.6,str:.8,def:.8,dex:.8,agi:.8,cha:0,int:.75}})}(),this.initializeDomElementRefs(),e.new&&this.create()}X.prototype.prestige=function(){this.resetAction();var e=c.Factions.Bladeburners;this.rank>=25&&Object(u.joinFaction)(e)},X.prototype.create=function(){this.contracts.Tracking=new Y({name:"Tracking",desc:"Identify and locate Synthoids. This contract involves reconnaissance and information-gathering ONLY. Do NOT engage. Stealth is of the utmost importance.

    Successfully completing Tracking contracts will slightly improve your Synthoid population estimate for whatever city you are currently in.",baseDifficulty:125,difficultyFac:1.02,rewardFac:1.041,rankGain:.3,hpLoss:.5,count:Object(C.getRandomInt)(25,150),countGrowth:Object(C.getRandomInt)(5,75)/10,weights:{hack:0,str:.05,def:.05,dex:.35,agi:.35,cha:.1,int:.05},decays:{hack:0,str:.91,def:.91,dex:.91,agi:.91,cha:.9,int:1},isStealth:!0}),this.contracts["Bounty Hunter"]=new Y({name:"Bounty Hunter",desc:"Hunt down and capture fugitive Synthoids. These Synthoids are wanted alive.

    Successfully completing a Bounty Hunter contract will lower the population in your current city, and will also increase its chaos level.",baseDifficulty:250,difficultyFac:1.04,rewardFac:1.085,rankGain:.9,hpLoss:1,count:Object(C.getRandomInt)(5,150),countGrowth:Object(C.getRandomInt)(5,75)/10,weights:{hack:0,str:.15,def:.15,dex:.25,agi:.25,cha:.1,int:.1},decays:{hack:0,str:.91,def:.91,dex:.91,agi:.91,cha:.8,int:.9},isKill:!0}),this.contracts.Retirement=new Y({name:"Retirement",desc:"Hunt down and retire (kill) rogue Synthoids.

    Successfully completing a Retirement contract will lower the population in your current city, and will also increase its chaos level.",baseDifficulty:200,difficultyFac:1.03,rewardFac:1.065,rankGain:.6,hpLoss:1,count:Object(C.getRandomInt)(5,150),countGrowth:Object(C.getRandomInt)(5,75)/10,weights:{hack:0,str:.2,def:.2,dex:.2,agi:.2,cha:.1,int:.1},decays:{hack:0,str:.91,def:.91,dex:.91,agi:.91,cha:.8,int:.9},isKill:!0}),this.operations.Investigation=new z({name:"Investigation",desc:"As a field agent, investigate and identify Synthoid populations, movements, and operations.

    Successful Investigation ops will increase the accuracy of your synthoid data.

    You will NOT lose HP from failed Investigation ops.",baseDifficulty:400,difficultyFac:1.03,rewardFac:1.07,reqdRank:25,rankGain:2.2,rankLoss:.2,count:Object(C.getRandomInt)(1,100),countGrowth:Object(C.getRandomInt)(10,40)/10,weights:{hack:.25,str:.05,def:.05,dex:.2,agi:.1,cha:.25,int:.1},decays:{hack:.85,str:.9,def:.9,dex:.9,agi:.9,cha:.7,int:.9},isStealth:!0}),this.operations["Undercover Operation"]=new z({name:"Undercover Operation",desc:"Conduct undercover operations to identify hidden and underground Synthoid communities and organizations.

    Successful Undercover ops will increase the accuracy of your synthoid data.",baseDifficulty:500,difficultyFac:1.04,rewardFac:1.09,reqdRank:100,rankGain:4.4,rankLoss:.4,hpLoss:2,count:Object(C.getRandomInt)(1,100),countGrowth:Object(C.getRandomInt)(10,40)/10,weights:{hack:.2,str:.05,def:.05,dex:.2,agi:.2,cha:.2,int:.1},decays:{hack:.8,str:.9,def:.9,dex:.9,agi:.9,cha:.7,int:.9},isStealth:!0}),this.operations["Sting Operation"]=new z({name:"Sting Operation",desc:"Conduct a sting operation to bait and capture particularly notorious Synthoid criminals.",baseDifficulty:650,difficultyFac:1.04,rewardFac:1.095,reqdRank:500,rankGain:5.5,rankLoss:.5,hpLoss:2.5,count:Object(C.getRandomInt)(1,150),countGrowth:Object(C.getRandomInt)(3,40)/10,weights:{hack:.25,str:.05,def:.05,dex:.25,agi:.1,cha:.2,int:.1},decays:{hack:.8,str:.85,def:.85,dex:.85,agi:.85,cha:.7,int:.9},isStealth:!0}),this.operations.Raid=new z({name:"Raid",desc:"Lead an assault on a known Synthoid community. Note that there must be an existing Synthoid community in your current city in order for this Operation to be successful",baseDifficulty:800,difficultyFac:1.045,rewardFac:1.1,reqdRank:3e3,rankGain:55,rankLoss:2.5,hpLoss:50,count:Object(C.getRandomInt)(1,150),countGrowth:Object(C.getRandomInt)(2,40)/10,weights:{hack:.1,str:.2,def:.2,dex:.2,agi:.2,cha:0,int:.1},decays:{hack:.7,str:.8,def:.8,dex:.8,agi:.8,cha:0,int:.9},isKill:!0}),this.operations["Stealth Retirement Operation"]=new z({name:"Stealth Retirement Operation",desc:"Lead a covert operation to retire Synthoids. The objective is to complete the task without drawing any attention. Stealth and discretion are key.",baseDifficulty:1e3,difficultyFac:1.05,rewardFac:1.11,reqdRank:2e4,rankGain:22,rankLoss:2,hpLoss:10,count:Object(C.getRandomInt)(1,150),countGrowth:Object(C.getRandomInt)(1,20)/10,weights:{hack:.1,str:.1,def:.1,dex:.3,agi:.3,cha:0,int:.1},decays:{hack:.7,str:.8,def:.8,dex:.8,agi:.8,cha:0,int:.9},isStealth:!0,isKill:!0}),this.operations.Assassination=new z({name:"Assassination",desc:"Assassinate Synthoids that have been identified as important, high-profile social and political leaders in the Synthoid communities.",baseDifficulty:1500,difficultyFac:1.06,rewardFac:1.14,reqdRank:5e4,rankGain:44,rankLoss:4,hpLoss:5,count:Object(C.getRandomInt)(1,150),countGrowth:Object(C.getRandomInt)(1,20)/10,weights:{hack:.1,str:.1,def:.1,dex:.3,agi:.3,cha:0,int:.1},decays:{hack:.6,str:.8,def:.8,dex:.8,agi:.8,cha:0,int:.8},isStealth:!0,isKill:!0})},X.prototype.storeCycles=function(e=1){this.storedCycles+=e},X.prototype.process=function(){if(!1===p.b&&this.blackops.hasOwnProperty("Operation Daedalus"))return Object(p.a)(m.Player.bitNodeN);if(!1===r.Augmentations[a.AugmentationNames.BladesSimulacrum].owned&&m.Player.isWorking){if(this.action.type!==q.Idle){let e="Your Bladeburner action was cancelled because you started doing something else.";this.automateEnabled&&(e+="

    Your automation was disabled as well. You will have to re-enable it through the Bladeburner console",this.automateEnabled=!1),Object(g.dialogBoxCreate)(e)}this.resetAction()}if(this.stamina<=0&&(this.log("Your Bladeburner action was cancelled because your stamina hit 0"),this.resetAction()),this.storedCycles>=5){var e=Math.floor(this.storedCycles/5);for(var t in e=Math.min(e,5),this.storedCycles-=5*e,this.calculateMaxStamina(),this.stamina+=this.calculateStaminaGainPerSecond()*e,this.stamina=Math.min(this.maxStamina,this.stamina),this.contracts)if(this.contracts.hasOwnProperty(t)){var n=this.contracts[t];n.count+=e*n.countGrowth/480}for(var i in this.operations)if(this.operations.hasOwnProperty(i)){var o=this.operations[i];o.count+=e*o.countGrowth/480}for(var s=0;s=this.automateThreshHigh&&(this.action.name===this.automateActionHigh.name&&this.action.type===this.automateActionHigh.type||(this.action=new $({type:this.automateActionHigh.type,name:this.automateActionHigh.name}),this.startAction(this.action)))),h.routing.isOn(h.Page.Bladeburner)&&this.updateContent()}},X.prototype.calculateMaxStamina=function(){const e=m.Player.agility*this.skillMultipliers.effAgi;let t=(Math.pow(e,.8)+this.staminaBonus)*this.skillMultipliers.stamina*m.Player.bladeburner_max_stamina_mult;if(this.maxStamina!==t){const e=this.maxStamina;this.maxStamina=t,this.stamina=this.maxStamina*this.stamina/e}if(isNaN(t))throw new Error("Max Stamina calculated to be NaN in Bladeburner.calculateMaxStamina()")},X.prototype.calculateStaminaGainPerSecond=function(){var e=m.Player.agility*this.skillMultipliers.effAgi;return(.0085+this.maxStamina/7e4)*Math.pow(e,.17)*(this.skillMultipliers.stamina*m.Player.bladeburner_stamina_gain_mult)},X.prototype.calculateStaminaPenalty=function(){return Math.min(1,this.stamina/(.5*this.maxStamina))},X.prototype.changeRank=function(e){if(isNaN(e))throw new Error("NaN passed into Bladeburner.changeRank()");this.rank+=e,this.rank<0&&(this.rank=0),this.maxRank=Math.max(this.rank,this.maxRank);if(Object(c.factionExists)("Bladeburners")){var t=c.Factions.Bladeburners;if(!(t instanceof l.Faction))throw new Error("Could not properly get Bladeburner Faction object in Bladeburner UI Overview Faction button");if(t.isMember){var n=1+t.favor/100;t.playerReputation+=2*e*m.Player.faction_rep_mult*n}}var r=3*(this.totalSkillPoints+1);if(this.maxRank>=r){var a=Math.floor((this.maxRank-r)/3+1);this.skillPoints+=a,this.totalSkillPoints+=a}},X.prototype.getCurrentCity=function(){var e=this.cities[this.city];if(!(e instanceof j))throw new Error("Bladeburner.getCurrentCity() did not properly return a City object");return e},X.prototype.resetSkillMultipliers=function(){this.skillMultipliers={successChanceAll:1,successChanceStealth:1,successChanceKill:1,successChanceContract:1,successChanceOperation:1,successChanceEstimate:1,actionTime:1,effHack:1,effStr:1,effDef:1,effDex:1,effAgi:1,effCha:1,effInt:1,stamina:1,money:1,expGain:1,weaponAbility:1,gunAbility:1}},X.prototype.updateSkillMultipliers=function(){for(var e in this.resetSkillMultipliers(),this.skills)if(this.skills.hasOwnProperty(e)){var t=U[e];if(null==t)throw new Error("Could not find Skill Object for: "+e);var n=this.skills[e];if(null==n||n<=0)continue;for(var r=Object.keys(this.skillMultipliers),a=0;a=this.actionTimeToComplete?this.completeAction():void 0}},X.prototype.completeAction=function(){switch(this.action.type){case q.Contract:case q.Operation:try{var e=this.action.type===q.Operation;if(null==(g=this.getActionObject(this.action)))throw new Error("Failed to get Contract/Operation Object for: "+this.action.name);var t=g.getDifficulty(),n=Math.pow(t,.28)+t/650,r=Math.pow(g.rewardFac,g.level-1);if(this.stamina-=.285*n,this.stamina<0&&(this.stamina=0),g.attempt(this)){this.gainActionStats(g,!0),++g.successes,--g.count;var a=0;if(e||(a=25e4*r*this.skillMultipliers.money,m.Player.gainMoney(a),m.Player.recordMoneySource(a,"bladeburner")),e?g.setMaxLevel(2.5):g.setMaxLevel(3),g.rankGain){var s=Object(b.addOffset)(g.rankGain*r*i.BitNodeMultipliers.BladeburnerRank,10);this.changeRank(s),e&&this.logging.ops?this.log(g.name+" successfully completed! Gained "+Object(f.formatNumber)(s,3)+" rank"):!e&&this.logging.contracts&&this.log(g.name+" contract successfully completed! Gained "+Object(f.formatNumber)(s,3)+" rank and "+d.numeralWrapper.format(a,"$0.000a"))}e?this.completeOperation(!0):this.completeContract(!0)}else{this.gainActionStats(g,!1),++g.failures;var l=0,c=0;g.rankLoss&&(l=Object(b.addOffset)(g.rankLoss*r,10),this.changeRank(-1*l)),g.hpLoss&&(c=g.hpLoss*n,c=Math.ceil(Object(b.addOffset)(c,10)),this.hpLost+=c,m.Player.takeDamage(c)&&(++this.numHosp,this.moneyLost+=o.CONSTANTS.HospitalCostPerHp*m.Player.max_hp));var u="";l>0&&(u+="Lost "+Object(f.formatNumber)(l,3)+" rank."),c>0&&(u+="Took "+Object(f.formatNumber)(c,0)+" damage."),e&&this.logging.ops?this.log(g.name+" failed! "+u):!e&&this.logging.contracts&&this.log(g.name+" contract failed! "+u),e?this.completeOperation(!1):this.completeContract(!1)}g.autoLevel&&(g.level=g.maxLevel),this.startAction(this.action)}catch(e){Object(k.exceptionAlert)(e)}break;case q.BlackOp:case q.BlackOperation:try{var g;if(null==(g=this.getActionObject(this.action))||!(g instanceof V))throw new Error("Failed to get BlackOperation Object for: "+this.action.name);t=g.getDifficulty(),n=Math.pow(t,.28)+t/650;this.stamina-=.285*n,this.stamina<0&&(this.stamina=0);var _,y=g.teamCount;if(g.attempt(this)){this.gainActionStats(g,!0),g.count=0,this.blackops[g.name]=!0;var E=0;if(g.rankGain&&(E=Object(b.addOffset)(g.rankGain*i.BitNodeMultipliers.BladeburnerRank,10),this.changeRank(E)),_=Math.ceil(y/2),"Operation Daedalus"===g.name)return this.resetAction(),Object(p.a)(m.Player.bitNodeN);h.routing.isOn(h.Page.Bladeburner)&&this.createActionAndSkillsContent(),this.logging.blackops&&this.log(g.name+" successful! Gained "+Object(f.formatNumber)(E,1)+" rank")}else{this.gainActionStats(g,!1);var v=0;c=0;g.rankLoss&&(v=Object(b.addOffset)(g.rankLoss,10),this.changeRank(-1*v)),g.hpLoss&&(c=g.hpLoss*n,c=Math.ceil(Object(b.addOffset)(c,10)),m.Player.takeDamage(c)&&(++this.numHosp,this.moneyLost+=o.CONSTANTS.HospitalCostPerHp*m.Player.max_hp)),_=Math.floor(y),this.logging.blackops&&this.log(g.name+" failed! Lost "+Object(f.formatNumber)(v,1)+" rank and took "+Object(f.formatNumber)(c,0)+" damage")}if(this.resetAction(),y>=1){var O=Object(C.getRandomInt)(1,_);this.teamSize-=O,this.teamLost+=O,this.logging.blackops&&this.log("You lost "+Object(f.formatNumber)(O,0)+" team members during "+g.name)}}catch(e){Object(k.exceptionAlert)(e)}break;case q.Training:this.stamina-=.1425;var P=30*m.Player.strength_exp_mult,S=30*m.Player.defense_exp_mult,T=30*m.Player.dexterity_exp_mult,M=30*m.Player.agility_exp_mult,x=.04*this.skillMultipliers.stamina;m.Player.gainStrengthExp(P),m.Player.gainDefenseExp(S),m.Player.gainDexterityExp(T),m.Player.gainAgilityExp(M),this.staminaBonus+=x,this.logging.general&&this.log("Training completed. Gained: "+Object(f.formatNumber)(P,1)+" str exp, "+Object(f.formatNumber)(S,1)+" def exp, "+Object(f.formatNumber)(T,1)+" dex exp, "+Object(f.formatNumber)(M,1)+" agi exp, "+Object(f.formatNumber)(x,3)+" max stamina"),this.startAction(this.action);break;case q.FieldAnalysis:case q["Field Analysis"]:var w=.04*Math.pow(m.Player.hacking_skill,.3)+.04*Math.pow(m.Player.intelligence,.9)+.02*Math.pow(m.Player.charisma,.3);if(w*=m.Player.bladeburner_analysis_mult,isNaN(w)||w<0)throw new Error("Field Analysis Effectiveness calculated to be NaN or negative");var A=20*m.Player.hacking_exp_mult,R=20*m.Player.charisma_exp_mult;m.Player.gainHackingExp(A),m.Player.gainIntelligenceExp(.001),m.Player.gainCharismaExp(R),this.changeRank(.1*i.BitNodeMultipliers.BladeburnerRank),this.getCurrentCity().improvePopulationEstimateByPercentage(w*this.skillMultipliers.successChanceEstimate),this.logging.general&&this.log("Field analysis completed. Gained 0.1 rank, "+Object(f.formatNumber)(A,1)+" hacking exp, and "+Object(f.formatNumber)(R,1)+" charisma exp"),this.startAction(this.action);break;case q.Recruitment:var N=this.getRecruitmentSuccessChance();if(Math.random()=1){n=e?Math.ceil(r/2):Math.floor(r);var a=Object(C.getRandomInt)(0,n);this.teamSize-=a,this.teamLost+=a,this.logging.ops&&a>0&&this.log("Lost "+Object(f.formatNumber)(a,0)+" team members during this "+t.name)}var i=this.getCurrentCity();switch(t.name){case"Investigation":e?(i.improvePopulationEstimateByPercentage(.4*this.skillMultipliers.successChanceEstimate),Math.random()<.02*this.skillMultipliers.successChanceEstimate&&i.improveCommunityEstimate(1)):this.triggerPotentialMigration(this.city,.1);break;case"Undercover Operation":e?(i.improvePopulationEstimateByPercentage(.8*this.skillMultipliers.successChanceEstimate),Math.random()<.02*this.skillMultipliers.successChanceEstimate&&i.improveCommunityEstimate(1)):this.triggerPotentialMigration(this.city,.15);break;case"Sting Operation":e&&i.changePopulationByPercentage(-.1,{changeEstEqually:!0,nonZero:!0}),i.changeChaosByCount(.1);break;case"Raid":if(e)i.changePopulationByPercentage(-1,{changeEstEqually:!0,nonZero:!0}),--i.comms,--i.commsEst;else{var o=Object(C.getRandomInt)(-10,-5)/10;i.changePopulationByPercentage(o,{nonZero:!0})}i.changeChaosByPercentage(Object(C.getRandomInt)(1,5));break;case"Stealth Retirement Operation":e&&i.changePopulationByPercentage(-.5,{changeEstEqually:!0,nonZero:!0}),i.changeChaosByPercentage(Object(C.getRandomInt)(-3,-1));break;case"Assassination":e&&i.changePopulationByCount(-1,{estChange:-1}),i.changeChaosByPercentage(Object(C.getRandomInt)(-5,5));break;default:throw new Error("Invalid Action name in completeOperation: "+this.action.name)}},X.prototype.getRecruitmentTime=function(){var e=m.Player.charisma*this.skillMultipliers.effCha,t=Math.pow(e,.81)+e/90;return Math.max(10,Math.round(300-t))},X.prototype.getRecruitmentSuccessChance=function(){return Math.pow(m.Player.charisma,.45)/(this.teamSize+1)},X.prototype.getDiplomacyEffectiveness=function(){return(100-(Math.pow(m.Player.charisma,.045)+m.Player.charisma/1e3))/100},X.prototype.gainActionStats=function(e,t){var n=e.getDifficulty(),r=Math.pow(n,.28)+n/650,a=this.actionTimeToComplete,i=t?1:.5,o=1*a*i*r,s=.001*a*i*r;const l=this.skillMultipliers.expGain;m.Player.gainHackingExp(o*e.weights.hack*m.Player.hacking_exp_mult*l),m.Player.gainStrengthExp(o*e.weights.str*m.Player.strength_exp_mult*l),m.Player.gainDefenseExp(o*e.weights.def*m.Player.defense_exp_mult*l),m.Player.gainDexterityExp(o*e.weights.dex*m.Player.dexterity_exp_mult*l),m.Player.gainAgilityExp(o*e.weights.agi*m.Player.agility_exp_mult*l),m.Player.gainCharismaExp(o*e.weights.cha*m.Player.charisma_exp_mult*l),m.Player.gainIntelligenceExp(s*e.weights.int*l)},X.prototype.randomEvent=function(){var e=Math.random(),t=D[Object(C.getRandomInt)(0,5)],n=this.cities[t];if(!(n instanceof j))throw new Error("sourceCity was not a City object in Bladeburner.randomEvent()");for(var r=D[Object(C.getRandomInt)(0,5)];r===t;)r=D[Object(C.getRandomInt)(0,5)];var a=this.cities[r];if(!(n instanceof j&&a instanceof j))throw new Error("sourceCity/destCity was not a City object in Bladeburner.randomEvent()");if(e<=.05){++n.comms;var i=Object(C.getRandomInt)(10,20)/100,o=Math.round(n.pop*i);n.pop+=o,this.logging.events&&this.log("Intelligence indicates that a new Synthoid community was formed in a city")}else if(e<=.1)if(n.comms<=0){++n.comms;i=Object(C.getRandomInt)(10,20)/100,o=Math.round(n.pop*i);n.pop+=o,this.logging.events&&this.log("Intelligence indicates that a new Synthoid community was formed in a city")}else{--n.comms,++a.comms;i=Object(C.getRandomInt)(10,20)/100,o=Math.round(n.pop*i);n.pop-=o,a.pop+=o,this.logging.events&&this.log("Intelligence indicates that a Synthoid community migrated from "+t+" to some other city")}else if(e<=.3){i=Object(C.getRandomInt)(8,24)/100,o=Math.round(n.pop*i);n.pop+=o,this.logging.events&&this.log("Intelligence indicates that the Synthoid population of "+t+" just changed significantly")}else if(e<=.5)this.triggerMigration(t),this.logging.events&&this.log("Intelligence indicates that a large number of Synthoids migrated from "+t+" to some other city");else if(e<=.7)n.chaos+=1,n.chaos*=1+Object(C.getRandomInt)(5,20)/100,this.logging.events&&this.log("Tensions between Synthoids and humans lead to riots in "+t+"! Chaos increased");else if(e<=.9){i=Object(C.getRandomInt)(8,20)/100,o=Math.round(n.pop*i);n.pop-=o,this.logging.events&&this.log("Intelligence indicates that the Synthoid population of "+t+" just changed significantly")}},X.prototype.triggerPotentialMigration=function(e,t){(null==t||isNaN(t))&&console.log("ERROR: Invalid 'chance' parameter passed into Bladeburner.triggerPotentialMigration()"),t>1&&(t/=100),Math.random()0&&(i*=Object(C.getRandomInt)(2,4),--r.comms,++n.comms);var o=Math.round(r.pop*i);r.pop-=o,n.pop+=o};let Q={};X.prototype.initializeDomElementRefs=function(){Q={bladeburnerDiv:null,overviewConsoleParentDiv:null,overviewDiv:null,actionAndSkillsDiv:null,currentTab:null,consoleDiv:null,consoleTable:null,consoleInputRow:null,consoleInputCell:null,consoleInputHeader:null,consoleInput:null,overviewRank:null,overviewStamina:null,overviewStaminaHelpTip:null,overviewGen1:null,overviewEstPop:null,overviewEstPopHelpTip:null,overviewEstComms:null,overviewChaos:null,overviewSkillPoints:null,overviewBonusTime:null,overviewAugSuccessMult:null,overviewAugMaxStaminaMult:null,overviewAugStaminaGainMult:null,overviewAugAnalysisMult:null,actionsAndSkillsDesc:null,actionsAndSkillsList:null,generalActions:{},contracts:{},operations:{},blackops:{},skills:{},skillPointsDisplay:null}},X.prototype.createContent=function(){Q.bladeburnerDiv=Object(M.createElement)("div",{id:"bladeburner-container",position:"fixed",class:"generic-menupage-container"}),Q.overviewConsoleParentDiv=Object(M.createElement)("div",{height:"60%",display:"block",position:"relative"}),Q.overviewDiv=Object(M.createElement)("div",{width:"30%",display:"inline-block",border:"1px solid white"}),Q.actionAndSkillsDiv=Object(M.createElement)("div",{height:"60%",width:"70%",display:"block",border:"1px solid white",margin:"6px",padding:"6px"}),Q.currentTab="general",this.createOverviewContent(),this.createActionAndSkillsContent(),Q.consoleDiv=Object(M.createElement)("div",{class:"bladeburner-console-div",clickListener:()=>(Q.consoleInput instanceof Element&&Q.consoleInput.focus(),!1)}),Q.consoleTable=Object(M.createElement)("table",{class:"bladeburner-console-table"}),Q.consoleInputRow=Object(M.createElement)("tr",{class:"bladeburner-console-input-row",id:"bladeubrner-console-input-row"}),Q.consoleInputCell=Object(M.createElement)("td",{class:"bladeburner-console-input-cell"}),Q.consoleInputHeader=Object(M.createElement)("pre",{innerText:"> "}),Q.consoleInput=Object(M.createElement)("input",{type:"text",class:"bladeburner-console-input",tabIndex:1,onfocus:()=>{Q.consoleInput.value=Q.consoleInput.value}}),Q.consoleInputCell.appendChild(Q.consoleInputHeader),Q.consoleInputCell.appendChild(Q.consoleInput),Q.consoleInputRow.appendChild(Q.consoleInputCell),Q.consoleTable.appendChild(Q.consoleInputRow),Q.consoleDiv.appendChild(Q.consoleTable),Q.overviewConsoleParentDiv.appendChild(Q.overviewDiv),Q.overviewConsoleParentDiv.appendChild(Q.consoleDiv),Q.bladeburnerDiv.appendChild(Q.overviewConsoleParentDiv),Q.bladeburnerDiv.appendChild(Q.actionAndSkillsDiv);const e=Object(M.createElement)("div");if(e.innerHTML=`${R}= This action requires stealth, ${N} = This action involves retirement`,Q.bladeburnerDiv.appendChild(e),document.getElementById("entire-game-container").appendChild(Q.bladeburnerDiv),0===this.consoleLogs.length)this.postToConsole("Bladeburner Console BETA"),this.postToConsole("Type 'help' to see console commands");else for(let e=0;e{Object(g.dialogBoxCreate)("Performing actions will use up your stamina.

    Your max stamina is determined primarily by your agility stat.

    Your stamina gain rate is determined by both your agility and your max stamina. Higher max stamina leads to a higher gain rate.

    Once your stamina falls below 50% of its max value, it begins to negatively affect the success rate of your contracts/operations. This penalty is shown in the overview panel. If the penalty is 15%, then this means your success rate would be multipled by 85% (100 - 15).

    Your max stamina and stamina gain rate can also be increased by training, or through skills and Augmentation upgrades.")}}),Q.overviewGen1=Object(M.createElement)("p",{display:"block"}),Q.overviewEstPop=Object(M.createElement)("p",{innerText:"Est. Synthoid Population: ",display:"inline-block",tooltip:"This is your Bladeburner division's estimate of how many Synthoids exist in your current city."}),Q.overviewEstPopHelpTip=Object(M.createElement)("div",{innerText:"?",class:"help-tip",clickListener:()=>{Object(g.dialogBoxCreate)("The success rate of your contracts/operations depends on the population of Synthoids in your current city. The success rate that is shown to you is only an estimate, and it is based on your Synthoid population estimate.

    Therefore, it is important that this Synthoid population estimate is accurate so that you have a better idea of your success rate for contracts/operations. Certain actions will increase the accuracy of your population estimate.

    The Synthoid populations of cities can change due to your actions or random events. If random events occur, they will be logged in the Bladeburner Console.")}}),Q.overviewEstComms=Object(M.createElement)("p",{innerText:"Est. Synthoid Communities: ",display:"inline-block",tooltip:"This is your Bladeburner divison's estimate of how many Synthoid communities exist in your current city."}),Q.overviewChaos=Object(M.createElement)("p",{innerText:"City Chaos: ",display:"inline-block",tooltip:"The city's chaos level due to tensions and conflicts between humans and Synthoids. Having too high of a chaos level can make contracts and operations harder."}),Q.overviewBonusTime=Object(M.createElement)("p",{innerText:"Bonus time: ",display:"inline-block",tooltip:"You gain bonus time while offline or when the game is inactive (e.g. when the tab is throttled by browser). Bonus time makes the Bladeburner mechanic progress faster, up to 5x the normal speed."}),Q.overviewSkillPoints=Object(M.createElement)("p",{display:"block"}),Q.overviewAugSuccessMult=Object(M.createElement)("p",{display:"block"}),Q.overviewAugMaxStaminaMult=Object(M.createElement)("p",{display:"block"}),Q.overviewAugStaminaGainMult=Object(M.createElement)("p",{display:"block"}),Q.overviewAugAnalysisMult=Object(M.createElement)("p",{display:"block"}),Q.overviewDiv.appendChild(Q.overviewRank),Object(T.appendLineBreaks)(Q.overviewDiv,1),Q.overviewDiv.appendChild(Q.overviewStamina),Q.overviewDiv.appendChild(Q.overviewStaminaHelpTip),Q.overviewDiv.appendChild(Q.overviewGen1),Q.overviewDiv.appendChild(Q.overviewEstPop),Q.overviewDiv.appendChild(Q.overviewEstPopHelpTip),Object(T.appendLineBreaks)(Q.overviewDiv,1),Q.overviewDiv.appendChild(Q.overviewEstComms),Object(T.appendLineBreaks)(Q.overviewDiv,1),Q.overviewDiv.appendChild(Q.overviewChaos),Object(T.appendLineBreaks)(Q.overviewDiv,2),Q.overviewDiv.appendChild(Q.overviewBonusTime),Q.overviewDiv.appendChild(Q.overviewSkillPoints),Object(T.appendLineBreaks)(Q.overviewDiv,1),Q.overviewDiv.appendChild(Q.overviewAugSuccessMult),Q.overviewDiv.appendChild(Q.overviewAugMaxStaminaMult),Q.overviewDiv.appendChild(Q.overviewAugStaminaGainMult),Q.overviewDiv.appendChild(Q.overviewAugAnalysisMult),Object(T.appendLineBreaks)(Q.overviewDiv,1),Q.overviewDiv.appendChild(Object(M.createElement)("a",{innerHTML:"Travel",class:"a-link-button",display:"inline-block",clickListener:()=>{var e="bladeburner-travel-popup-cancel-btn",t=[];t.push(Object(M.createElement)("a",{innerText:"Cancel",class:"a-link-button",clickListener:()=>(Object(A.removeElementById)(e),!1)})),t.push(Object(M.createElement)("p",{innerText:"Travel to a different city for your Bladeburner activities. This does not cost any money. The city you are in for your Bladeburner duties does not affect your location in the game otherwise"}));for(var n=0;n(n.city=D[r],Object(A.removeElementById)(e),n.updateOverviewContent(),!1)}))}(this,n);Object(x.createPopup)(e,t)}}));if(Object(c.factionExists)("Bladeburners")){var e=c.Factions.Bladeburners;if(!(e instanceof l.Faction))throw new Error("Could not properly get Bladeburner Faction object in Bladeburner UI Overview Faction button");Q.overviewDiv.appendChild(Object(M.createElement)("a",{innerText:"Faction",class:"a-link-button",display:"inline-block",tooltip:"Apply to the Bladeburner Faction, or go to the faction page if you are already a member",clickListener:()=>(e.isMember?(s.Engine.loadFactionContent(),Object(u.displayFactionContent)("Bladeburners")):this.rank>=25?(Object(u.joinFaction)(e),Object(g.dialogBoxCreate)("Congratulations! You were accepted into the Bladeburners faction"),Object(S.removeChildrenFromElement)(Q.overviewDiv),this.createOverviewContent()):Object(g.dialogBoxCreate)("You need a rank of 25 to join the Bladeburners Faction!"),!1)}))}Q.overviewDiv.appendChild(Object(M.createElement)("br")),Q.overviewDiv.appendChild(Object(M.createElement)("br")),this.updateOverviewContent()},X.prototype.createActionAndSkillsContent=function(){null==Q.currentTab&&(Q.currentTab="general"),Object(S.removeChildrenFromElement)(Q.actionAndSkillsDiv),Object(E.clearObject)(Q.generalActions),Object(E.clearObject)(Q.contracts),Object(E.clearObject)(Q.operations),Object(E.clearObject)(Q.blackops),Object(E.clearObject)(Q.skills);for(var e=Q.currentTab.toLowerCase(),t=["General","Contracts","Operations","BlackOps","Skills"],n=0;n(Q.currentTab=e[t].toLowerCase(),n.createActionAndSkillsContent(),!1)}))}(t,n,this,e);switch(Q.actionsAndSkillsDesc=Object(M.createElement)("p",{display:"block",margin:"4px",padding:"4px"}),Object(S.removeChildrenFromElement)(Q.actionsAndSkillsList),Q.actionsAndSkillsList=Object(M.createElement)("ul"),e){case"general":this.createGeneralActionsContent();break;case"contracts":this.createContractsContent();break;case"operations":this.createOperationsContent();break;case"blackops":this.createBlackOpsContent();break;case"skills":this.createSkillsContent();break;default:throw new Error("Invalid value for DomElems.currentTab in Bladeburner.createActionAndSkillsContent")}this.updateContent(),Q.actionAndSkillsDiv.appendChild(Q.actionsAndSkillsDesc),Q.actionAndSkillsDiv.appendChild(Q.actionsAndSkillsList)},X.prototype.createGeneralActionsContent=function(){if(null==Q.actionsAndSkillsList||null==Q.actionsAndSkillsDesc)throw new Error("Bladeburner.createGeneralActionsContent called with either DomElems.actionsAndSkillsList or DomElems.actionsAndSkillsDesc = null");for(var e in Q.actionsAndSkillsDesc.innerText="These are generic actions that will assist you in your Bladeburner duties. They will not affect your Bladeburner rank in any way.",K)K.hasOwnProperty(e)&&(Q.generalActions[e]=Object(M.createElement)("div",{class:"bladeburner-action",name:e}),Q.actionsAndSkillsList.appendChild(Q.generalActions[e]))},X.prototype.createContractsContent=function(){if(null==Q.actionsAndSkillsList||null==Q.actionsAndSkillsDesc)throw new Error("Bladeburner.createContractsContent called with either DomElems.actionsAndSkillsList or DomElems.actionsAndSkillsDesc = null");for(var e in Q.actionsAndSkillsDesc.innerHTML="Complete contracts in order to increase your Bladeburner rank and earn money. Failing a contract will cause you to lose HP, which can lead to hospitalization.

    You can unlock higher-level contracts by successfully completing them. Higher-level contracts are more difficult, but grant more rank, experience, and money.",this.contracts)this.contracts.hasOwnProperty(e)&&(Q.contracts[e]=Object(M.createElement)("div",{class:"bladeburner-action",name:e}),Q.actionsAndSkillsList.appendChild(Q.contracts[e]))},X.prototype.createOperationsContent=function(){if(null==Q.actionsAndSkillsList||null==Q.actionsAndSkillsDesc)throw new Error("Bladeburner.createOperationsContent called with either DomElems.actionsAndSkillsList or DomElems.actionsAndSkillsDesc = null");for(var e in Q.actionsAndSkillsDesc.innerHTML="Carry out operations for the Bladeburner division. Failing an operation will reduce your Bladeburner rank. It will also cause you to lose HP, which can lead to hospitalization. In general, operations are harder and more punishing than contracts, but are also more rewarding.

    Operations can affect the chaos level and Synthoid population of your current city. The exact effects vary between different Operations.

    For operations, you can use a team. You must first recruit team members. Having a larger team will improves your chances of success.

    You can unlock higher-level operations by successfully completing them. Higher-level operations are more difficult, but grant more rank and experience.",this.operations)this.operations.hasOwnProperty(e)&&(Q.operations[e]=Object(M.createElement)("div",{class:"bladeburner-action",name:e}),Q.actionsAndSkillsList.appendChild(Q.operations[e]))},X.prototype.createBlackOpsContent=function(){if(null==Q.actionsAndSkillsList||null==Q.actionsAndSkillsDesc)throw new Error("Bladeburner.createBlackOpsContent called with either DomElems.actionsAndSkillsList or DomElems.actionsAndSkillsDesc = null");Q.actionsAndSkillsDesc.innerHTML="Black Operations (Black Ops) are special, one-time covert operations. Each Black Op must be unlocked successively by completing the one before it.

    Your ultimate goal to climb through the ranks of Bladeburners is to complete all of the Black Ops.

    Like normal operations, you may use a team for Black Ops. Failing a black op will incur heavy HP and rank losses.";var e=[];for(var t in J)J.hasOwnProperty(t)&&e.push(J[t]);e.sort(function(e,t){return e.reqdRank-t.reqdRank});for(var n=e.length-1;n>=0;--n)null==this.blackops[[e[n].name]]&&0!==n&&null==this.blackops[[e[n-1].name]]||(Q.blackops[e[n].name]=Object(M.createElement)("div",{class:"bladeburner-action",name:e[n].name}),Q.actionsAndSkillsList.appendChild(Q.blackops[e[n].name]))},X.prototype.createSkillsContent=function(){if(null==Q.actionsAndSkillsList||null==Q.actionsAndSkillsDesc)throw new Error("Bladeburner.createSkillsContent called with either DomElems.actionsAndSkillsList or DomElems.actionsAndSkillsDesc = null");Q.actionsAndSkillsDesc.innerHTML="You will gain one skill point every 3 ranks.

    Note that when upgrading a skill, the benefit for that skill is additive. However, the effects of different skills with each other is multiplicative.

    ";for(var e=Object.keys(this.skillMultipliers),t=0;t";break;case"successChanceStealth":Q.actionsAndSkillsDesc.innerHTML+="Stealth Success Chance: x"+n+"
    ";break;case"successChanceKill":Q.actionsAndSkillsDesc.innerHTML+="Retirement Success Chance: x"+n+"
    ";break;case"successChanceContract":Q.actionsAndSkillsDesc.innerHTML+="Contract Success Chance: x"+n+"
    ";break;case"successChanceOperation":Q.actionsAndSkillsDesc.innerHTML+="Operation Success Chance: x"+n+"
    ";break;case"successChanceEstimate":Q.actionsAndSkillsDesc.innerHTML+="Synthoid Data Estimate: x"+n+"
    ";break;case"actionTime":Q.actionsAndSkillsDesc.innerHTML+="Action Time: x"+n+"
    ";break;case"effHack":Q.actionsAndSkillsDesc.innerHTML+="Hacking Skill: x"+n+"
    ";break;case"effStr":Q.actionsAndSkillsDesc.innerHTML+="Strength: x"+n+"
    ";break;case"effDef":Q.actionsAndSkillsDesc.innerHTML+="Defense: x"+n+"
    ";break;case"effDex":Q.actionsAndSkillsDesc.innerHTML+="Dexterity: x"+n+"
    ";break;case"effAgi":Q.actionsAndSkillsDesc.innerHTML+="Agility: x"+n+"
    ";break;case"effCha":Q.actionsAndSkillsDesc.innerHTML+="Charisma: x"+n+"
    ";break;case"effInt":Q.actionsAndSkillsDesc.innerHTML+="Intelligence: x"+n+"
    ";break;case"stamina":Q.actionsAndSkillsDesc.innerHTML+="Stamina: x"+n+"
    ";break;case"money":Q.actionsAndSkillsDesc.innerHTML+="Contract Money: x"+n+"
    ";break;case"expGain":Q.actionsAndSkillsDesc.innerHTML+="Exp Gain: x"+n+"
    ";break;case"weaponAbility":case"gunAbility":break;default:console.log("Warning: Unrecognized SkillMult Key: "+e[t])}}for(var r in Q.skillPointsDisplay=Object(M.createElement)("p",{innerHTML:"
    Skill Points: "+Object(f.formatNumber)(this.skillPoints,0)+""}),Q.actionAndSkillsDiv.appendChild(Q.skillPointsDisplay),U)U.hasOwnProperty(r)&&(Q.skills[r]=Object(M.createElement)("div",{class:"bladeburner-action",name:r}),Q.actionsAndSkillsList.appendChild(Q.skills[r]))},X.prototype.updateContent=function(){this.updateOverviewContent(),this.updateActionAndSkillsContent()},X.prototype.updateOverviewContent=function(){h.routing.isOn(h.Page.Bladeburner)&&(Q.overviewRank.childNodes[0].nodeValue="Rank: "+Object(f.formatNumber)(this.rank,2),Q.overviewStamina.innerText="Stamina: "+Object(f.formatNumber)(this.stamina,3)+" / "+Object(f.formatNumber)(this.maxStamina,3),Q.overviewGen1.innerHTML="Stamina Penalty: "+Object(f.formatNumber)(100*(1-this.calculateStaminaPenalty()),1)+"%

    Team Size: "+Object(f.formatNumber)(this.teamSize,0)+"
    Team Members Lost: "+Object(f.formatNumber)(this.teamLost,0)+"

    Num Times Hospitalized: "+this.numHosp+"
    Money Lost From Hospitalizations: "+d.numeralWrapper.format(this.moneyLost,"$0.000a")+"

    Current City: "+this.city+"
    ",Q.overviewEstPop.childNodes[0].nodeValue="Est. Synthoid Population: "+d.numeralWrapper.format(this.getCurrentCity().popEst,"0.000a"),Q.overviewEstComms.childNodes[0].nodeValue="Est. Synthoid Communities: "+Object(f.formatNumber)(this.getCurrentCity().comms,0),Q.overviewChaos.childNodes[0].nodeValue="City Chaos: "+Object(f.formatNumber)(this.getCurrentCity().chaos),Q.overviewSkillPoints.innerText="Skill Points: "+Object(f.formatNumber)(this.skillPoints,0),Q.overviewBonusTime.childNodes[0].nodeValue="Bonus time: "+Object(f.convertTimeMsToTimeElapsedString)(this.storedCycles/5*1e3),Q.overviewAugSuccessMult.innerText="Aug. Success Chance Mult: "+Object(f.formatNumber)(100*m.Player.bladeburner_success_chance_mult,1)+"%",Q.overviewAugMaxStaminaMult.innerText="Aug. Max Stamina Mult: "+Object(f.formatNumber)(100*m.Player.bladeburner_max_stamina_mult,1)+"%",Q.overviewAugStaminaGainMult.innerText="Aug. Stamina Gain Mult: "+Object(f.formatNumber)(100*m.Player.bladeburner_stamina_gain_mult,1)+"%",Q.overviewAugAnalysisMult.innerText="Aug. Field Analysis Mult: "+Object(f.formatNumber)(100*m.Player.bladeburner_analysis_mult,1)+"%")},X.prototype.updateActionAndSkillsContent=function(){switch(null==Q.currentTab&&(Q.currentTab="general"),Q.currentTab.toLowerCase()){case"general":for(var e=Object.keys(Q.generalActions),t=0;t";var d=Object.keys(Q.skills);for(t=0;t(this.action.type=q[t.name],this.action.name=t.name,this.startAction(this.action),this.updateActionAndSkillsContent(),!1)}));Object(T.appendLineBreaks)(e,2),e.appendChild(Object(M.createElement)("pre",{innerHTML:t.desc,display:"inline-block"}))},X.prototype.updateContractsUIElement=function(e,t){Object(S.removeChildrenFromElement)(e);var n=e.classList.contains(B),r=t.getSuccessChance(this,{est:!0});if(e.appendChild(Object(M.createElement)("h2",{innerText:n?t.name+" (IN PROGRESS - "+Object(f.formatNumber)(this.actionTimeCurrent,0)+" / "+Object(f.formatNumber)(this.actionTimeToComplete,0)+")":t.name,display:"inline-block"})),n){var a=this.actionTimeCurrent/this.actionTimeToComplete;e.appendChild(Object(M.createElement)("p",{display:"block",innerText:Object(v.createProgressBarText)({progress:a})}))}else e.appendChild(Object(M.createElement)("a",{innerText:"Start",class:"a-link-button",padding:"3px",margin:"3px",clickListener:()=>(this.action.type=q.Contract,this.action.name=t.name,this.startAction(this.action),this.updateActionAndSkillsContent(),!1)}));var i=t.level>=t.maxLevel;Object(T.appendLineBreaks)(e,2),e.appendChild(Object(M.createElement)("pre",{display:"inline-block",innerText:"Level: "+t.level+" / "+t.maxLevel,tooltip:t.getSuccessesNeededForNextLevel(3)+" successes needed for next level"})),e.appendChild(Object(M.createElement)("a",{class:i?"a-link-button-inactive":"a-link-button",innerHTML:"↑",padding:"2px",margin:"2px",tooltip:n?"WARNING: changing the level will restart the contract":"",display:"inline",clickListener:()=>(++t.level,n&&this.startAction(this.action),this.updateContractsUIElement(e,t),!1)})),e.appendChild(Object(M.createElement)("a",{class:t.level<=1?"a-link-button-inactive":"a-link-button",innerHTML:"↓",padding:"2px",margin:"2px",tooltip:n?"WARNING: changing the level will restart the contract":"",display:"inline",clickListener:()=>(--t.level,n&&this.startAction(this.action),this.updateContractsUIElement(e,t),!1)}));var o=t.getActionTime(this);Object(T.appendLineBreaks)(e,2),e.appendChild(Object(M.createElement)("pre",{display:"inline-block",innerHTML:t.desc+"\n\n"+`Estimated success chance: ${Object(f.formatNumber)(100*r,1)}% ${t.isStealth?R:""}${t.isKill?N:""}\n`+"Time Required (s): "+Object(f.formatNumber)(o,0)+"\nContracts remaining: "+Math.floor(t.count)+"\nSuccesses: "+t.successes+"\nFailures: "+t.failures})),e.appendChild(Object(M.createElement)("br"));var s="bladeburner-"+t.name+"-autolevel-checkbox";e.appendChild(Object(M.createElement)("label",{for:s,innerText:"Autolevel",color:"white",tooltip:"Automatically increase contract level when possible"}));const l=Object(M.createElement)("div",{class:"bbcheckbox"}),c=Object(M.createElement)("input",{type:"checkbox",id:s,checked:t.autoLevel,changeListener:()=>{t.autoLevel=c.checked}}),u=Object(M.createElement)("label",{for:s});l.appendChild(c),l.appendChild(u),e.appendChild(l)},X.prototype.updateOperationsUIElement=function(e,t){Object(S.removeChildrenFromElement)(e);var n=e.classList.contains(B),r=t.getSuccessChance(this,{est:!0});if(e.appendChild(Object(M.createElement)("h2",{innerText:n?t.name+" (IN PROGRESS - "+Object(f.formatNumber)(this.actionTimeCurrent,0)+" / "+Object(f.formatNumber)(this.actionTimeToComplete,0)+")":t.name,display:"inline-block"})),n){var a=this.actionTimeCurrent/this.actionTimeToComplete;e.appendChild(Object(M.createElement)("p",{display:"block",innerText:Object(v.createProgressBarText)({progress:a})}))}else e.appendChild(Object(M.createElement)("a",{innerText:"Start",class:"a-link-button",margin:"3px",padding:"3px",clickListener:()=>(this.action.type=q.Operation,this.action.name=t.name,this.startAction(this.action),this.updateActionAndSkillsContent(),!1)})),e.appendChild(Object(M.createElement)("a",{innerText:"Set Team Size (Curr Size: "+Object(f.formatNumber)(t.teamCount,0)+")",class:"a-link-button",margin:"3px",padding:"3px",clickListener:()=>{var n="bladeburner-operation-set-team-size-popup",r=Object(M.createElement)("p",{innerText:"Enter the amount of team members you would like to take on these operations. If you do not have the specified number of team members, then as many as possible will be used. Note that team members may be lost during operations."}),a=Object(M.createElement)("input",{type:"number",placeholder:"Team Members"}),i=Object(M.createElement)("a",{innerText:"Confirm",class:"a-link-button",clickListener:()=>{var r=Math.round(parseFloat(a.value));return isNaN(r)?Object(g.dialogBoxCreate)("Invalid value entered for number of Team Members (must be numeric)"):(t.teamCount=r,this.updateOperationsUIElement(e,t)),Object(A.removeElementById)(n),!1}}),o=Object(M.createElement)("a",{innerText:"Cancel",class:"a-link-button",clickListener:()=>(Object(A.removeElementById)(n),!1)});Object(x.createPopup)(n,[r,a,i,o])}}));var i=t.level>=t.maxLevel;Object(T.appendLineBreaks)(e,2),e.appendChild(Object(M.createElement)("pre",{display:"inline-block",innerText:"Level: "+t.level+" / "+t.maxLevel,tooltip:t.getSuccessesNeededForNextLevel(2.5)+" successes needed for next level"})),e.appendChild(Object(M.createElement)("a",{class:i?"a-link-button-inactive":"a-link-button",innerHTML:"↑",padding:"2px",margin:"2px",tooltip:n?"WARNING: changing the level will restart the Operation":"",display:"inline",clickListener:()=>(++t.level,n&&this.startAction(this.action),this.updateOperationsUIElement(e,t),!1)})),e.appendChild(Object(M.createElement)("a",{class:t.level<=1?"a-link-button-inactive":"a-link-button",innerHTML:"↓",padding:"2px",margin:"2px",tooltip:n?"WARNING: changing the level will restart the Operation":"",display:"inline",clickListener:()=>(--t.level,n&&this.startAction(this.action),this.updateOperationsUIElement(e,t),!1)}));t.getDifficulty();var o=t.getActionTime(this);Object(T.appendLineBreaks)(e,2),e.appendChild(Object(M.createElement)("pre",{display:"inline-block",innerHTML:t.desc+"\n\n"+`Estimated success chance: ${Object(f.formatNumber)(100*r,1)}% ${t.isStealth?R:""}${t.isKill?N:""}\n`+"Time Required(s): "+Object(f.formatNumber)(o,0)+"\nOperations remaining: "+Math.floor(t.count)+"\nSuccesses: "+t.successes+"\nFailures: "+t.failures})),e.appendChild(Object(M.createElement)("br"));var s="bladeburner-"+t.name+"-autolevel-checkbox";e.appendChild(Object(M.createElement)("label",{for:s,innerText:"Autolevel",color:"white",tooltip:"Automatically increase operation level when possible"}));const l=Object(M.createElement)("div",{class:"bbcheckbox"}),c=Object(M.createElement)("input",{type:"checkbox",id:s,checked:t.autoLevel,changeListener:()=>{t.autoLevel=c.checked}}),u=Object(M.createElement)("label",{for:s});l.appendChild(c),l.appendChild(u),e.appendChild(l)},X.prototype.updateBlackOpsUIElement=function(e,t){Object(S.removeChildrenFromElement)(e);var n=e.classList.contains(B),r=null!=this.blackops[t.name],a=t.getSuccessChance(this,{est:!0}),i=(t.getDifficulty(),t.getActionTime(this)),o=this.rank>=t.reqdRank;if(r)e.appendChild(Object(M.createElement)("h2",{innerText:t.name+" (COMPLETED)",display:"block"}));else{if(e.appendChild(Object(M.createElement)("h2",{innerText:n?t.name+" (IN PROGRESS - "+Object(f.formatNumber)(this.actionTimeCurrent,0)+" / "+Object(f.formatNumber)(this.actionTimeToComplete,0)+")":t.name,display:"inline-block"})),n){var s=this.actionTimeCurrent/this.actionTimeToComplete;e.appendChild(Object(M.createElement)("p",{display:"block",innerText:Object(v.createProgressBarText)({progress:s})}))}else e.appendChild(Object(M.createElement)("a",{innerText:"Start",margin:"3px",padding:"3px",class:o?"a-link-button":"a-link-button-inactive",clickListener:()=>(this.action.type=q.BlackOperation,this.action.name=t.name,this.startAction(this.action),this.updateActionAndSkillsContent(),!1)})),e.appendChild(Object(M.createElement)("a",{innerText:"Set Team Size (Curr Size: "+Object(f.formatNumber)(t.teamCount,0)+")",class:"a-link-button",margin:"3px",padding:"3px",clickListener:()=>{var n="bladeburner-operation-set-team-size-popup",r=Object(M.createElement)("p",{innerText:"Enter the amount of team members you would like to take on this BlackOp. If you do not have the specified number of team members, then as many as possible will be used. Note that team members may be lost during operations."}),a=Object(M.createElement)("input",{type:"number",placeholder:"Team Members"}),i=Object(M.createElement)("a",{innerText:"Confirm",class:"a-link-button",clickListener:()=>{var r=Math.round(parseFloat(a.value));return isNaN(r)?Object(g.dialogBoxCreate)("Invalid value entered for number of Team Members (must be numeric)"):(t.teamCount=r,this.updateBlackOpsUIElement(e,t)),Object(A.removeElementById)(n),!1}}),o=Object(M.createElement)("a",{innerText:"Cancel",class:"a-link-button",clickListener:()=>(Object(A.removeElementById)(n),!1)});Object(x.createPopup)(n,[r,a,i,o])}}));Object(T.appendLineBreaks)(e,2),e.appendChild(Object(M.createElement)("p",{display:"inline-block",innerHTML:"
    "+t.desc+"

    "})),e.appendChild(Object(M.createElement)("p",{display:"block",color:o?"white":"red",innerHTML:"Required Rank: "+Object(f.formatNumber)(t.reqdRank,0)+"
    "})),e.appendChild(Object(M.createElement)("p",{display:"inline-block",innerHTML:`Estimated Success Chance: ${Object(f.formatNumber)(100*a,1)}% ${t.isStealth?R:""}${t.isKill?N:""}\n`+"Time Required(s): "+Object(f.formatNumber)(i,0)}))}},X.prototype.updateSkillsUIElement=function(e,t){Object(S.removeChildrenFromElement)(e);var n=t.name,r=0;this.skills[n]&&!isNaN(this.skills[n])&&(r=this.skills[n]);var a=t.calculateCost(r);e.appendChild(Object(M.createElement)("h2",{innerText:t.name+" (Lvl "+r+")",display:"inline-block"}));var i=this.skillPoints>=a,o=!!t.maxLvl&&r>=t.maxLvl;e.appendChild(Object(M.createElement)("a",{innerText:"Level",display:"inline-block",class:i&&!o?"a-link-button":"a-link-button-inactive",margin:"3px",padding:"3px",clickListener:()=>{if(!(this.skillPoints100&&this.consoleLogs.shift()),null!=t&&null!=Q.consoleDiv&&(e("#bladeubrner-console-input-row").before(''+t+""),Q.consoleTable.childNodes.length>100&&Q.consoleTable.removeChild(Q.consoleTable.firstChild),this.updateConsoleScroll())},X.prototype.updateConsoleScroll=function(){Q.consoleDiv.scrollTop=Q.consoleDiv.scrollHeight},X.prototype.resetConsoleInput=function(){Q.consoleInput.value=""},X.prototype.clearConsole=function(){for(;Q.consoleTable.childNodes.length>1;)Q.consoleTable.removeChild(Q.consoleTable.firstChild);this.consoleLogs.length=0},X.prototype.log=function(e){this.postToConsole(`[${Object(O.getTimestamp)()}] ${e}`)},X.prototype.executeConsoleCommands=function(e){try{this.consoleHistory[this.consoleHistory.length-1]!=e&&(this.consoleHistory.push(e),this.consoleHistory.length>50&&this.consoleHistory.splice(0,1)),L=this.consoleHistory.length;for(var t=e.split(";"),n=0;n"))}},X.prototype.executeLogConsoleCommand=function(e){if(e.length<3)return this.postToConsole("Invalid usage of log command: log [enable/disable] [action/event]"),void this.postToConsole("Use 'help log' for more details and examples");var t=!0;switch(e[1].toLowerCase().includes("d")&&(t=!1),e[2].toLowerCase()){case"general":case"gen":this.logging.general=t,this.log("Logging "+(t?"enabled":"disabled")+" for general actions");break;case"contract":case"contracts":this.logging.contracts=t,this.log("Logging "+(t?"enabled":"disabled")+" for Contracts");break;case"ops":case"op":case"operations":case"operation":this.logging.ops=t,this.log("Logging "+(t?"enabled":"disabled")+" for Operations");break;case"blackops":case"blackop":case"black operations":case"black operation":this.logging.blackops=t,this.log("Logging "+(t?"enabled":"disabled")+" for BlackOps");break;case"event":case"events":this.logging.events=t,this.log("Logging "+(t?"enabled":"disabled")+" for events");break;case"all":this.logging.general=t,this.logging.contracts=t,this.logging.ops=t,this.logging.blackops=t,this.logging.events=t,this.log("Logging "+(t?"enabled":"disabled")+" for everything");break;default:this.postToConsole("Invalid action/event type specified: "+e[2]),this.postToConsole("Examples of valid action/event identifiers are: [general, contracts, ops, blackops, events]")}},X.prototype.executeSkillConsoleCommand=function(e){switch(e.length){case 1:this.postToConsole("Invalid usage of 'skill' console command: skill [action] [name]"),this.postToConsole("Use 'help skill' for more info");break;case 2:if("list"===e[1].toLowerCase()){this.postToConsole("Skills: ");for(var t=Object.keys(U),n=0;n=c?(this.skillPoints-=c,this.upgradeSkill(r),this.log(r.name+" upgraded to Level "+this.skills[s]),this.createActionAndSkillsContent()):this.postToConsole("You do not have enough Skill Points to upgrade this. You need "+Object(f.formatNumber)(c,0))}else this.postToConsole("Invalid usage of 'skill' console command: skill [action] [name]"),this.postToConsole("Use 'help skill' for more info");break;default:this.postToConsole("Invalid usage of 'skill' console command: skill [action] [name]"),this.postToConsole("Use 'help skill' for more info")}},X.prototype.executeStartConsoleCommand=function(e){if(3!==e.length)return this.postToConsole("Invalid usage of 'start' console command: start [type] [name]"),void this.postToConsole("Use 'help start' for more info");var t=e[2];switch(e[1].toLowerCase()){case"general":case"gen":null!=K[t]?(this.action.type=q[t],this.action.name=t,this.startAction(this.action),this.updateActionAndSkillsContent()):this.postToConsole("Invalid action name specified: "+e[2]);break;case"contract":case"contracts":null!=this.contracts[t]?(this.action.type=q.Contract,this.action.name=t,this.startAction(this.action),this.updateActionAndSkillsContent()):this.postToConsole("Invalid contract name specified: "+e[2]);break;case"ops":case"op":case"operations":case"operation":null!=this.operations[t]?(this.action.type=q.Operation,this.action.name=t,this.startAction(this.action),this.updateActionAndSkillsContent()):this.postToConsole("Invalid Operation name specified: "+e[2]);break;case"blackops":case"blackop":case"black operations":case"black operation":null!=J[t]?(this.action.type=q.BlackOperation,this.action.name=t,this.startAction(this.action),this.updateActionAndSkillsContent()):this.postToConsole("Invalid BlackOp name specified: "+e[2]);break;default:this.postToConsole("Invalid action/event type specified: "+e[1]),this.postToConsole("Examples of valid action/event identifiers are: [general, contract, op, blackop]")}},X.prototype.getActionIdFromTypeAndName=function(e="",t=""){if(""===e||""===t)return null;var n=new $,r=e.toLowerCase().trim(),a=t.toLowerCase().trim();switch(r){case"contract":case"contracts":case"contr":return n.type=q.Contract,this.contracts.hasOwnProperty(t)?(n.name=t,n):null;case"operation":case"operations":case"op":case"ops":return n.type=q.Operation,this.operations.hasOwnProperty(t)?(n.name=t,n):null;case"blackoperation":case"black operation":case"black operations":case"black op":case"black ops":case"blackop":case"blackops":return n.type=q.BlackOp,J.hasOwnProperty(t)?(n.name=t,n):null;case"general":case"general action":case"gen":break;default:return null}if(r.startsWith("gen")){switch(a){case"training":n.type=q.Training,n.name="Training";break;case"recruitment":case"recruit":n.type=q.Recruitment,n.name="Recruitment";break;case"field analysis":case"fieldanalysis":n.type=q["Field Analysis"],n.name="Field Analysis";break;case"diplomacy":n.type=q.Diplomacy,n.name="Diplomacy";break;case"hyperbolic regeneration chamber":n.type=q["Hyperbolic Regeneration Chamber"],n.name="Hyperbolic Regeneration Chamber";break;default:return null}return n}},X.prototype.getTypeAndNameFromActionId=function(e){var t={};let n=Object.keys(q);for(let r=0;rthis.rank)return n.log(`Failed to start Black Op ${a.name} due to insufficient rank`),!1;if(null!=this.blackops[a.name])return n.log(`Failed to start Black Op ${a.name} because its already been completed`),!1;var i=[];for(const e in J)J.hasOwnProperty(e)&&i.push(e);i.sort(function(e,t){return J[e].reqdRank-J[t].reqdRank});let e=i.indexOf(a.name);if(-1===e)return n.log("ERROR: Invalid Black Operation name passed into bladeburner.startAction(). Note that this name is case-sensitive & whitespace-sensitive"),!1;if(e>0&&null==this.blackops[i[e-1]])return n.log(`ERROR: Cannot attempt Black Operation ${a.name} because you have not done the preceding one`),!1}try{return this.startAction(a),n.shouldLog("startAction")&&n.log("Starting bladeburner action with type "+e+" and name "+t),!0}catch(r){return this.resetAction(),n.log("ERROR: bladeburner.startAction() failed to start action of type "+e+" due to invalid name: "+t+"Note that this name is case-sensitive and whitespace-sensitive"),!1}},X.prototype.getActionTimeNetscriptFn=function(e,t,n){var r="ERROR: bladeburner.getActionTime() failed due to an invalid action specified. Type: "+e+", Name: "+t+". Note that for contracts and operations, the name of the operation is case-sensitive.",a=this.getActionIdFromTypeAndName(e,t);if(null==a)return n.log(r),-1;var i=this.getActionObject(a);if(null==i)return n.log(r),-1;switch(a.type){case q.Contract:case q.Operation:case q.BlackOp:case q.BlackOperation:return i.getActionTime(this);case q.Training:case q["Field Analysis"]:case q.FieldAnalysis:return 30;case q.Recruitment:return this.getRecruitmentTime();default:return n.log(r),-1}},X.prototype.getActionEstimatedSuccessChanceNetscriptFn=function(e,t,n){var r="ERROR: bladeburner.getActionEstimatedSuccessChance() failed due to an invalid action specified. Type: "+e+", Name: "+t+". Note that for contracts and operations, the name of the operation is case-sensitive.",a=this.getActionIdFromTypeAndName(e,t);if(null==a)return n.log(r),-1;var i=this.getActionObject(a);if(null==i)return n.log(r),-1;switch(a.type){case q.Contract:case q.Operation:case q.BlackOp:case q.BlackOperation:return i.getSuccessChance(this,{est:!0});case q.Training:case q["Field Analysis"]:case q.FieldAnalysis:return 1;case q.Recruitment:return this.getRecruitmentSuccessChance();default:return n.log(r),-1}},X.prototype.getActionCountRemainingNetscriptFn=function(e,t,n){var r="ERROR: bladeburner.getActionCountRemaining() failed due to an invalid action specified. Type: "+e+", Name: "+t+". Note that for contracts and operations, the name of the operation is case-sensitive.",a=this.getActionIdFromTypeAndName(e,t);if(null==a)return n.log(r),-1;var i=this.getActionObject(a);if(null==i)return n.log(r),-1;switch(a.type){case q.Contract:case q.Operation:return Math.floor(i.count);case q.BlackOp:case q.BlackOperation:return null!=this.blackops[t]?0:1;case q.Training:case q["Field Analysis"]:case q.FieldAnalysis:return 1/0;default:return n.log(r),-1}},X.prototype.getSkillLevelNetscriptFn=function(e,t){var n="ERROR: bladeburner.getSkillLevel() failed due to an invalid skill specified: "+e+". Note that the name of the skill is case-sensitive";return""===e?-1:U.hasOwnProperty(e)?null==this.skills[e]?0:this.skills[e]:(t.log(n),-1)},X.prototype.getSkillUpgradeCostNetscriptFn=function(e,t){var n="ERROR: bladeburner.getSkillUpgradeCostNetscriptFn() failed due to an invalid skill specified: "+e+". Note that the name of the skill is case-sensitive";if(""===e)return-1;if(!U.hasOwnProperty(e))return t.log(n),-1;var r=U[e];return null==this.skills[e]?r.calculateCost(0):r.calculateCost(this.skills[e])},X.prototype.upgradeSkillNetscriptFn=function(e,t){var n="ERROR: bladeburner.upgradeSkill() failed due to an invalid skill specified: "+e+". Note that the name of the skill is case-sensitive";if(!U.hasOwnProperty(e))return t.log(n),!1;var r=U[e],a=0;this.skills[e]&&!isNaN(this.skills[e])&&(a=this.skills[e]);var i=r.calculateCost(a);return r.maxLvl&&a>=r.maxLvl?(t.shouldLog("upgradeSkill")&&t.log(`bladeburner.upgradeSkill() failed because ${e} is already maxed`),!1):this.skillPoints=25?(Object(u.joinFaction)(t),e.shouldLog("joinBladeburnerFaction")&&e.log("Joined Bladeburners Faction"),h.routing.isOn(h.Page.Bladeburner)&&(Object(S.removeChildrenFromElement)(Q.overviewDiv),this.createOverviewContent()),!0):(e.shouldLog("joinBladeburnerFaction")&&e.log("Failed to join Bladeburners Faction because you do not have the required 25 rank"),!1))},X.prototype.toJSON=function(){return Object(_.Generic_toJSON)("Bladeburner",this)},X.fromJSON=function(e){return Object(_.Generic_fromJSON)(X,e.data)},_.Reviver.constructors.Bladeburner=X}).call(this,n(85))},function(e,t,n){"use strict";n.d(t,"d",function(){return h}),n.d(t,"c",function(){return g}),n.d(t,"b",function(){return y}),n.d(t,"a",function(){return d});var r=n(14),a=n(0),i=n(19),o=n(32),s=n(50),l=n(30),c=n(3),u=n(37),m=n(28);const p=["Start","GoToCharacterPage","CharacterPage","CharacterGoToTerminalPage","TerminalIntro","TerminalHelp","TerminalLs","TerminalScan","TerminalScanAnalyze1","TerminalScanAnalyze2","TerminalConnect","TerminalAnalyze","TerminalNuke","TerminalManualHack","TerminalHackingMechanics","TerminalCreateScript","TerminalTypeScript","TerminalFree","TerminalRunScript","TerminalGoToActiveScriptsPage","ActiveScriptsPage","ActiveScriptsToTerminal","TerminalTailScript","GoToHacknetNodesPage","HacknetNodesIntroduction","HacknetNodesGoToWorldPage","WorldDescription","TutorialPageInfo","End"],h={};for(let e=0;eh.Start&&(d.currStep-=1);_()}(),!1}),Object(l.clearEventListeners)("interactive-tutorial-next").addEventListener("click",function(){return y(),!1}),_()}function _(){if(d.isRunning){var e=Object(l.clearEventListeners)("terminal-menu-link"),t=Object(l.clearEventListeners)("stats-menu-link"),n=Object(l.clearEventListeners)("active-scripts-menu-link"),a=Object(l.clearEventListeners)("hacknet-nodes-menu-link"),i=Object(l.clearEventListeners)("city-menu-link"),o=Object(l.clearEventListeners)("tutorial-menu-link");e.removeAttribute("class"),t.removeAttribute("class"),n.removeAttribute("class"),a.removeAttribute("class"),i.removeAttribute("class"),o.removeAttribute("class");var s=document.getElementById("interactive-tutorial-next");switch(d.currStep){case h.Start:r.Engine.loadTerminalContent(),b("Welcome to Bitburner, a cyberpunk-themed incremental RPG! The game takes place in a dark, dystopian future...The year is 2077...

    This tutorial will show you the basics of the game. You may skip the tutorial at any time."),s.style.display="inline-block";break;case h.GoToCharacterPage:r.Engine.loadTerminalContent(),b("Let's start by heading to the Stats page. Click the 'Stats' tab on the main navigation menu (left-hand side of the screen)"),s.style.display="none",t.setAttribute("class","flashing-button"),t.addEventListener("click",function(){return r.Engine.loadCharacterContent(),y(),!1});break;case h.CharacterPage:r.Engine.loadCharacterContent(),b("The Stats page shows a lot of important information about your progress, such as your skills, money, and bonuses/multipliers. "),s.style.display="inline-block";break;case h.CharacterGoToTerminalPage:r.Engine.loadCharacterContent(),b("Let's head to your computer's terminal by clicking the 'Terminal' tab on the main navigation menu."),s.style.display="none",e.setAttribute("class","flashing-button"),e.addEventListener("click",function(){return r.Engine.loadTerminalContent(),y(),!1});break;case h.TerminalIntro:r.Engine.loadTerminalContent(),b("The Terminal is used to interface with your home computer as well as all of the other machines around the world."),s.style.display="inline-block";break;case h.TerminalHelp:r.Engine.loadTerminalContent(),b("Let's try it out. Start by entering the 'help' command into the Terminal (Don't forget to press Enter after typing the command)"),s.style.display="none";break;case h.TerminalLs:r.Engine.loadTerminalContent(),b("The 'help' command displays a list of all available Terminal commands, how to use them, and a description of what they do.

    Let's try another command. Enter the 'ls' command"),s.style.display="none";break;case h.TerminalScan:r.Engine.loadTerminalContent(),b("'ls' is a basic command that shows all of the contents (programs/scripts) on the computer. Right now, it shows that you have a program called 'NUKE.exe' on your computer. We'll get to what this does later.

    Using your home computer's terminal, you can connect to other machines throughout the world. Let's do that now by first entering the 'scan' command."),s.style.display="none";break;case h.TerminalScanAnalyze1:r.Engine.loadTerminalContent(),b("The 'scan' command shows all available network connections. In other words, it displays a list of all servers that can be connected to from your current machine. A server is identified by either its IP or its hostname.

    That's great and all, but there's so many servers. Which one should you go to? The 'scan-analyze' command gives some more detailed information about servers on the network. Try it now"),s.style.display="none";break;case h.TerminalScanAnalyze2:r.Engine.loadTerminalContent(),b("You just ran 'scan-analyze' with a depth of one. This command shows more detailed information about each server that you can connect to (servers that are a distance of one node away).

    It is also possible to run 'scan-analyze' with a higher depth. Let's try a depth of two with the following command: 'scan-analyze 2'."),s.style.display="none";break;case h.TerminalConnect:r.Engine.loadTerminalContent(),b("Now you can see information about all servers that are up to two nodes away, as well as figure out how to navigate to those servers through the network. You can only connect to a server that is one node away. To connect to a machine, use the 'connect [ip/hostname]' command. You can type in the ip or the hostname, but dont use both.

    From the results of the 'scan-analyze' command, we can see that the 'foodnstuff' server is only one node away. Let's connect so it now using: 'connect foodnstuff'"),s.style.display="none";break;case h.TerminalAnalyze:r.Engine.loadTerminalContent(),b("You are now connected to another machine! What can you do now? You can hack it!

    In the year 2077, currency has become digital and decentralized. People and corporations store their money on servers and computers. Using your hacking abilities, you can hack servers to steal money and gain experience.

    Before you try to hack a server, you should run diagnostics using the 'analyze' command"),s.style.display="none";break;case h.TerminalNuke:r.Engine.loadTerminalContent(),b("When the 'analyze' command finishes running it will show useful information about hacking the server.

    For this server, the required hacking skill is only 1, which means you can hack it right now. However, in order to hack a server you must first gain root access. The 'NUKE.exe' program that we saw earlier on your home computer is a virus that will grant you root access to a machine if there are enough open ports.

    The 'analyze' results shows that there do not need to be any open ports on this machine for the NUKE virus to work, so go ahead and run the virus using the 'run NUKE.exe' command."),s.style.display="none";break;case h.TerminalManualHack:r.Engine.loadTerminalContent(),b("You now have root access! You can hack the server using the 'hack' command. Try doing that now."),s.style.display="none";break;case h.TerminalHackingMechanics:r.Engine.loadTerminalContent(),b("You are now attempting to hack the server. Note that performing a hack takes time and only has a certain percentage chance of success. This time and success chance is determined by a variety of factors, including your hacking skill and the server's security level.

    If your attempt to hack the server is successful, you will steal a certain percentage of the server's total money. This percentage is affected by your hacking skill and the server's security level.

    The amount of money on a server is not limitless. So, if you constantly hack a server and deplete its money, then you will encounter diminishing returns in your hacking."),s.style.display="inline-block";break;case h.TerminalCreateScript:r.Engine.loadTerminalContent(),b("Hacking is the core mechanic of the game and is necessary for progressing. However, you don't want to be hacking manually the entire time. You can automate your hacking by writing scripts!

    To create a new script or edit an existing one, you can use the 'nano' command. Scripts must end with the '.script' extension. Let's make a script now by entering 'nano foodnstuff.script' after the hack command finishes running (Sidenote: Pressing ctrl + c will end a command like hack early)"),s.style.display="none";break;case h.TerminalTypeScript:r.Engine.loadScriptEditorContent("foodnstuff.script",""),b("This is the script editor. You can use it to program your scripts. Scripts are written in the Netscript language, a programming language created for this game. There are details about the Netscript language in the documentation, which can be accessed in the 'Tutorial' tab on the main navigation menu. I highly suggest you check it out after this tutorial. For now, just copy and paste the following code into the script editor:

    while(true) {
      hack('foodnstuff');
    }

    For anyone with basic programming experience, this code should be straightforward. This script will continuously hack the 'foodnstuff' server.

    To save and close the script editor, press the button in the bottom left, or press ctrl + b."),s.style.display="none";break;case h.TerminalFree:r.Engine.loadTerminalContent(),b("Now we'll run the script. Scripts require a certain amount of RAM to run, and can be run on any machine which you have root access to. Different servers have different amounts of RAM. You can also purchase more RAM for your home server.

    To check how much RAM is available on this machine, enter the 'free' command."),s.style.display="none";break;case h.TerminalRunScript:r.Engine.loadTerminalContent(),b("We have 16GB of free RAM on this machine, which is enough to run our script. Let's run our script using 'run foodnstuff.script'."),s.style.display="none";break;case h.TerminalGoToActiveScriptsPage:r.Engine.loadTerminalContent(),b("Your script is now running! The script might take a few seconds to 'fully start up'. Your scripts will continuously run in the background and will automatically stop if the code ever completes (the 'foodnstuff.script' will never complete because it runs an infinite loop).

    These scripts can passively earn you income and hacking experience. Your scripts will also earn money and experience while you are offline, although at a much slower rate.

    Let's check out some statistics for our running scripts by clicking the 'Active Scripts' link in the main navigation menu."),s.style.display="none",n.setAttribute("class","flashing-button"),n.addEventListener("click",function(){return r.Engine.loadActiveScriptsContent(),y(),!1});break;case h.ActiveScriptsPage:r.Engine.loadActiveScriptsContent(),b("This page displays stats/information about all of your scripts that are running across every existing server. You can use this to gauge how well your scripts are doing. Let's go back to the Terminal now using the 'Terminal' link."),s.style.display="none",e.setAttribute("class","flashing-button"),e.addEventListener("click",function(){return r.Engine.loadTerminalContent(),y(),!1});break;case h.ActiveScriptsToTerminal:r.Engine.loadTerminalContent(),b("One last thing about scripts, each active script contains logs that detail what it's doing. We can check these logs using the 'tail' command. Do that now for the script we just ran by typing 'tail foodnstuff.script'"),s.style.display="none";break;case h.TerminalTailScript:r.Engine.loadTerminalContent(),b("The log for this script won't show much right now (it might show nothing at all) because it just started running...but check back again in a few minutes!

    This pretty much covers the basics of hacking. To learn more about writing scripts using the Netscript language, select the 'Tutorial' link in the main navigation menu to look at the documentation. If you are an experienced JavaScript developer, I would highly suggest you check out the section on NetscriptJS/Netscript 2.0.

    For now, let's move on to something else!"),s.style.display="inline-block";break;case h.GoToHacknetNodesPage:r.Engine.loadTerminalContent(),b("Hacking is not the only way to earn money. One other way to passively earn money is by purchasing and upgrading Hacknet Nodes. Let's go to the 'Hacknet Nodes' page through the main navigation menu now."),s.style.display="none",a.setAttribute("class","flashing-button"),a.addEventListener("click",function(){return r.Engine.loadHacknetNodesContent(),y(),!1});break;case h.HacknetNodesIntroduction:r.Engine.loadHacknetNodesContent(),b("From this page you can purchase new Hacknet Nodes and upgrade your existing ones. Let's purchase a new one now."),s.style.display="none";break;case h.HacknetNodesGoToWorldPage:r.Engine.loadHacknetNodesContent(),b("You just purchased a Hacknet Node! This Hacknet Node will passively earn you money over time, both online and offline. When you get enough money, you can upgrade your newly-purchased Hacknet Node below.

    Let's go to the 'City' page through the main navigation menu."),s.style.display="none",i.setAttribute("class","flashing-button"),i.addEventListener("click",function(){return r.Engine.loadLocationContent(),y(),!1});break;case h.WorldDescription:r.Engine.loadLocationContent(),b("This page lists all of the different locations you can currently travel to. Each location has something that you can do. There's a lot of content out in the world, make sure you explore and discover!

    Lastly, click on the 'Tutorial' link in the main navigation menu."),s.style.display="none",o.setAttribute("class","flashing-button"),o.addEventListener("click",function(){return r.Engine.loadTutorialContent(),y(),!1});break;case h.TutorialPageInfo:r.Engine.loadTutorialContent(),b("This page contains a lot of different documentation about the game's content and mechanics. I know it's a lot, but I highly suggest you read (or at least skim) through this before you start playing. That's the end of the tutorial. Hope you enjoy the game!"),s.style.display="inline-block",s.innerHTML="Finish Tutorial";break;case h.End:f();break;default:throw new Error("Invalid tutorial step")}!0===d.stepIsDone[d.currStep]&&(s.style.display="inline-block")}else console.log("Interactive Tutorial not running")}function y(){d.currStep===h.GoToCharacterPage&&document.getElementById("stats-menu-link").removeAttribute("class"),d.currStep===h.CharacterGoToTerminalPage&&document.getElementById("terminal-menu-link").removeAttribute("class"),d.currStep===h.TerminalGoToActiveScriptsPage&&document.getElementById("active-scripts-menu-link").removeAttribute("class"),d.currStep===h.ActiveScriptsPage&&document.getElementById("terminal-menu-link").removeAttribute("class"),d.currStep===h.GoToHacknetNodesPage&&document.getElementById("hacknet-nodes-menu-link").removeAttribute("class"),d.currStep===h.HacknetNodesGoToWorldPage&&document.getElementById("city-menu-link").removeAttribute("class"),d.currStep===h.WorldDescription&&document.getElementById("tutorial-menu-link").removeAttribute("class"),d.stepIsDone[d.currStep]=!0,d.currStep
    Getting Started GuideDocumentation

    The Beginner's Guide to Hacking was added to your home computer! It contains some tips/pointers for starting out with the game. To read it, go to Terminal and enter

    cat hackers-starting-handbook.lit"}),n=Object(c.createElement)("a",{class:"a-link-button",float:"right",padding:"6px",innerText:"Got it!",clickListener:()=>{Object(m.removeElementById)(e)}});Object(u.createPopup)(e,[t,n]),a.Player.getHomeComputer().messages.push("hackers-starting-handbook.lit")}function b(e){var t=document.getElementById("interactive-tutorial-text");if(null==t)throw new Error("Could not find text box");t.innerHTML=e,t.parentElement.scrollTop=0}},,function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});const r=n(126),a=n(476),i=n(475),o=n(113),s=n(474),l=n(473),c=n(86),u=n(77),m=n(146),p=n(472),h=n(8),d=n(116),g=n(0),_=n(199),y=n(12),f=n(2),b=n(9),E=n(18),v=n(1),k=n(52);function C(e,n,r,s,l,c=null){const u=c instanceof d.WorkerScript;if(!(e instanceof o.Stock))return u?c.log("ERROR: Invalid stock passed to placeOrder() function"):b.dialogBoxCreate("ERROR: Invalid stock passed to placeOrder() function"),!1;if("number"!=typeof n||"number"!=typeof r)return u?c.log("ERROR: Invalid numeric value provided for either 'shares' or 'price' argument"):b.dialogBoxCreate("ERROR: Invalid numeric value provided for either 'shares' or 'price' argument"),!1;const m=new a.Order(e.symbol,n,r,s,l);if(null==t.StockMarket.Orders){const e={};for(const n in t.StockMarket){const r=t.StockMarket[n];r instanceof o.Stock&&(e[r.symbol]=[])}t.StockMarket.Orders=e}t.StockMarket.Orders[e.symbol].push(m);const p={rerenderFn:R,stockMarket:t.StockMarket,symbolToStockMap:t.SymbolToStockMap};return i.processOrders(e,m.type,m.pos,p),R(),!0}function O(e,n=null){var r=n instanceof d.WorkerScript;if(null==t.StockMarket.Orders)return!1;if(e.order&&e.order instanceof a.Order){const n=e.order;for(var i=t.StockMarket.Orders[n.stockSymbol],s=0;s=n.cap&&(s=.1,n.b=!1),isNaN(s)&&(s=.5);const l=Math.random(),m={rerenderFn:R,stockMarket:t.StockMarket,symbolToStockMap:t.SymbolToStockMap};l{!function(e){null!=t.CompanyPositions[e.name]&&console.warn(`Duplicate Company Position being defined: ${e.name}`),t.CompanyPositions[e.name]=new a.CompanyPosition(e)}(e)})},function(e,t,n){"use strict";var r=this&&this.__awaiter||function(e,t,n,r){return new(n||(n=Promise))(function(a,i){function o(e){try{l(r.next(e))}catch(e){i(e)}}function s(e){try{l(r.throw(e))}catch(e){i(e)}}function l(e){e.done?a(e.value):new n(function(t){t(e.value)}).then(o,s)}l((r=r.apply(e,t||[])).next())})};Object.defineProperty(t,"__esModule",{value:!0});const a=n(699),i=n(18),o=n(27),s=n(3),l=n(37),c=n(28);class u{constructor(e,t,n,r,a,i){this.name=e,this.desc=t,this.generate=n,this.solver=r,this.difficulty=a,this.numTries=i}}t.CodingContractType=u,t.CodingContractTypes={};for(const e of a.codingContractTypesMetadata)t.CodingContractTypes[e.name]=new u(e.name,e.desc,e.gen,e.solver,e.difficulty,e.numTries);var m;!function(e){e[e.FactionReputation=0]="FactionReputation",e[e.FactionReputationAll=1]="FactionReputationAll",e[e.CompanyReputation=2]="CompanyReputation",e[e.Money=3]="Money"}(t.CodingContractRewardType||(t.CodingContractRewardType={})),function(e){e[e.Success=0]="Success",e[e.Failure=1]="Failure",e[e.Cancelled=2]="Cancelled"}(m=t.CodingContractResult||(t.CodingContractResult={}));class p{constructor(e="",n="Find Largest Prime Factor",r=null){if(this.tries=0,this.fn=e,this.fn.endsWith(".cct")||(this.fn+=".cct"),null==t.CodingContractTypes[n])throw new Error(`Error: invalid contract type: ${n} please contact developer`);this.type=n,this.data=t.CodingContractTypes[n].generate(),this.reward=r}static fromJSON(e){return i.Generic_fromJSON(p,e.data)}getData(){return this.data}getDescription(){return t.CodingContractTypes[this.type].desc(this.data)}getDifficulty(){return t.CodingContractTypes[this.type].difficulty}getMaxNumTries(){return t.CodingContractTypes[this.type].numTries}getType(){return t.CodingContractTypes[this.type].name}isSolution(e){return t.CodingContractTypes[this.type].solver(this.data,e)}prompt(){return r(this,void 0,void 0,function*(){return new Promise((e,n)=>{const r=t.CodingContractTypes[this.type],a=`coding-contract-prompt-popup-${this.fn}`,i=s.createElement("p",{innerHTML:["You are attempting to solve a Coding Contract. You have",`${this.getMaxNumTries()-this.tries} tries remaining,`,"after which the contract will self-destruct.

    ",`${r.desc(this.data).replace(/\n/g,"
    ")}`].join(" ")});let u,p,h;u=s.createElement("input",{onkeydown:e=>{e.keyCode===o.KEY.ENTER&&""!==u.value?(e.preventDefault(),p.click()):e.keyCode===o.KEY.ESC&&(e.preventDefault(),h.click())},placeholder:"Enter Solution here",width:"50%"}),p=s.createElement("a",{class:"a-link-button",clickListener:()=>{const t=u.value;this.isSolution(t)?e(m.Success):e(m.Failure),c.removeElementById(a)},innerText:"Solve"}),h=s.createElement("a",{class:"a-link-button",clickListener:()=>{e(m.Cancelled),c.removeElementById(a)},innerText:"Cancel"});const d=s.createElement("br");l.createPopup(a,[i,d,d,u,p,h]),u.focus()})})}toJSON(){return i.Generic_toJSON("CodingContract",this)}}t.CodingContract=p,i.Reviver.constructors.CodingContract=p},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.isString=function(e){return"string"==typeof e||e instanceof String}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});const r=n(9);t.exceptionAlert=function(e){console.error(e),r.dialogBoxCreate("Caught an exception: "+e+"

    Filename: "+(e.fileName||"UNKNOWN FILE NAME")+"

    Line Number: "+(e.lineNumber||"UNKNOWN LINE NUMBER")+"

    This is a bug, please report to game developer with this message as well as details about how to reproduce the bug.

    If you want to be safe, I suggest refreshing the game WITHOUT saving so that your safe doesn't get corrupted",!1)}},function(e,t,n){"use strict";n.r(t),n.d(t,"inviteToFaction",function(){return P}),n.d(t,"joinFaction",function(){return S}),n.d(t,"startHackingMission",function(){return T}),n.d(t,"displayFactionContent",function(){return M}),n.d(t,"purchaseAugmentationBoxCreate",function(){return x}),n.d(t,"hasAugmentationPrereqs",function(){return w}),n.d(t,"purchaseAugmentation",function(){return A}),n.d(t,"getNextNeurofluxLevel",function(){return R}),n.d(t,"processPassiveFactionRepGain",function(){return N});var r=n(1),a=n.n(r),i=n(52),o=n.n(i),s=n(287),l=n(11),c=n(68),u=n(124),m=n(4),p=n(20),h=n(8),d=n(14),g=n(69),_=n(13),y=n(71),f=n(0),b=n(19),E=n(12),v=n(9),k=n(286),C=(n(18),n(7)),O=n(45);function P(e){b.Settings.SuppressFactionInvites?(e.alreadyInvited=!0,f.Player.factionInvitations.push(e.name),E.routing.isOn(E.Page.Factions)&&d.Engine.loadFactionsContent()):Object(k.a)(e)}function S(e){e.isMember=!0,f.Player.factions.push(e.name);const t=e.getInfo();for(const e in t.enemies){const n=t.enemies[e];_.Factions[n]instanceof g.Faction&&(_.Factions[n].isBanned=!0)}}function T(e){const t=new y.a(e.playerReputation,e);Object(y.d)(!0,t),t.init()}function M(e,t=!1){const n=_.Factions[e];if(null==n)throw new Error(`Invalid factionName passed into displayFactionContent(): ${e}`);if(!n.isMember)throw new Error("Not a member of this faction. Cannot display faction information");o.a.render(a.a.createElement(s.FactionRoot,{engine:d.Engine,initiallyOnAugmentationsPage:t,faction:n,p:f.Player,startHackingMissionFn:T}),d.Engine.Display.factionContent)}function x(e,t){const n=t.getInfo(),r=Object(O.yesNoBoxGetYesButton)();r.innerHTML="Purchase",r.addEventListener("click",function(){!Object(c.f)(e)&&f.Player.hasAugmentation(e)||(A(e,t),Object(O.yesNoBoxClose)())});const a=Object(O.yesNoBoxGetNoButton)();a.innerHTML="Cancel",a.addEventListener("click",function(){Object(O.yesNoBoxClose)()}),Object(O.yesNoBoxCreate)("

    "+e.name+"


    "+e.info+"


    Would you like to purchase the "+e.name+" Augmentation for $"+Object(C.formatNumber)(e.baseCost*n.augmentationPriceMult,2)+"?")}function w(e){let t=!0;if(e.prereqs&&e.prereqs.length>0)for(let n=0;n=t.HacknetNodeMaxCores)return 1/0;const a=t.BaseCostForHacknetNodeCore,i=t.HacknetNodeUpgradeCoreMult;let o=0,s=this.cores;for(let e=0;e=t.HacknetNodeMaxLevel)return 1/0;const a=t.HacknetNodeUpgradeLevelMult;let i=0,o=this.level;for(let e=0;e=t.HacknetNodeMaxRam)return 1/0;let a=0,i=Math.round(Math.log2(this.ram)),o=this.ram;for(let e=0;e1?1:r<0?0:r}function o(e){null==e.baseDifficulty&&(e.baseDifficulty=e.hackDifficulty);var t=3;return(t+=e.baseDifficulty*a.Player.hacking_exp_mult*.3)*r.BitNodeMultipliers.HackExpGain}function s(e){const t=(100-e.hackDifficulty)/100*((a.Player.hacking_skill-(e.requiredHackingSkill-1))/a.Player.hacking_skill)*a.Player.hacking_money_mult/240;return t<0?0:t>1?1:t*r.BitNodeMultipliers.ScriptHackMoney}function l(e,t,n){const r=e.requiredHackingSkill*e.hackDifficulty;null==t&&(t=a.Player.hacking_skill),null==n&&(n=a.Player.intelligence);var i=2.5*r+500;return 5*(i/=t+50+.1*n)/a.Player.hacking_speed_mult}function c(e,t,n){return 3.2*l(e,t,n)}function u(e,t,n){return 4*l(e,t,n)}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});const r=n(3),a=n(82);t.createPopupCloseButton=function(e,t){let n;function i(e){27===e.keyCode&&n.click()}return n=r.createElement("button",{class:t.class?t.class:"popup-box-button",display:t.display?t.display:"inline-block",innerText:null==t.innerText?"Cancel":t.innerText,clickListener:()=>{if(e instanceof Element)a.removeElement(e);else try{const t=document.getElementById(e);t instanceof Element&&a.removeElement(t)}catch(e){console.error(`createPopupCloseButton() threw: ${e}`)}return document.removeEventListener("keydown",i),!1}}),document.addEventListener("keydown",i),n}},,function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});const r=n(3);t.createOptionElement=function(e,t=""){let n=t;return""===n&&(n=e),r.createElement("option",{text:e,value:n})}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.isScriptFilename=function(e){return e.endsWith(".js")||e.endsWith(".script")||e.endsWith(".ns")}},function(e,t,n){"use strict";n.d(t,"a",function(){return i});var r=n(1);const a=n.n(r).a.Component;class i extends a{corp(){return this.props.corp}eventHandler(){return this.props.eventHandler}routing(){return this.props.routing}render(){}}},function(e,t,n){"use strict";n.d(t,"a",function(){return x}),n.d(t,"c",function(){return A}),n.d(t,"e",function(){return N}),n.d(t,"f",function(){return I}),n.d(t,"b",function(){return B}),n.d(t,"d",function(){return L});var r=n(66),a=n(116),i=n(88),o=n(102),s=n(155),l=n(8),c=n(14),u=n(276),m=n(5),p=n(128),h=n(274),d=n(108),g=n(0),_=n(125),y=n(171),f=n(74),b=n(21),E=n(19),v=n(64),k=n(182),C=n(9),O=(n(147),n(83)),P=n(152),S=n(7),T=n(81);const M=n(177),x=[];for(var w=0;w{i=!0;let t=e.source.value;t.startsWith("./")&&(t=t.slice(2));let n=function(e){for(let t=0;t{n.push(e.id.name),r.push(e)}}),a+="var "+t+";\n(function (namespace) {\n",r.forEach(e=>{a+=Object(k.generate)(e),a+="\n"}),n.forEach(e=>{a+="namespace."+e+" = "+e,a+="\n"}),a+="})("+t+" || ("+t+" = {}));\n"}else{let t=[];e.specifiers.forEach(e=>{t.push(e.local.name)});let n=[];M.simple(o,{FunctionDeclaration:e=>{t.includes(e.id.name)&&n.push(e)}}),n.forEach(e=>{a+=Object(k.generate)(e),a+="\n"})}}}),!i)return{code:e,lineOffset:0};var o=0;if("Program"!==n.type||null==n.body)throw new Error("Code could not be properly parsed");for(let e=n.body.length-1;e>=0;--e)"ImportDeclaration"===n.body[e].type&&(n.body.splice(e,1),++o);var s=(a.match(/\n/g)||[]).length-o;return e=Object(k.generate)(n),{code:e=a+e,lineOffset:s}}(t,e);n=a.code,i=a.lineOffset}catch(t){return Object(C.dialogBoxCreate)("Error processing Imports in "+e.name+":
    "+t),e.env.stopFlag=!0,e.running=!1,void Object(r.killWorkerScript)(e)}var o;try{o=new u.a(n,function(t,n){var r=Object(p.a)(e);for(let e in r){let a=r[e];if("function"==typeof a)if("hack"===e||"grow"===e||"weaken"===e||"sleep"===e||"prompt"===e){let r=function(){let e=[];for(let n=0;n"+t),e.env.stopFlag=!0,e.running=!1,void Object(r.killWorkerScript)(e)}return new Promise(function(t,n){try{!function r(){try{if(e.env.stopFlag)return n(e);o.step()?Object(v.setTimeoutRef)(r,E.Settings.CodeInstructionRunTime):t(e)}catch(t){return t=t.toString(),Object(m.a)(t)||(t=Object(m.b)(e,t)),e.errorMessage=t,n(e)}}()}catch(t){return Object(S.isString)(t)?(e.errorMessage=t,n(e)):t instanceof a.WorkerScript?n(t):n(e)}})}function N(e,t){return D(e,t)?(t.runScript(e,g.Player.hacknet_node_money_mult),e.pid):0}function D(e,t){e.filename;let n=1;e.threads&&!isNaN(e.threads)?n=e.threads:e.threads=1;const l=Object(P.roundToTwo)(Object(y.getRamUsageFromRunningScript)(e)*n);if(l>t.maxRam-t.ramUsed)return Object(C.dialogBoxCreate)(`Not enough RAM to run script ${e.filename} with args `+`${Object(O.arrayToString)(e.args)}. This likely occurred because you re-loaded `+"the game and the script's RAM usage increased (either because of an update to the game or your changes to the script.)"),!1;t.ramUsed=Object(P.roundToTwo)(t.ramUsed+l);const c=Object(s.generateNextPid)();if(-1===c)throw new Error("Failed to start script because could not find available PID. This is most because you have too many scripts running.");const u=new a.WorkerScript(e,c,p.a);u.ramUsage=l,i.workerScripts.set(c,u),o.WorkerScriptStartStopEventEmitter.emitEvent();let d=null;if(u.name.endsWith(".js")||u.name.endsWith(".ns"))d=function(e){e.running=!0;let t=null;function n(n,r){return function(...a){if(e.env.stopFlag)throw e;if("sleep"===n)return r(...a);if(t)throw e.errorMessage=Object(m.b)(e,sprintf("Concurrent calls to Netscript functions not allowed! Did you forget to await hack(), grow(), or some other promise-returning function? (Currently running: %s tried to run: %s)",t,n),null),e;let i;t=n;try{i=r(...a)}catch(e){throw t=null,e}return i&&void 0!==i.finally?i.finally(function(){t=null}):(t=null,i)}}for(let t in e.env.vars)"function"==typeof e.env.vars[t]&&(e.env.vars[t]=n(t,e.env.vars[t]));return Object(h.a)(e.getServer().scripts,e).then(function(t){return void 0===t?e:[t,e]}).catch(t=>{if(t instanceof Error)throw e.errorMessage=Object(m.b)(e,t.message+(t.stack&&"\nstack:\n"+t.stack.toString()||"")),e;if(Object(m.a)(t))throw e.errorMessage=t,e;throw t})}(u);else if(!((d=R(u))instanceof Promise))return!1;return d.then(function(e){e.running&&(Object(r.killWorkerScript)(u),e.log("Script finished running"))}).catch(function(e){if(e instanceof Error)return Object(C.dialogBoxCreate)("Script runtime unknown error. This is a bug please contact game developer"),void console.error("Evaluating workerscript returns an Error. THIS SHOULDN'T HAPPEN: "+e.toString());if(e instanceof a.WorkerScript){if(!Object(m.a)(e.errorMessage))return void e.log("Script killed");var t=e.errorMessage.split("|");if(4!=t.length)return console.error("ERROR: Something wrong with Error text in evaluator..."),void console.error("Error text: "+errorText);var n=t[1],i=t[2],o=t[3];Object(C.dialogBoxCreate)("Script runtime error:
    Server Ip: "+n+"
    Script name: "+i+"
    Args:"+Object(O.arrayToString)(e.args)+"
    "+o),e.log("Script crashed with runtime error"),e.running=!1,e.env.stopFlag=!0}else{if(Object(m.a)(e))return Object(C.dialogBoxCreate)("Script runtime unknown error. This is a bug please contact game developer"),void console.error("ERROR: Evaluating workerscript returns only error message rather than WorkerScript object. THIS SHOULDN'T HAPPEN: "+e.toString());Object(C.dialogBoxCreate)("An unknown script died for an unknown reason. This is a bug please contact game dev"),console.error(e)}Object(r.killWorkerScript)(u)}),!0}function I(e=1){var t=e*c.Engine._idleSpeed/1e3;for(const e of i.workerScripts.values())e.scriptRef.onlineRunningTime+=t}function B(){var e=0;let t=-1!==window.location.href.toLowerCase().indexOf("?noscripts");t&&console.info("Skipping the load of any scripts during startup");for(const n in b.AllServers)if(b.AllServers.hasOwnProperty(n)){const r=b.AllServers[n];r.ramUsed=0;for(let e=0;el)return r.log(`Cannot run script ${t} (t=${i}) on ${e.hostname} because there is not enough available RAM!`),0;{null==r.disableLogs.ALL&&null==r.disableLogs.exec&&null==r.disableLogs.run&&null==r.disableLogs.spawn&&r.log(`Running script: ${t} on ${e.hostname} with ${i} threads and args: ${Object(O.arrayToString)(n)}.`);let a=new _.RunningScript(o,n);return a.threads=i,N(a,e)}}return r.log(`Could not find script ${t} on ${e.hostname}`),0}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});const r=n(6);function a(e){return t.GlobalAliases.hasOwnProperty(e)?t.GlobalAliases[e]:null}t.Aliases={},t.GlobalAliases={},t.loadAliases=function(e){t.Aliases=""===e?{}:JSON.parse(e)},t.loadGlobalAliases=function(e){t.GlobalAliases=""===e?{}:JSON.parse(e)},t.printAliases=function(){for(var e in t.Aliases)t.Aliases.hasOwnProperty(e)&&r.post("alias "+e+"="+t.Aliases[e]);for(var e in t.GlobalAliases)t.GlobalAliases.hasOwnProperty(e)&&r.post("global alias "+e+"="+t.GlobalAliases[e])},t.parseAliasDeclaration=function(e,n=!1){var r=e.match(/^([_|\w|!|%|,|@]+)="(.+)"$/);return null!=r&&3==r.length&&(n?function(e,n){e in t.Aliases&&delete t.Aliases[e],t.GlobalAliases[e]=n}(r[1],r[2]):function(e,n){e in t.GlobalAliases&&delete t.GlobalAliases[e],t.Aliases[e]=n}(r[1],r[2]),!0)},t.removeAlias=function(e){return t.Aliases.hasOwnProperty(e)?(delete t.Aliases[e],!0):!!t.GlobalAliases.hasOwnProperty(e)&&(delete t.GlobalAliases[e],!0)},t.substituteAliases=function(e){const n=e.split(" ");if(n.length>0){if("unalias"===n[0])return n.join(" ");null!=(i=function(e){return t.Aliases.hasOwnProperty(e)?t.Aliases[e]:null}(n[0]))?n[0]=i:null!=(i=a(n[0]))&&(n[0]=i);for(var r=0;rt&&(n=1),this.wanted=n,this.wanted<1&&(this.wanted=1)}else console.warn("ERROR: wantedLevelGains is NaN");"number"==typeof n?(t.gainMoney(n*e),t.recordMoneySource(n*e,"gang")):console.warn("ERROR: respectGains is NaN")},T.prototype.processTerritoryAndPowerGains=function(e=1){if(this.storedTerritoryAndPowerCycles+=e,!(this.storedTerritoryAndPowerCycles<100)){this.storedTerritoryAndPowerCycles-=100;var t=this.facName;for(const e in O)if(O.hasOwnProperty(e))if(e==t)O[e].power+=this.calculatePower();else{const t=Math.random();if(t<.5){const t=.005*O[e].power;O[e].power+=Math.min(.85,t)}else{const n=.75*t*O[e].territory;O[e].power+=n}}this.territoryWarfareEngaged?this.territoryClashChance=1:this.territoryClashChance>0&&(this.territoryClashChance=Math.max(0,this.territoryClashChance-.01));for(let e=0;et!==C[e]),r=Object(g.getRandomInt)(0,n.length-1),a=C[e],i=n[r];if(!(a!==t&&i!==t||Math.random()=30)&&this.respect>=this.getRespectNeededToRecruitMember()},T.prototype.getRespectNeededToRecruitMember=function(){if(this.members.length<3)return 0;const e=this.members.length-2;return Math.round(.9*Math.pow(e,3)+Math.pow(e,2))},T.prototype.recruitMember=function(e){if(""===(e=String(e))||!this.canRecruitMember())return!1;if(this.members.filter(t=>t.name===e).length>=1)return!1;let t=new M(e);return this.members.push(t),c.routing.isOn(c.Page.Gang)&&(this.createGangMemberDisplayElement(t),this.updateGangContent()),!0},T.prototype.getWantedPenalty=function(){return this.respect/(this.respect+this.wanted)},T.prototype.processExperienceGains=function(e=1){for(var t=0;t=0;--e){const n=this.members[e];if("Territory Warfare"!==n.task)continue;const r=t/Math.pow(n.def,.6);Math.random()")):t.log(`Ascended Gang member ${e.name}`),c.routing.isOn(c.Page.Gang)&&this.displayGangMemberList(),n}catch(e){if(null!=t)throw e;Object(d.exceptionAlert)(e)}},T.prototype.getDiscount=function(){const e=this.getPower(),t=this.respect,n=Math.pow(t,.01)+t/5e6+Math.pow(e,.01)+e/1e6-1;return Math.max(1,n)},T.prototype.getAllTaskNames=function(){let e=[];const t=Object.keys(w);return e=this.isHackingGang?t.filter(e=>{let t=w[e];return null!=t&&("Unassigned"!==e&&t.isHacking)}):t.filter(e=>{let t=w[e];return null!=t&&("Unassigned"!==e&&t.isCombat)})},T.prototype.getAllUpgradeNames=function(){return Object.keys(R)},T.prototype.getUpgradeCost=function(e){return null==R[e]?1/0:R[e].getCost(this)},T.prototype.getUpgradeType=function(e){const t=R[e];if(null==t)return"";switch(t.type){case"w":return"Weapon";case"a":return"Armor";case"v":return"Vehicle";case"r":return"Rootkit";case"g":return"Augmentation";default:return""}},T.prototype.toJSON=function(){return Object(p.Generic_toJSON)("Gang",this)},T.fromJSON=function(e){return Object(p.Generic_fromJSON)(T,e.data)},p.Reviver.constructors.Gang=T,M.prototype.calculateSkill=function(e,t=1){return Math.max(Math.floor(t*(32*Math.log(e+534.5)-200)),1)},M.prototype.updateSkillLevels=function(){this.hack=this.calculateSkill(this.hack_exp,this.hack_mult*this.hack_asc_mult),this.str=this.calculateSkill(this.str_exp,this.str_mult*this.str_asc_mult),this.def=this.calculateSkill(this.def_exp,this.def_mult*this.def_asc_mult),this.dex=this.calculateSkill(this.dex_exp,this.dex_mult*this.dex_asc_mult),this.agi=this.calculateSkill(this.agi_exp,this.agi_mult*this.agi_asc_mult),this.cha=this.calculateSkill(this.cha_exp,this.cha_mult*this.cha_asc_mult)},M.prototype.calculatePower=function(){return(this.hack+this.str+this.def+this.dex+this.agi+this.cha)/95},M.prototype.assignToTask=function(e){return w.hasOwnProperty(e)?(this.task=e,!0):(this.task="Unassigned",!1)},M.prototype.unassignFromTask=function(){this.task="Unassigned"},M.prototype.getTask=function(){return this.task instanceof x&&(this.task=this.task.name),w.hasOwnProperty(this.task)?w[this.task]:w.Unassigned},M.prototype.calculateRespectGain=function(e){const t=this.getTask();if(null==t||!(t instanceof x)||0===t.baseRespect)return 0;var n=t.hackWeight/100*this.hack+t.strWeight/100*this.str+t.defWeight/100*this.def+t.dexWeight/100*this.dex+t.agiWeight/100*this.agi+t.chaWeight/100*this.cha;if((n-=4*t.difficulty)<=0)return 0;const r=Math.pow(100*O[e.facName].territory,t.territory.respect)/100;if(isNaN(r)||r<=0)return 0;var a=e.getWantedPenalty();return 11*t.baseRespect*n*r*a},M.prototype.calculateWantedLevelGain=function(e){const t=this.getTask();if(null==t||!(t instanceof x)||0===t.baseWanted)return 0;let n=t.hackWeight/100*this.hack+t.strWeight/100*this.str+t.defWeight/100*this.def+t.dexWeight/100*this.dex+t.agiWeight/100*this.agi+t.chaWeight/100*this.cha;if((n-=3.5*t.difficulty)<=0)return 0;const r=Math.pow(100*O[e.facName].territory,t.territory.wanted)/100;if(isNaN(r)||r<=0)return 0;if(t.baseWanted<0)return.4*t.baseWanted*n*r;{const e=7*t.baseWanted/Math.pow(3*n*r,.8);return Math.min(100,e)}},M.prototype.calculateMoneyGain=function(e){const t=this.getTask();if(null==t||!(t instanceof x)||0===t.baseMoney)return 0;var n=t.hackWeight/100*this.hack+t.strWeight/100*this.str+t.defWeight/100*this.def+t.dexWeight/100*this.dex+t.agiWeight/100*this.agi+t.chaWeight/100*this.cha;if((n-=3.2*t.difficulty)<=0)return 0;const r=Math.pow(100*O[e.facName].territory,t.territory.money)/100;if(isNaN(r)||r<=0)return 0;var a=e.getWantedPenalty();return 5*t.baseMoney*n*r*a},M.prototype.gainExperience=function(e=1){const t=this.getTask();if(null==t||!(t instanceof x)||t===w.Unassigned)return;const n=Math.pow(t.difficulty,.9)*e;this.hack_exp+=t.hackWeight/1500*n,this.str_exp+=t.strWeight/1500*n,this.def_exp+=t.defWeight/1500*n,this.dex_exp+=t.dexWeight/1500*n,this.agi_exp+=t.agiWeight/1500*n,this.cha_exp+=t.chaWeight/1500*n},M.prototype.recordEarnedRespect=function(e=1,t){this.earnedRespect+=this.calculateRespectGain(t)*e},M.prototype.ascend=function(){const e=this.getAscensionResults(),t=e.hack,n=e.str,r=e.def,a=e.dex,i=e.agi,o=e.cha;this.hack_asc_mult+=t,this.str_asc_mult+=n,this.def_asc_mult+=r,this.dex_asc_mult+=a,this.agi_asc_mult+=i,this.cha_asc_mult+=o,this.upgrades.length=0,this.hack_mult=1,this.str_mult=1,this.def_mult=1,this.dex_mult=1,this.agi_mult=1,this.cha_mult=1;for(let e=0;e{!function(e,t,n,r,a){w[e]=new x(e,t,n,r,a)}(e.name,e.desc,e.isHacking,e.isCombat,e.params)}),A.prototype.getCost=function(e){const t=e.getDiscount();return this.cost/t},A.prototype.createDescription=function(){const e=["Increases:"];null!=this.mults.str&&e.push(`* Strength by ${Math.round(100*(this.mults.str-1))}%`),null!=this.mults.def&&e.push(`* Defense by ${Math.round(100*(this.mults.def-1))}%`),null!=this.mults.dex&&e.push(`* Dexterity by ${Math.round(100*(this.mults.dex-1))}%`),null!=this.mults.agi&&e.push(`* Agility by ${Math.round(100*(this.mults.agi-1))}%`),null!=this.mults.cha&&e.push(`* Charisma by ${Math.round(100*(this.mults.cha-1))}%`),null!=this.mults.hack&&e.push(`* Hacking by ${Math.round(100*(this.mults.hack-1))}%`),this.desc=e.join("
    ")},A.prototype.apply=function(e){null!=this.mults.str&&(e.str_mult*=this.mults.str),null!=this.mults.def&&(e.def_mult*=this.mults.def),null!=this.mults.dex&&(e.dex_mult*=this.mults.dex),null!=this.mults.agi&&(e.agi_mult*=this.mults.agi),null!=this.mults.cha&&(e.cha_mult*=this.mults.cha),null!=this.mults.hack&&(e.hack_mult*=this.mults.hack)},A.prototype.toJSON=function(){return Object(p.Generic_toJSON)("GangMemberUpgrade",this)},A.fromJSON=function(e){return Object(p.Generic_fromJSON)(A,e.data)},p.Reviver.constructors.GangMemberUpgrade=A;const R={};a.gangMemberUpgradesMetadata.forEach(e=>{!function(e,t,n,r){R[e]=new A(e,t,n,r)}(e.name,e.cost,e.upgType,e.mults)}),T.prototype.createGangMemberUpgradeBox=function(e,t=""){const n="gang-member-upgrade-popup-box";if(N.gangMemberUpgradeBoxOpened){if(null==N.gangMemberUpgradeBoxElements||null==N.gangMemberUpgradeBox||null==N.gangMemberUpgradeBoxContent)return void console.error("Refreshing Gang member upgrade box throws error because required elements are null");for(var r=2;r-1||this.members[r].task.indexOf(a)>-1){var i=this.members[r].createGangMemberUpgradePanel(this,e);N.gangMemberUpgradeBoxContent.appendChild(i),N.gangMemberUpgradeBoxElements.push(i)}}else{N.gangMemberUpgradeBoxFilter=Object(f.createElement)("input",{type:"text",placeholder:"Filter gang members",value:t,onkeyup:()=>{var t=N.gangMemberUpgradeBoxFilter.value.toString();this.createGangMemberUpgradeBox(e,t)}}),N.gangMemberUpgradeBoxDiscount=Object(f.createElement)("p",{innerText:"Discount: -"+u.numeralWrapper.format(1-1/this.getDiscount(),"0.00%"),marginLeft:"6px",tooltip:"You get a discount on equipment and upgrades based on your gang's respect and power. More respect and power leads to more discounts."}),N.gangMemberUpgradeBoxElements=[N.gangMemberUpgradeBoxFilter,N.gangMemberUpgradeBoxDiscount];for(a=N.gangMemberUpgradeBoxFilter.value.toString(),r=0;r-1||this.members[r].task.indexOf(a)>-1)&&N.gangMemberUpgradeBoxElements.push(this.members[r].createGangMemberUpgradePanel(this,e));N.gangMemberUpgradeBox=Object(b.createPopup)(n,N.gangMemberUpgradeBoxElements),N.gangMemberUpgradeBoxContent=document.getElementById(n+"-content"),N.gangMemberUpgradeBoxOpened=!0}},M.prototype.createGangMemberUpgradePanel=function(e,t){var n=Object(f.createElement)("div",{border:"1px solid white"}),r=Object(f.createElement)("h1",{innerText:this.name+" ("+this.task+")"});n.appendChild(r);var a=Object(f.createElement)("pre",{fontSize:"14px",display:"inline-block",width:"20%",innerText:"Hack: "+this.hack+" (x"+Object(h.formatNumber)(this.hack_mult*this.hack_asc_mult,2)+")\nStr: "+this.str+" (x"+Object(h.formatNumber)(this.str_mult*this.str_asc_mult,2)+")\nDef: "+this.def+" (x"+Object(h.formatNumber)(this.def_mult*this.def_asc_mult,2)+")\nDex: "+this.dex+" (x"+Object(h.formatNumber)(this.dex_mult*this.dex_asc_mult,2)+")\nAgi: "+this.agi+" (x"+Object(h.formatNumber)(this.agi_mult*this.agi_asc_mult,2)+")\nCha: "+this.cha+" (x"+Object(h.formatNumber)(this.cha_mult*this.cha_asc_mult,2)+")\n"});const i=[];function o(e){const t=R[e];null!=t?i.push(Object(f.createElement)("div",{class:"gang-owned-upgrade",innerText:e,tooltip:t.desc})):console.error(`Could not find GangMemberUpgrade object for name ${e}`)}for(const e of this.upgrades)o(e);for(const e of this.augmentations)o(e);var s=Object(f.createElement)("div",{class:"gang-owned-upgrades-div",innerText:"Purchased Upgrades:"});for(const e of i)s.appendChild(e);n.appendChild(a),n.appendChild(s),n.appendChild(Object(f.createElement)("br",{}));const l=[],c=[],m=[],p=[],d=[];for(let n in R)if(R.hasOwnProperty(n)){let r=R[n];if(t.money.lt(r.getCost(e)))continue;if(this.upgrades.includes(n)||this.augmentations.includes(n))continue;switch(r.type){case"w":l.push(r);break;case"a":c.push(r);break;case"v":m.push(r);break;case"r":p.push(r);break;case"g":d.push(r);break;default:console.error(`ERROR: Invalid Gang Member Upgrade Type: ${r.type}`)}}const g=Object(f.createElement)("div",{width:"20%",display:"inline-block"}),_=Object(f.createElement)("div",{width:"20%",display:"inline-block"}),y=Object(f.createElement)("div",{width:"20%",display:"inline-block"}),b=Object(f.createElement)("div",{width:"20%",display:"inline-block"}),E=Object(f.createElement)("div",{width:"20%",display:"inline-block"});g.appendChild(Object(f.createElement)("h2",{innerText:"Weapons"})),_.appendChild(Object(f.createElement)("h2",{innerText:"Armor"})),y.appendChild(Object(f.createElement)("h2",{innerText:"Vehicles"})),b.appendChild(Object(f.createElement)("h2",{innerText:"Rootkits"})),E.appendChild(Object(f.createElement)("h2",{innerText:"Augmentations"}));const v=[l,c,m,p,d],k=[g,_,y,b,E];for(let n=0;n(a.buyUpgrade(n,t,e),!1)};i>=3?s.tooltipleft=n.desc:s.tooltip=n.desc,r.appendChild(Object(f.createElement)("a",s))}(r[i],a,this,n,e)}}return n.appendChild(g),n.appendChild(_),n.appendChild(y),n.appendChild(b),n.appendChild(E),n};const N={gangContentCreated:!1,gangContainer:null,managementButton:null,territoryButton:null,gangManagementSubpage:null,gangTerritorySubpage:null,gangDesc:null,gangInfo:null,gangRecruitMemberButton:null,gangRecruitRequirementText:null,gangExpandAllButton:null,gangCollapseAllButton:null,gangMemberFilter:null,gangManageEquipmentButton:null,gangMemberList:null,gangMemberPanels:{},gangMemberUpgradeBoxOpened:!1,gangMemberUpgradeBox:null,gangMemberUpgradeBoxContent:null,gangMemberUpgradeBoxFilter:null,gangMemberUpgradeBoxDiscount:null,gangMemberUpgradeBoxElements:null,gangTerritoryDescText:null,gangTerritoryWarfareCheckbox:null,gangTerritoryWarfareCheckboxLabel:null,gangTerritoryWarfareClashChance:null,gangTerritoryDeathNotifyCheckbox:null,gangTerritoryDeathNotifyCheckboxLabel:null,gangTerritoryInfoText:null};T.prototype.displayGangContent=function(e){if(!N.gangContentCreated||null==N.gangContainer){N.gangContentCreated=!0,N.gangContainer=Object(f.createElement)("div",{id:"gang-container",class:"generic-menupage-container"});var t=this.facName;this.members,this.wanted,this.respect;N.gangContainer.appendChild(Object(f.createElement)("a",{class:"a-link-button",display:"inline-block",innerText:"Back",clickListener:()=>(i.Engine.loadFactionContent(),Object(l.displayFactionContent)(t),!1)})),N.managementButton=Object(f.createElement)("a",{id:"gang-management-subpage-button",class:"a-link-button-inactive",display:"inline-block",innerHTML:"Gang Management (Alt+1)",clickListener:()=>(N.gangManagementSubpage.style.display="block",N.gangTerritorySubpage.style.display="none",N.managementButton.classList.toggle("a-link-button-inactive"),N.managementButton.classList.toggle("a-link-button"),N.territoryButton.classList.toggle("a-link-button-inactive"),N.territoryButton.classList.toggle("a-link-button"),this.updateGangContent(),!1)}),N.territoryButton=Object(f.createElement)("a",{id:"gang-territory-subpage-button",class:"a-link-button",display:"inline-block",innerHTML:"Gang Territory (Alt+2)",clickListener:()=>(N.gangManagementSubpage.style.display="none",N.gangTerritorySubpage.style.display="block",N.managementButton.classList.toggle("a-link-button-inactive"),N.managementButton.classList.toggle("a-link-button"),N.territoryButton.classList.toggle("a-link-button-inactive"),N.territoryButton.classList.toggle("a-link-button"),this.updateGangContent(),!1)}),N.gangContainer.appendChild(N.managementButton),N.gangContainer.appendChild(N.territoryButton),N.gangManagementSubpage=Object(f.createElement)("div",{display:"block",id:"gang-management-subpage"});var n="";n=this.isHackingGang?"Ethical Hacking":"Vigilante Justice",N.gangDesc=Object(f.createElement)("p",{width:"70%",innerHTML:"This page is used to manage your gang members and get an overview of your gang's stats.

    If a gang member is not earning much money or respect, the task that you have assigned to that member might be too difficult. Consider training that member's stats or choosing an easier task. The tasks closer to the top of the dropdown list are generally easier. Alternatively, the gang member's low production might be due to the fact that your wanted level is too high. Consider assigning a few members to the '"+n+"' task to lower your wanted level.

    Installing Augmentations does NOT reset your progress with your Gang. Furthermore, after installing Augmentations, you will automatically be a member of whatever Faction you created your gang with.

    You can also manage your gang programmatically through Netscript using the Gang API"}),N.gangManagementSubpage.appendChild(N.gangDesc),N.gangInfo=Object(f.createElement)("p",{id:"gang-info",width:"70%"}),N.gangManagementSubpage.appendChild(N.gangInfo),N.gangRecruitMemberButton=Object(f.createElement)("a",{id:"gang-management-recruit-member-btn",class:"a-link-button-inactive",innerHTML:"Recruit Gang Member",display:"inline-block",margin:"10px",clickListener:()=>{const e="recruit-gang-member-popup";let t;const n=Object(f.createElement)("p",{innerText:"Please enter a name for your new Gang member:"}),r=Object(f.createElement)("br"),a=Object(f.createElement)("input",{onkeyup:e=>{e.keyCode===_.KEY.ENTER&&t.click()},placeholder:"Name must be unique",type:"text"});t=Object(f.createElement)("a",{class:"std-button",clickListener:()=>{let t=a.value;return""===t?(Object(m.dialogBoxCreate)("You must enter a name for your Gang member!"),!1):this.canRecruitMember()?this.recruitMember(t)?(Object(k.removeElementById)(e),!1):(Object(m.dialogBoxCreate)("You already have a gang member with this name!"),!1):(Object(m.dialogBoxCreate)("You cannot recruit another Gang member!"),!1)},innerText:"Recruit Gang Member"});const i=Object(f.createElement)("a",{class:"std-button",clickListener:()=>(Object(k.removeElementById)(e),!1),innerText:"Cancel"});Object(b.createPopup)(e,[n,r,a,t,i]),a.focus()}}),N.gangManagementSubpage.appendChild(N.gangRecruitMemberButton),N.gangRecruitRequirementText=Object(f.createElement)("p",{color:"red",id:"gang-recruit-requirement-text",margin:"10px"}),N.gangManagementSubpage.appendChild(N.gangRecruitRequirementText),N.gangManagementSubpage.appendChild(Object(f.createElement)("br",{})),N.gangExpandAllButton=Object(f.createElement)("a",{class:"a-link-button",display:"inline-block",innerHTML:"Expand All",clickListener:()=>{for(var e=N.gangManagementSubpage.getElementsByClassName("accordion-header"),t=0;t{for(var e=N.gangManagementSubpage.getElementsByClassName("accordion-header"),t=0;t{this.displayGangMemberList()}}),N.gangManageEquipmentButton=Object(f.createElement)("a",{class:"a-link-button",display:"inline-block",innerHTML:"Manage Equipment",clickListener:()=>{this.createGangMemberUpgradeBox(e)}}),N.gangManagementSubpage.appendChild(N.gangExpandAllButton),N.gangManagementSubpage.appendChild(N.gangCollapseAllButton),N.gangManagementSubpage.appendChild(N.gangMemberFilter),N.gangManagementSubpage.appendChild(N.gangManageEquipmentButton),N.gangMemberList=Object(f.createElement)("ul",{id:"gang-member-list"}),this.displayGangMemberList(),N.gangManagementSubpage.appendChild(N.gangMemberList),N.gangTerritorySubpage=Object(f.createElement)("div",{id:"gang-territory-subpage",display:"none"}),N.gangTerritoryDescText=Object(f.createElement)("p",{width:"70%",innerHTML:"This page shows how much territory your Gang controls. This statistic is listed as a percentage, which represents how much of the total territory you control.

    Every ~20 seconds, your gang has a chance to 'clash' with other gangs. Your chance to win a clash depends on your gang's power, which is listed in the display below. Your gang's power slowly accumulates over time. The accumulation rate is determined by the stats of all Gang members you have assigned to the 'Territory Warfare' task. Gang members that are not assigned to this task do not contribute to your gang's power. Your gang also loses a small amount of power whenever you lose a clash

    NOTE: Gang members assigned to 'Territory Warfare' can be killed during clashes. This can happen regardless of whether you win or lose the clash. A gang member being killed results in both respect and power loss for your gang.

    The amount of territory you have affects all aspects of your Gang members' production, including money, respect, and wanted level. It is very beneficial to have high territory control.

    "}),N.gangTerritorySubpage.appendChild(N.gangTerritoryDescText),N.gangTerritoryWarfareCheckbox=Object(f.createElement)("input",{display:"inline-block",id:"gang-management-territory-warfare-checkbox",changeListener:()=>{this.territoryWarfareEngaged=N.gangTerritoryWarfareCheckbox.checked},margin:"2px",type:"checkbox"}),N.gangTerritoryWarfareCheckbox.checked=this.territoryWarfareEngaged,N.gangTerritoryWarfareCheckboxLabel=Object(f.createElement)("label",{color:"white",display:"inline-block",for:"gang-management-territory-warfare-checkbox",innerText:"Engage in Territory Warfare",tooltip:"Engaging in Territory Warfare sets your clash chance to 100%. Disengaging will cause your clash chance to gradually decrease until it reaches 0%"}),N.gangTerritorySubpage.appendChild(N.gangTerritoryWarfareCheckbox),N.gangTerritorySubpage.appendChild(N.gangTerritoryWarfareCheckboxLabel),N.gangTerritorySubpage.appendChild(Object(f.createElement)("br")),N.gangTerritoryWarfareClashChance=Object(f.createElement)("p",{display:"inline-block"}),N.gangTerritorySubpage.appendChild(N.gangTerritoryWarfareClashChance),N.gangTerritorySubpage.appendChild(Object(f.createElement)("div",{class:"help-tip",display:"inline-block",innerText:"?",clickListener:()=>{Object(m.dialogBoxCreate)("This percentage represents the chance you have of 'clashing' with with another gang. If you do not wish to gain/lose territory, then keep this percentage at 0% by not engaging in territory warfare.")}})),N.gangTerritoryDeathNotifyCheckbox=Object(f.createElement)("input",{display:"inline-block",id:"gang-management-notify-member-death-checkbox",changeListener:()=>{this.notifyMemberDeath=N.gangTerritoryDeathNotifyCheckbox.checked},margin:"2px",type:"checkbox"}),N.gangTerritoryDeathNotifyCheckbox.checked=this.notifyMemberDeath,N.gangTerritoryDeathNotifyCheckboxLabel=Object(f.createElement)("label",{color:"white",display:"inline-block",for:"gang-management-notify-member-death-checkbox",innerText:"Notify about Gang Member Deaths",tooltip:"If this is enabled, then you will receive a pop-up notifying you whenever one of your Gang Members dies in a territory clash."}),N.gangTerritorySubpage.appendChild(Object(f.createElement)("br")),N.gangTerritorySubpage.appendChild(N.gangTerritoryDeathNotifyCheckbox),N.gangTerritorySubpage.appendChild(N.gangTerritoryDeathNotifyCheckboxLabel),N.gangTerritorySubpage.appendChild(Object(f.createElement)("br"));var r=Object(f.createElement)("fieldset",{display:"block",margin:"6px",width:"50%"});N.gangTerritoryInfoText=Object(f.createElement)("p"),r.appendChild(N.gangTerritoryInfoText),N.gangTerritorySubpage.appendChild(r),N.gangContainer.appendChild(N.gangTerritorySubpage),N.gangContainer.appendChild(N.gangManagementSubpage),document.getElementById("entire-game-container").appendChild(N.gangContainer)}N.gangContainer.style.display="block",this.updateGangContent()},T.prototype.displayGangMemberList=function(){Object(E.removeChildrenFromElement)(N.gangMemberList),N.gangMemberPanels={};const e=this.members,t=N.gangMemberFilter.value.toString();for(var n=0;n-1||e[n].task.indexOf(t)>-1)&&this.createGangMemberDisplayElement(e[n])},T.prototype.updateGangContent=function(){if(N.gangContentCreated)if(N.gangMemberUpgradeBoxOpened&&(N.gangMemberUpgradeBoxDiscount.childNodes[0].nodeValue="Discount: -"+u.numeralWrapper.format(1-1/this.getDiscount(),"0.00%")),"block"===N.gangTerritorySubpage.style.display){N.gangTerritoryWarfareClashChance.innerText=`Territory Clash Chance: ${u.numeralWrapper.format(this.territoryClashChance,"0.000%")}`,N.gangTerritoryWarfareCheckbox.checked=this.territoryWarfareEngaged,N.gangTerritoryInfoText.innerHTML="";const e=O[this.facName].power;let t=Object.keys(O).filter(e=>e!=this.facName);t.unshift(this.facName);for(const n of t)if(O.hasOwnProperty(n)){const t=O[n];let r,a=100*t.territory;if(r=a<=0?Object(h.formatNumber)(0,2):a>=100?Object(h.formatNumber)(100,2):Object(h.formatNumber)(a,2),n===this.facName){let e=`${n}
    Power: ${Object(h.formatNumber)(t.power,6)}
    `;e+=`Territory: ${r}%

    `,N.gangTerritoryInfoText.innerHTML+=e}else{const a=e/(t.power+e);let i=`${n}
    Power: ${Object(h.formatNumber)(t.power,6)}
    `;i+=`Territory: ${r}%
    `,i+=`Chance to win clash with this gang: ${u.numeralWrapper.format(a,"0.000%")}

    `,N.gangTerritoryInfoText.innerHTML+=i}}}else{if(N.gangInfo instanceof Element){var e,t=s.Factions[this.facName];e=t instanceof o.Faction?t.playerReputation:"ERROR",Object(E.removeChildrenFromElement)(N.gangInfo),N.gangInfo.appendChild(Object(f.createElement)("p",{display:"inline-block",innerText:"Respect: "+Object(h.formatNumber)(this.respect,6)+" ("+Object(h.formatNumber)(5*this.respectGainRate,6)+" / sec)",tooltip:"Represents the amount of respect your gang has from other gangs and criminal organizations. Your respect affects the amount of money your gang members will earn, and also determines how much reputation you are earning with your gang's corresponding Faction."})),N.gangInfo.appendChild(Object(f.createElement)("br")),N.gangInfo.appendChild(Object(f.createElement)("p",{display:"inline-block",innerText:"Wanted Level: "+Object(h.formatNumber)(this.wanted,6)+" ("+Object(h.formatNumber)(5*this.wantedGainRate,6)+" / sec)",tooltip:"Represents how much the gang is wanted by law enforcement. The higher your gang's wanted level, the harder it will be for your gang members to make money and earn respect. Note that the minimum wanted level is 1."})),N.gangInfo.appendChild(Object(f.createElement)("br"));var n=this.getWantedPenalty();n=100*(1-n),N.gangInfo.appendChild(Object(f.createElement)("p",{display:"inline-block",innerText:`Wanted Level Penalty: -${Object(h.formatNumber)(n,2)}%`,tooltip:"Penalty for respect and money gain rates due to Wanted Level"})),N.gangInfo.appendChild(Object(f.createElement)("br")),N.gangInfo.appendChild(Object(f.createElement)("p",{display:"inline-block",innerText:`Money gain rate: ${u.numeralWrapper.format(5*this.moneyGainRate,"$0.000a")} / sec`})),N.gangInfo.appendChild(Object(f.createElement)("br"));var r=100*O[this.facName].territory;let a;a=r<=0?Object(h.formatNumber)(0,2):r>=100?Object(h.formatNumber)(100,2):Object(h.formatNumber)(r,2),N.gangInfo.appendChild(Object(f.createElement)("p",{display:"inline-block",innerText:`Territory: ${Object(h.formatNumber)(a,3)}%`,tooltip:"The percentage of total territory your Gang controls"})),N.gangInfo.appendChild(Object(f.createElement)("br")),N.gangInfo.appendChild(Object(f.createElement)("p",{display:"inline-block",innerText:"Faction reputation: "+Object(h.formatNumber)(e,3)})),N.gangInfo.appendChild(Object(f.createElement)("br"));const l=1e3/i.Engine._idleSpeed;N.gangInfo.appendChild(Object(f.createElement)("p",{innerText:`Bonus time: ${Object(h.convertTimeMsToTimeElapsedString)(this.storedCycles/l*1e3)}`,display:"inline-block",tooltip:"You gain bonus time while offline or when the game is inactive (e.g. when the tab is throttled by the browser). Bonus time makes the Gang mechanic progress faster, up to 5x the normal speed"})),N.gangInfo.appendChild(Object(f.createElement)("br"))}else console.error("gang-info DOM element DNE");const a=this.members.length,l=this.getRespectNeededToRecruitMember(),c=N.gangRecruitMemberButton;a>=30?(c.className="a-link-button-inactive",N.gangRecruitRequirementText.style.display="inline-block",N.gangRecruitRequirementText.innerHTML="You have reached the maximum amount of gang members"):this.canRecruitMember()?(c.className="a-link-button",N.gangRecruitRequirementText.style.display="none"):(c.className="a-link-button-inactive",N.gangRecruitRequirementText.style.display="inline-block",N.gangRecruitRequirementText.innerHTML=`${Object(h.formatNumber)(l,2)} respect needed to recruit next member`);for(let e=0;e")});N.gangMemberPanels[t].statsDiv=i;const o=Object(f.createElement)("pre",{display:"inline",id:t+"gang-member-stats-text"}),s=Object(f.createElement)("br"),l=Object(f.createElement)("button",{class:"accordion-button",innerText:"Ascend",clickListener:()=>{const t=`gang-management-ascend-member ${e.name}`,n=e.getAscensionResults(),r=Object(f.createElement)("pre",{innerText:["Are you sure you want to ascend this member? (S)he will lose all of","his non-Augmentation upgrades and his/her stats will reset back to 1.","",`Furthermore, your gang will lose ${u.numeralWrapper.format(e.earnedRespect,"0.000000")} respect`,"","In return, (s)he will gain the following permanent boost to stat multipliers:\n",`Hacking: +${u.numeralWrapper.format(n.hack,"0.00%")}`,`Strength: +${u.numeralWrapper.format(n.str,"0.00%")}`,`Defense: +${u.numeralWrapper.format(n.def,"0.00%")}`,`Dexterity: +${u.numeralWrapper.format(n.dex,"0.00%")}`,`Agility: +${u.numeralWrapper.format(n.agi,"0.00%")}`,`Charisma: +${u.numeralWrapper.format(n.cha,"0.00%")}`].join("\n")}),a=Object(f.createElement)("button",{class:"std-button",clickListener:()=>(this.ascendMember(e),this.updateGangMemberDisplayElement(e),Object(k.removeElementById)(t),!1),innerText:"Ascend"}),i=Object(f.createElement)("button",{class:"std-button",clickListener:()=>(Object(k.removeElementById)(t),!1),innerText:"Cancel"});Object(b.createPopup)(t,[r,a,i])}}),c=Object(f.createElement)("div",{class:"help-tip",clickListener:()=>{Object(m.dialogBoxCreate)(["Ascending a Gang Member resets the member's progress and stats in exchange","for a permanent boost to their stat multipliers.","

    The additional stat multiplier that the Gang Member gains upon ascension","is based on the amount of multipliers the member has from non-Augmentation Equipment.","

    Upon ascension, the member will lose all of its non-Augmentation Equipment and your","gang will lose respect equal to the total respect earned by the member."].join(" "))},innerText:"?",marginTop:"5px"});i.appendChild(o),i.appendChild(s),i.appendChild(l),i.appendChild(c);const p=Object(f.createElement)("div",{class:"gang-member-info-div",id:t+"gang-member-task"}),h=Object(f.createElement)("select",{class:"dropdown",id:t+"gang-member-task-selector"});let d=this.getAllTaskNames();d.unshift("---");for(var g=0;g{var t=h.options[h.selectedIndex].text;e.assignToTask(t),this.setGangMemberTaskDescription(e,t),this.updateGangContent()}),w.hasOwnProperty(e.task)){var E=e.task,v=0;for(let e=0;e"))}var a=document.getElementById(t+"gang-member-gain-info");a&&(a.innerHTML=[`Money: $ ${Object(h.formatNumber)(5*e.calculateMoneyGain(this),2)} / sec`,`Respect: ${Object(h.formatNumber)(5*e.calculateRespectGain(this),6)} / sec`,`Wanted Level: ${Object(h.formatNumber)(5*e.calculateWantedLevelGain(this),6)} / sec`,`Total Respect Earned: ${Object(h.formatNumber)(e.earnedRespect,6)}`].join("
    "));const i=document.getElementById(t+"gang-member-task-selector");if(i){let t=this.getAllTaskNames();if(t.unshift("---"),w.hasOwnProperty(e.task)){const n=e.task;let r=0;for(let e=0;e
    This augmentation increases all of the player's combat stats by 8%.",strength_mult:1.08,defense_mult:1.08,agility_mult:1.08,dexterity_mult:1.08});t.addToFactions(["Tetrads","The Dark Army","The Syndicate"]),x(o.AugmentationNames.HemoRecirculator)&&delete a.Augmentations[o.AugmentationNames.HemoRecirculator],O(t);const n=new r.Augmentation({name:o.AugmentationNames.Targeting1,moneyCost:3e6,repCost:2e3,info:"This cranial implant is embedded within the player's inner ear structure and optic nerves. It regulates and enhances the user's balance and hand-eye coordination. It is also capable of augmenting reality by projecting digital information directly onto the retina. These enhancements allow the player to better lock-on and keep track of enemies.

    This augmentation increases the player's dexterity by 10%.",dexterity_mult:1.1});n.addToFactions(["Slum Snakes","The Dark Army","The Syndicate","Sector-12","Volhaven","Ishima","OmniTek Incorporated","KuaiGong International","Blade Industries"]),x(o.AugmentationNames.Targeting1)&&delete a.Augmentations[o.AugmentationNames.Targeting1],O(n);const i=new r.Augmentation({name:o.AugmentationNames.Targeting2,moneyCost:85e5,repCost:3500,info:"This is an upgrade of the Augmented Targeting I cranial implant, which is capable of augmenting reality and enhances the user's balance and hand-eye coordination.

    This augmentation increases the player's dexterity by 20%.",prereqs:[o.AugmentationNames.Targeting1],dexterity_mult:1.2});i.addToFactions(["The Dark Army","The Syndicate","Sector-12","Volhaven","Ishima","OmniTek Incorporated","KuaiGong International","Blade Industries"]),x(o.AugmentationNames.Targeting2)&&delete a.Augmentations[o.AugmentationNames.Targeting2],O(i);const s=new r.Augmentation({name:o.AugmentationNames.Targeting3,moneyCost:23e6,repCost:11e3,info:"This is an upgrade of the Augmented Targeting II cranial implant, which is capable of augmenting reality and enhances the user's balance and hand-eye coordination.

    This augmentation increases the player's dexterity by 30%.",prereqs:[o.AugmentationNames.Targeting2],dexterity_mult:1.3});s.addToFactions(["The Dark Army","The Syndicate","OmniTek Incorporated","KuaiGong International","Blade Industries","The Covenant"]),x(o.AugmentationNames.Targeting3)&&delete a.Augmentations[o.AugmentationNames.Targeting3],O(s);const m=new r.Augmentation({name:o.AugmentationNames.SyntheticHeart,moneyCost:575e6,repCost:3e5,info:"This advanced artificial heart, created from plasteel and graphene, is capable of pumping more blood at much higher efficiencies than a normal human heart.

    This augmentation increases the player's agility and strength by 50%.",agility_mult:1.5,strength_mult:1.5});m.addToFactions(["KuaiGong International","Fulcrum Secret Technologies","Speakers for the Dead","NWO","The Covenant","Daedalus","Illuminati"]),x(o.AugmentationNames.SyntheticHeart)&&delete a.Augmentations[o.AugmentationNames.SyntheticHeart],O(m);const h=new r.Augmentation({name:o.AugmentationNames.SynfibrilMuscle,repCost:175e3,moneyCost:225e6,info:"The myofibrils in human muscles are injected with special chemicals that react with the proteins inside the myofibrils, altering their underlying structure. The end result is muscles that are stronger and more elastic. Scientists have named these artificially enhanced units 'synfibrils'.

    This augmentation increases the player's strength and defense by 30%.",strength_mult:1.3,defense_mult:1.3});h.addToFactions(["KuaiGong International","Fulcrum Secret Technologies","Speakers for the Dead","NWO","The Covenant","Daedalus","Illuminati","Blade Industries"]),x(o.AugmentationNames.SynfibrilMuscle)&&delete a.Augmentations[o.AugmentationNames.SynfibrilMuscle],O(h);const d=new r.Augmentation({name:o.AugmentationNames.CombatRib1,repCost:3e3,moneyCost:475e4,info:"The human body's ribs are replaced with artificial ribs that automatically and continuously release cognitive and performance-enhancing drugs into the bloodstream, improving the user's abilities in combat.

    This augmentation increases the player's strength and defense by 10%.",strength_mult:1.1,defense_mult:1.1});d.addToFactions(["Slum Snakes","The Dark Army","The Syndicate","Sector-12","Volhaven","Ishima","OmniTek Incorporated","KuaiGong International","Blade Industries"]),x(o.AugmentationNames.CombatRib1)&&delete a.Augmentations[o.AugmentationNames.CombatRib1],O(d);const g=new r.Augmentation({name:o.AugmentationNames.CombatRib2,repCost:7500,moneyCost:13e6,info:"This is an upgrade to the Combat Rib I augmentation, and is capable of releasing even more potent combat-enhancing drugs into the bloodstream.

    This augmentation increases the player's strength and defense by 14%.",prereqs:[o.AugmentationNames.CombatRib1],strength_mult:1.14,defense_mult:1.14});g.addToFactions(["The Dark Army","The Syndicate","Sector-12","Volhaven","Ishima","OmniTek Incorporated","KuaiGong International","Blade Industries"]),x(o.AugmentationNames.CombatRib2)&&delete a.Augmentations[o.AugmentationNames.CombatRib2],O(g);const _=new r.Augmentation({name:o.AugmentationNames.CombatRib3,repCost:14e3,moneyCost:24e6,info:"This is an upgrade to the Combat Rib II augmentation, and is capable of releasing even more potent combat-enhancing drugs into the bloodstream

    .This augmentation increases the player's strength and defense by 18%.",prereqs:[o.AugmentationNames.CombatRib2],strength_mult:1.18,defense_mult:1.18});_.addToFactions(["The Dark Army","The Syndicate","OmniTek Incorporated","KuaiGong International","Blade Industries","The Covenant"]),x(o.AugmentationNames.CombatRib3)&&delete a.Augmentations[o.AugmentationNames.CombatRib3],O(_);const y=new r.Augmentation({name:o.AugmentationNames.NanofiberWeave,repCost:15e3,moneyCost:25e6,info:"Synthetic nanofibers are woven into the skin's extracellular matrix using electrospinning. This improves the skin's ability to regenerate itself and protect the body from external stresses and forces.

    This augmentation increases the player's strength and defense by 20%.",strength_mult:1.2,defense_mult:1.2});y.addToFactions(["Tian Di Hui","The Syndicate","The Dark Army","Speakers for the Dead","Blade Industries","Fulcrum Secret Technologies","OmniTek Incorporated"]),x(o.AugmentationNames.NanofiberWeave)&&delete a.Augmentations[o.AugmentationNames.NanofiberWeave],O(y);const b=new r.Augmentation({name:o.AugmentationNames.SubdermalArmor,repCost:35e4,moneyCost:65e7,info:"The NEMEAN Subdermal Weave is a thin, light-weight, graphene plating that houses a dilatant fluid. The material is implanted underneath the skin, and is the most advanced form of defensive enhancement that has ever been created. The dilatant fluid, despite being thin and light, is extremely effective at stopping piercing blows and reducing blunt trauma. The properties of graphene allow the plating to mitigate damage from any fire-related or electrical traumas.

    This augmentation increases the player's defense by 120%.",defense_mult:2.2});b.addToFactions(["The Syndicate","Fulcrum Secret Technologies","Illuminati","Daedalus","The Covenant"]),x(o.AugmentationNames.SubdermalArmor)&&delete a.Augmentations[o.AugmentationNames.SubdermalArmor],O(b);const E=new r.Augmentation({name:o.AugmentationNames.WiredReflexes,repCost:500,moneyCost:5e5,info:"Synthetic nerve-enhancements are injected into all major parts of the somatic nervous system, supercharging the body's ability to send signals through neurons. This results in increased reflex speed.

    This augmentation increases the player's agility and dexterity by 5%.",agility_mult:1.05,dexterity_mult:1.05});E.addToFactions(["Tian Di Hui","Slum Snakes","Sector-12","Volhaven","Aevum","Ishima","The Syndicate","The Dark Army","Speakers for the Dead"]),x(o.AugmentationNames.WiredReflexes)&&delete a.Augmentations[o.AugmentationNames.WiredReflexes],O(E);const v=new r.Augmentation({name:o.AugmentationNames.GrapheneBoneLacings,repCost:45e4,moneyCost:85e7,info:"A graphene-based material is grafted and fused into the user's bones, significantly increasing their density and tensile strength.

    This augmentation increases the player's strength and defense by 70%.",strength_mult:1.7,defense_mult:1.7});v.addToFactions(["Fulcrum Secret Technologies","The Covenant"]),x(o.AugmentationNames.GrapheneBoneLacings)&&delete a.Augmentations[o.AugmentationNames.GrapheneBoneLacings],O(v);const k=new r.Augmentation({name:o.AugmentationNames.BionicSpine,repCost:18e3,moneyCost:25e6,info:"An artificial spine created from plasteel and carbon fibers that completely replaces the organic spine. Not only is the Bionic Spine physically stronger than a human spine, but it is also capable of digitally stimulating and regulating the neural signals that are sent and received by the spinal cord. This results in greatly improved senses and reaction speeds.

    This augmentation increases all of the player's combat stats by 15%.",strength_mult:1.15,defense_mult:1.15,agility_mult:1.15,dexterity_mult:1.15});k.addToFactions(["Speakers for the Dead","The Syndicate","KuaiGong International","OmniTek Incorporated","Blade Industries"]),x(o.AugmentationNames.BionicSpine)&&delete a.Augmentations[o.AugmentationNames.BionicSpine],O(k);const C=new r.Augmentation({name:o.AugmentationNames.GrapheneBionicSpine,repCost:65e4,moneyCost:12e8,info:"An upgrade to the Bionic Spine augmentation. It fuses the implant with an advanced graphene material to make it much stronger and lighter.

    This augmentation increases all of the player's combat stats by 60%.",prereqs:[o.AugmentationNames.BionicSpine],strength_mult:1.6,defense_mult:1.6,agility_mult:1.6,dexterity_mult:1.6});C.addToFactions(["Fulcrum Secret Technologies","ECorp"]),x(o.AugmentationNames.GrapheneBionicSpine)&&delete a.Augmentations[o.AugmentationNames.GrapheneBionicSpine],O(C);const P=new r.Augmentation({name:o.AugmentationNames.BionicLegs,repCost:6e4,moneyCost:75e6,info:"Cybernetic legs created from plasteel and carbon fibers that completely replace the user's organic legs.

    This augmentation increases the player's agility by 60%.",agility_mult:1.6});P.addToFactions(["Speakers for the Dead","The Syndicate","KuaiGong International","OmniTek Incorporated","Blade Industries"]),x(o.AugmentationNames.BionicLegs)&&delete a.Augmentations[o.AugmentationNames.BionicLegs],O(P);const T=new r.Augmentation({name:o.AugmentationNames.GrapheneBionicLegs,repCost:3e5,moneyCost:9e8,info:"An upgrade to the Bionic Legs augmentation. It fuses the implant with an advanced graphene material to make it much stronger and lighter.

    This augmentation increases the player's agility by 150%.",prereqs:[o.AugmentationNames.BionicLegs],agility_mult:2.5});T.addToFactions(["MegaCorp","ECorp","Fulcrum Secret Technologies"]),x(o.AugmentationNames.GrapheneBionicLegs)&&delete a.Augmentations[o.AugmentationNames.GrapheneBionicLegs],O(T);const M=new r.Augmentation({name:o.AugmentationNames.SpeechProcessor,repCost:3e3,moneyCost:1e7,info:"A cochlear implant with an embedded computer that analyzes incoming speech. The embedded computer processes characteristics of incoming speech, such as tone and inflection, to pick up on subtle cues and aid in social interactions.

    This augmentation increases the player's charisma by 20%.",charisma_mult:1.2});M.addToFactions(["Tian Di Hui","Chongqing","Sector-12","New Tokyo","Aevum","Ishima","Volhaven","Silhouette"]),x(o.AugmentationNames.SpeechProcessor)&&delete a.Augmentations[o.AugmentationNames.SpeechProcessor],O(M);const w=new r.Augmentation({name:o.AugmentationNames.TITN41Injection,repCost:1e4,moneyCost:38e6,info:"TITN is a series of viruses that targets and alters the sequences of human DNA in genes that control personality. The TITN-41 strain alters these genes so that the subject becomes more outgoing and socialable.

    This augmentation increases the player's charisma and charisma experience gain rate by 15%.",charisma_mult:1.15,charisma_exp_mult:1.15});w.addToFactions(["Silhouette"]),x(o.AugmentationNames.TITN41Injection)&&delete a.Augmentations[o.AugmentationNames.TITN41Injection],O(w);const A=new r.Augmentation({name:o.AugmentationNames.EnhancedSocialInteractionImplant,repCost:15e4,moneyCost:275e6,info:"A cranial implant that greatly assists in the user's ability to analyze social situations and interactions. The system uses a wide variety of factors such as facial expression, body language, and the voice's tone/inflection to determine the best course of action during socialsituations. The implant also uses deep learning software to continuously learn new behaviorpatterns and how to best respond.

    This augmentation increases the player's charisma and charisma experience gain rate by 60%.",charisma_mult:1.6,charisma_exp_mult:1.6});A.addToFactions(["Bachman & Associates","NWO","Clarke Incorporated","OmniTek Incorporated","Four Sigma"]),x(o.AugmentationNames.EnhancedSocialInteractionImplant)&&delete a.Augmentations[o.AugmentationNames.EnhancedSocialInteractionImplant],O(A);const R=new r.Augmentation({name:o.AugmentationNames.BitWire,repCost:1500,moneyCost:2e6,info:"A small brain implant embedded in the cerebrum. This regulates and improves the brain's computing capabilities.

    This augmentation increases the player's hacking skill by 5%.",hacking_mult:1.05});R.addToFactions(["CyberSec","NiteSec"]),x(o.AugmentationNames.BitWire)&&delete a.Augmentations[o.AugmentationNames.BitWire],O(R);const N=new r.Augmentation({name:o.AugmentationNames.ArtificialBioNeuralNetwork,repCost:11e4,moneyCost:6e8,info:"A network consisting of millions of nanoprocessors is embedded into the brain. The network is meant to mimick the way a biological brain solves a problem, which each nanoprocessor acting similar to the way a neuron would in a neural network. However, these nanoprocessors are programmed to perform computations much faster than organic neurons, allowing its user to solve much more complex problems at a much faster rate.

    This augmentation:
    Increases the player's hacking speed by 3%.
    Increases the amount of money the player's gains from hacking by 15%.
    Increases the player's hacking skill by 12%.",hacking_speed_mult:1.03,hacking_money_mult:1.15,hacking_mult:1.12});N.addToFactions(["BitRunners","Fulcrum Secret Technologies"]),x(o.AugmentationNames.ArtificialBioNeuralNetwork)&&delete a.Augmentations[o.AugmentationNames.ArtificialBioNeuralNetwork],O(N);const D=new r.Augmentation({name:o.AugmentationNames.ArtificialSynapticPotentiation,repCost:2500,moneyCost:16e6,info:"The body is injected with a chemical that artificially induces synaptic potentiation, otherwise known as the strengthening of synapses. This results in a enhanced cognitive abilities.

    This augmentation:
    Increases the player's hacking speed by 2%
    Increases the player's hacking chance by 5%.
    Increases the player's hacking experience gain rate by 5%.",hacking_speed_mult:1.02,hacking_chance_mult:1.05,hacking_exp_mult:1.05});D.addToFactions(["The Black Hand","NiteSec"]),x(o.AugmentationNames.ArtificialSynapticPotentiation)&&delete a.Augmentations[o.AugmentationNames.ArtificialSynapticPotentiation],O(D);const I=new r.Augmentation({name:o.AugmentationNames.EnhancedMyelinSheathing,repCost:4e4,moneyCost:275e6,info:"Electrical signals are used to induce a new, artificial form of myelinogensis in the human body. This process results in the proliferation of new, synthetic myelin sheaths in the nervous system. These myelin sheaths can propogate neuro-signals much faster than their organic counterparts, leading to greater processing speeds and better brain function.

    This augmentation:
    Increases the player's hacking speed by 3%.
    Increases the player's hacking skill by 8%.
    Increases the player's hacking experience gain rate by 10%.",hacking_speed_mult:1.03,hacking_exp_mult:1.1,hacking_mult:1.08});I.addToFactions(["Fulcrum Secret Technologies","BitRunners","The Black Hand"]),x(o.AugmentationNames.EnhancedMyelinSheathing)&&delete a.Augmentations[o.AugmentationNames.EnhancedMyelinSheathing],O(I);const B=new r.Augmentation({name:o.AugmentationNames.SynapticEnhancement,repCost:800,moneyCost:15e5,info:"A small cranial implant that continuously uses weak electric signals to stimulate the brain and induce stronger synaptic activity. This improves the user's cognitive abilities.

    This augmentation increases the player's hacking speed by 3%.",hacking_speed_mult:1.03});B.addToFactions(["CyberSec"]),x(o.AugmentationNames.SynapticEnhancement)&&delete a.Augmentations[o.AugmentationNames.SynapticEnhancement],O(B);const L=new r.Augmentation({name:o.AugmentationNames.NeuralRetentionEnhancement,repCost:8e3,moneyCost:5e7,info:"Chemical injections are used to permanently alter and strengthen the brain's neuronal circuits, strengthening its ability to retain information.

    This augmentation increases the player's hacking experience gain rate by 25%.",hacking_exp_mult:1.25});L.addToFactions(["NiteSec"]),x(o.AugmentationNames.NeuralRetentionEnhancement)&&delete a.Augmentations[o.AugmentationNames.NeuralRetentionEnhancement],O(L);const W=new r.Augmentation({name:o.AugmentationNames.DataJack,repCost:45e3,moneyCost:9e7,info:"A brain implant that provides an interface for direct, wireless communication between a computer's main memory and the mind. This implant allows the user to not only access a computer's memory, but also alter and delete it.

    This augmentation increases the amount of money the player gains from hacking by 25%.",hacking_money_mult:1.25});W.addToFactions(["BitRunners","The Black Hand","NiteSec","Chongqing","New Tokyo"]),x(o.AugmentationNames.DataJack)&&delete a.Augmentations[o.AugmentationNames.DataJack],O(W);const j=new r.Augmentation({name:o.AugmentationNames.ENM,repCost:6e3,moneyCost:5e7,info:"A thin device embedded inside the arm containing a wireless module capable of connecting to nearby networks. Once connected, the Netburner Module is capable of capturing and processing all of the traffic on that network. By itself, the Embedded Netburner Module does not do much, but a variety of very powerful upgrades can be installed that allow you to fully control the traffic on a network.

    This augmentation increases the player's hacking skill by 8%.",hacking_mult:1.08});j.addToFactions(["BitRunners","The Black Hand","NiteSec","ECorp","MegaCorp","Fulcrum Secret Technologies","NWO","Blade Industries"]),x(o.AugmentationNames.ENM)&&delete a.Augmentations[o.AugmentationNames.ENM],O(j);const F=new r.Augmentation({name:o.AugmentationNames.ENMCore,repCost:1e5,moneyCost:5e8,info:"The Core library is an implant that upgrades the firmware of the Embedded Netburner Module. This upgrade allows the Embedded Netburner Module to generate its own data on a network.

    This augmentation:
    Increases the player's hacking speed by 3%.
    Increases the amount of money the player gains from hacking by 10%.
    Increases the player's chance of successfully performing a hack by 3%.
    Increases the player's hacking experience gain rate by 7%.
    Increases the player's hacking skill by 7%.",prereqs:[o.AugmentationNames.ENM],hacking_speed_mult:1.03,hacking_money_mult:1.1,hacking_chance_mult:1.03,hacking_exp_mult:1.07,hacking_mult:1.07});F.addToFactions(["BitRunners","The Black Hand","ECorp","MegaCorp","Fulcrum Secret Technologies","NWO","Blade Industries"]),x(o.AugmentationNames.ENMCore)&&delete a.Augmentations[o.AugmentationNames.ENMCore],O(F);const U=new r.Augmentation({name:o.AugmentationNames.ENMCoreV2,repCost:4e5,moneyCost:9e8,info:"The Core V2 library is an implant that upgrades the firmware of the Embedded Netburner Module. This upgraded firmware allows the Embedded Netburner Module to control the information on a network by re-routing traffic, spoofing IP addresses, or altering the data inside network packets.

    This augmentation:
    Increases the player's hacking speed by 5%.
    Increases the amount of money the player gains from hacking by 30%.
    Increases the player's chance of successfully performing a hack by 5%.
    Increases the player's hacking experience gain rate by 15%.
    Increases the player's hacking skill by 8%.",prereqs:[o.AugmentationNames.ENMCore],hacking_speed_mult:1.05,hacking_money_mult:1.3,hacking_chance_mult:1.05,hacking_exp_mult:1.15,hacking_mult:1.08});U.addToFactions(["BitRunners","ECorp","MegaCorp","Fulcrum Secret Technologies","NWO","Blade Industries","OmniTek Incorporated","KuaiGong International"]),x(o.AugmentationNames.ENMCoreV2)&&delete a.Augmentations[o.AugmentationNames.ENMCoreV2],O(U);const H=new r.Augmentation({name:o.AugmentationNames.ENMCoreV3,repCost:7e5,moneyCost:15e8,info:"The Core V3 library is an implant that upgrades the firmware of the Embedded Netburner Module. This upgraded firmware allows the Embedded Netburner Module to seamlessly inject code into any device on a network.

    This augmentation:
    Increases the player's hacking speed by 5%.
    Increases the amount of money the player gains from hacking by 40%.
    Increases the player's chance of successfully performing a hack by 10%.
    Increases the player's hacking experience gain rate by 25%.
    Increases the player's hacking skill by 10%.",prereqs:[o.AugmentationNames.ENMCoreV2],hacking_speed_mult:1.05,hacking_money_mult:1.4,hacking_chance_mult:1.1,hacking_exp_mult:1.25,hacking_mult:1.1});H.addToFactions(["ECorp","MegaCorp","Fulcrum Secret Technologies","NWO","Daedalus","The Covenant","Illuminati"]),x(o.AugmentationNames.ENMCoreV3)&&delete a.Augmentations[o.AugmentationNames.ENMCoreV3],O(H);const G=new r.Augmentation({name:o.AugmentationNames.ENMAnalyzeEngine,repCost:25e4,moneyCost:12e8,info:"Installs the Analyze Engine for the Embedded Netburner Module, which is a CPU cluster that vastly outperforms the Netburner Module's native single-core processor.

    This augmentation increases the player's hacking speed by 10%.",prereqs:[o.AugmentationNames.ENM],hacking_speed_mult:1.1});G.addToFactions(["ECorp","MegaCorp","Fulcrum Secret Technologies","NWO","Daedalus","The Covenant","Illuminati"]),x(o.AugmentationNames.ENMAnalyzeEngine)&&delete a.Augmentations[o.AugmentationNames.ENMAnalyzeEngine],O(G);const K=new r.Augmentation({name:o.AugmentationNames.ENMDMA,repCost:4e5,moneyCost:14e8,info:"This implant installs a Direct Memory Access (DMA) controller into the Embedded Netburner Module. This allows the Module to send and receive data directly to and from the main memory of devices on a network.

    This augmentation:
    Increases the amount of money the player gains from hacking by 40%.
    Increases the player's chance of successfully performing a hack by 20%.",prereqs:[o.AugmentationNames.ENM],hacking_money_mult:1.4,hacking_chance_mult:1.2});K.addToFactions(["ECorp","MegaCorp","Fulcrum Secret Technologies","NWO","Daedalus","The Covenant","Illuminati"]),x(o.AugmentationNames.ENMDMA)&&delete a.Augmentations[o.AugmentationNames.ENMDMA],O(K);const q=new r.Augmentation({name:o.AugmentationNames.Neuralstimulator,repCost:2e4,moneyCost:6e8,info:"A cranial implant that intelligently stimulates certain areas of the brain in order to improve cognitive functions.

    This augmentation:
    Increases the player's hacking speed by 2%.
    Increases the player's chance of successfully performing a hack by 10%.
    Increases the player's hacking experience gain rate by 12%.",hacking_speed_mult:1.02,hacking_chance_mult:1.1,hacking_exp_mult:1.12});q.addToFactions(["The Black Hand","Chongqing","Sector-12","New Tokyo","Aevum","Ishima","Volhaven","Bachman & Associates","Clarke Incorporated","Four Sigma"]),x(o.AugmentationNames.Neuralstimulator)&&delete a.Augmentations[o.AugmentationNames.Neuralstimulator],O(q);const $=new r.Augmentation({name:o.AugmentationNames.NeuralAccelerator,repCost:8e4,moneyCost:35e7,info:"A microprocessor that accelerates the processing speed of biological neural networks. This is a cranial implant that is embedded inside the brain.

    This augmentation:
    Increases the player's hacking skill by 10%.
    Increases the player's hacking experience gain rate by 15%.
    Increases the amount of money the player gains from hacking by 20%.",hacking_mult:1.1,hacking_exp_mult:1.15,hacking_money_mult:1.2});$.addToFactions(["BitRunners"]),x(o.AugmentationNames.NeuralAccelerator)&&delete a.Augmentations[o.AugmentationNames.NeuralAccelerator],O($);const Y=new r.Augmentation({name:o.AugmentationNames.CranialSignalProcessorsG1,repCost:4e3,moneyCost:14e6,info:"The first generation of Cranial Signal Processors. Cranial Signal Processors are a set of specialized microprocessors that are attached to neurons in the brain. These chips process neural signals to quickly and automatically perform specific computations so that the brain doesn't have to.

    This augmentation:
    Increases the player's hacking speed by 1%.
    Increases the player's hacking skill by 5%.",hacking_speed_mult:1.01,hacking_mult:1.05});Y.addToFactions(["CyberSec"]),x(o.AugmentationNames.CranialSignalProcessorsG1)&&delete a.Augmentations[o.AugmentationNames.CranialSignalProcessorsG1],O(Y);const z=new r.Augmentation({name:o.AugmentationNames.CranialSignalProcessorsG2,repCost:7500,moneyCost:25e6,info:"The second generation of Cranial Signal Processors. Cranial Signal Processors are a set of specialized microprocessors that are attached to neurons in the brain. These chips process neural signals to quickly and automatically perform specific computations so that the brain doesn't have to.

    This augmentation:
    Increases the player's hacking speed by 2%.
    Increases the player's chance of successfully performing a hack by 5%.
    Increases the player's hacking skill by 7%.",prereqs:[o.AugmentationNames.CranialSignalProcessorsG1],hacking_speed_mult:1.02,hacking_chance_mult:1.05,hacking_mult:1.07});z.addToFactions(["CyberSec","NiteSec"]),x(o.AugmentationNames.CranialSignalProcessorsG2)&&delete a.Augmentations[o.AugmentationNames.CranialSignalProcessorsG2],O(z);const V=new r.Augmentation({name:o.AugmentationNames.CranialSignalProcessorsG3,repCost:2e4,moneyCost:11e7,info:"The third generation of Cranial Signal Processors. Cranial Signal Processors are a set of specialized microprocessors that are attached to neurons in the brain. These chips process neural signals to quickly and automatically perform specific computations so that the brain doesn't have to.

    This augmentation:
    Increases the player's hacking speed by 2%.
    Increases the amount of money the player gains from hacking by 15%.
    Increases the player's hacking skill by 9%.",prereqs:[o.AugmentationNames.CranialSignalProcessorsG2],hacking_speed_mult:1.02,hacking_money_mult:1.15,hacking_mult:1.09});V.addToFactions(["NiteSec","The Black Hand","BitRunners"]),x(o.AugmentationNames.CranialSignalProcessorsG3)&&delete a.Augmentations[o.AugmentationNames.CranialSignalProcessorsG3],O(V);const J=new r.Augmentation({name:o.AugmentationNames.CranialSignalProcessorsG4,repCost:5e4,moneyCost:22e7,info:"The fourth generation of Cranial Signal Processors. Cranial Signal Processors are a set of specialized microprocessors that are attached to neurons in the brain. These chips process neural signals to quickly and automatically perform specific computations so that the brain doesn't have to.

    This augmentation:
    Increases the player's hacking speed by 2%.
    Increases the amount of money the player gains from hacking by 20%.
    Increases the amount of money the player can inject into servers using grow() by 25%.",prereqs:[o.AugmentationNames.CranialSignalProcessorsG3],hacking_speed_mult:1.02,hacking_money_mult:1.2,hacking_grow_mult:1.25});J.addToFactions(["The Black Hand","BitRunners"]),x(o.AugmentationNames.CranialSignalProcessorsG4)&&delete a.Augmentations[o.AugmentationNames.CranialSignalProcessorsG4],O(J);const X=new r.Augmentation({name:o.AugmentationNames.CranialSignalProcessorsG5,repCost:1e5,moneyCost:45e7,info:"The fifth generation of Cranial Signal Processors. Cranial Signal Processors are a set of specialized microprocessors that are attached to neurons in the brain. These chips process neural signals to quickly and automatically perform specific computations so that the brain doesn't have to.

    This augmentation:
    Increases the player's hacking skill by 30%.
    Increases the amount of money the player gains from hacking by 25%.
    Increases the amount of money the player can inject into servers using grow() by 75%.",prereqs:[o.AugmentationNames.CranialSignalProcessorsG4],hacking_mult:1.3,hacking_money_mult:1.25,hacking_grow_mult:1.75});X.addToFactions(["BitRunners"]),x(o.AugmentationNames.CranialSignalProcessorsG5)&&delete a.Augmentations[o.AugmentationNames.CranialSignalProcessorsG5],O(X);const Q=new r.Augmentation({name:o.AugmentationNames.NeuronalDensification,repCost:75e3,moneyCost:275e6,info:"The brain is surgically re-engineered to have increased neuronal density by decreasing the neuron gap junction. Then, the body is genetically modified to enhance the production and capabilities of its neural stem cells.

    This augmentation:
    Increases the player's hacking skill by 15%.
    Increases the player's hacking experience gain rate by 10%.
    Increases the player's hacking speed by 3%.",hacking_mult:1.15,hacking_exp_mult:1.1,hacking_speed_mult:1.03});Q.addToFactions(["Clarke Incorporated"]),x(o.AugmentationNames.NeuronalDensification)&&delete a.Augmentations[o.AugmentationNames.NeuronalDensification],O(Q);const Z=new r.Augmentation({name:o.AugmentationNames.NuoptimalInjectorImplant,repCost:2e3,moneyCost:4e6,info:"This torso implant automatically injects nootropic supplements into the bloodstream to improve memory, increase focus, and provide other cognitive enhancements.

    This augmentation increases the amount of reputation the player gains when working for a company by 20%.",company_rep_mult:1.2});Z.addToFactions(["Tian Di Hui","Volhaven","New Tokyo","Chongqing","Ishima","Clarke Incorporated","Four Sigma","Bachman & Associates"]),x(o.AugmentationNames.NuoptimalInjectorImplant)&&delete a.Augmentations[o.AugmentationNames.NuoptimalInjectorImplant],O(Z);const ee=new r.Augmentation({name:o.AugmentationNames.SpeechEnhancement,repCost:1e3,moneyCost:25e5,info:"An advanced neural implant that improves your speaking abilities, making you more convincing and likable in conversations and overall improving your social interactions.

    This augmentation:
    Increases the player's charisma by 10%.
    Increases the amount of reputation the player gains when working for a company by 10%.",company_rep_mult:1.1,charisma_mult:1.1});ee.addToFactions(["Tian Di Hui","Speakers for the Dead","Four Sigma","KuaiGong International","Clarke Incorporated","Bachman & Associates"]),x(o.AugmentationNames.SpeechEnhancement)&&delete a.Augmentations[o.AugmentationNames.SpeechEnhancement],O(ee);const te=new r.Augmentation({name:o.AugmentationNames.FocusWire,repCost:3e4,moneyCost:18e7,info:"A cranial implant that stops procrastination by blocking specific neural pathways in the brain.

    This augmentation:
    Increases all experience gains by 5%.
    Increases the amount of money the player gains from working by 20%.
    Increases the amount of reputation the player gains when working for a company by 10%.",hacking_exp_mult:1.05,strength_exp_mult:1.05,defense_exp_mult:1.05,dexterity_exp_mult:1.05,agility_exp_mult:1.05,charisma_exp_mult:1.05,company_rep_mult:1.1,work_money_mult:1.2});te.addToFactions(["Bachman & Associates","Clarke Incorporated","Four Sigma","KuaiGong International"]),x(o.AugmentationNames.FocusWire)&&delete a.Augmentations[o.AugmentationNames.FocusWire],O(te);const ne=new r.Augmentation({name:o.AugmentationNames.PCDNI,repCost:15e4,moneyCost:75e7,info:"Installs a Direct-Neural Interface jack into your arm that is compatible with most computers. Connecting to a computer through this jack allows you to interface with it using the brain's electrochemical signals.

    This augmentation:
    Increases the amount of reputation the player gains when working for a company by 30%.
    Increases the player's hacking skill by 8%.",company_rep_mult:1.3,hacking_mult:1.08});ne.addToFactions(["Four Sigma","OmniTek Incorporated","ECorp","Blade Industries"]),x(o.AugmentationNames.PCDNI)&&delete a.Augmentations[o.AugmentationNames.PCDNI],O(ne);const re=new r.Augmentation({name:o.AugmentationNames.PCDNIOptimizer,repCost:2e5,moneyCost:9e8,info:"This is a submodule upgrade to the PC Direct-Neural Interface augmentation. It improves the performance of the interface and gives the user more control options to the connected computer.

    This augmentation:
    Increases the amount of reputation the player gains when working for a company by 75%.
    Increases the player's hacking skill by 10%.",prereqs:[o.AugmentationNames.PCDNI],company_rep_mult:1.75,hacking_mult:1.1});re.addToFactions(["Fulcrum Secret Technologies","ECorp","Blade Industries"]),x(o.AugmentationNames.PCDNIOptimizer)&&delete a.Augmentations[o.AugmentationNames.PCDNIOptimizer],O(re);const ae=new r.Augmentation({name:o.AugmentationNames.PCDNINeuralNetwork,repCost:6e5,moneyCost:15e8,info:"This is an additional installation that upgrades the functionality of the PC Direct-Neural Interface augmentation. When connected to a computer, The NeuroNet Injector upgrade allows the user to use his/her own brain's processing power to aid the computer in computational tasks.

    This augmentation:
    Increases the amount of reputation the player gains when working for a company by 100%.
    Increases the player's hacking skill by 10%.
    Increases the player's hacking speed by 5%.",prereqs:[o.AugmentationNames.PCDNI],company_rep_mult:2,hacking_mult:1.1,hacking_speed_mult:1.05});ae.addToFactions(["Fulcrum Secret Technologies"]),x(o.AugmentationNames.PCDNINeuralNetwork)&&delete a.Augmentations[o.AugmentationNames.PCDNINeuralNetwork],O(ae);const ie=new r.Augmentation({name:o.AugmentationNames.ADRPheromone1,repCost:1500,moneyCost:35e5,info:"The body is genetically re-engineered so that it produces the ADR-V1 pheromone, an artificial pheromone discovered by scientists. The ADR-V1 pheromone, when excreted, triggers feelings of admiration and approval in other people.

    This augmentation:
    Increases the amount of reputation the player gains when working for a company by 10%
    Increases the amount of reputation the player gains for a faction by 10%.",company_rep_mult:1.1,faction_rep_mult:1.1});ie.addToFactions(["Tian Di Hui","The Syndicate","NWO","MegaCorp","Four Sigma"]),x(o.AugmentationNames.ADRPheromone1)&&delete a.Augmentations[o.AugmentationNames.ADRPheromone1],O(ie);const oe=new r.Augmentation({name:o.AugmentationNames.ADRPheromone2,repCost:25e3,moneyCost:11e7,info:"The body is genetically re-engineered so that it produces the ADR-V2 pheromone, which is similar to but more potent than ADR-V1. This pheromone, when excreted, triggers feelings of admiration, approval, and respect in others.

    This augmentation:
    Increases the amount of reputation the player gains for a faction and company by 20%.",company_rep_mult:1.2,faction_rep_mult:1.2});oe.addToFactions(["Silhouette","Four Sigma","Bachman & Associates","Clarke Incorporated"]),x(o.AugmentationNames.ADRPheromone2)&&delete a.Augmentations[o.AugmentationNames.ADRPheromone2],O(oe);const se=new r.Augmentation({name:o.AugmentationNames.ShadowsSimulacrum,repCost:15e3,moneyCost:8e7,info:"A crude but functional matter phase-shifter module that is embedded in the brainstem and cerebellum. This augmentation was developed by criminal organizations and allows the user to project and control holographic simulacrums within a large radius. These simulacrums are commonly used for espionage and surveillance work.

    This augmentation:
    Increases the amount of reputation the player gains when working for a faction or company by 15%.",company_rep_mult:1.15,faction_rep_mult:1.15});se.addToFactions(["The Syndicate","The Dark Army","Speakers for the Dead"]),x(o.AugmentationNames.ShadowsSimulacrum)&&delete a.Augmentations[o.AugmentationNames.ShadowsSimulacrum],O(se);const le=new r.Augmentation({name:o.AugmentationNames.HacknetNodeCPUUpload,repCost:1500,moneyCost:22e5,info:"Uploads the architecture and design details of a Hacknet Node's CPU into the brain. This allows the user to engineer custom hardware and software for the Hacknet Node that provides better performance.

    This augmentation:
    Increases the amount of money produced by Hacknet Nodes by 15%.
    Decreases the cost of purchasing a Hacknet Node by 15%.",hacknet_node_money_mult:1.15,hacknet_node_purchase_cost_mult:.85});le.addToFactions(["Netburners"]),x(o.AugmentationNames.HacknetNodeCPUUpload)&&delete a.Augmentations[o.AugmentationNames.HacknetNodeCPUUpload],O(le);const ce=new r.Augmentation({name:o.AugmentationNames.HacknetNodeCacheUpload,repCost:1e3,moneyCost:11e5,info:"Uploads the architecture and design details of a Hacknet Node's main-memory cache into the brain. This allows the user to engineer custom cache hardware for the Hacknet Node that offers better performance.

    This augmentation:
    Increases the amount of money produced by Hacknet Nodes by 10%.
    Decreases the cost of leveling up a Hacknet Node by 15%.",hacknet_node_money_mult:1.1,hacknet_node_level_cost_mult:.85});ce.addToFactions(["Netburners"]),x(o.AugmentationNames.HacknetNodeCacheUpload)&&delete a.Augmentations[o.AugmentationNames.HacknetNodeCacheUpload],O(ce);const ue=new r.Augmentation({name:o.AugmentationNames.HacknetNodeNICUpload,repCost:750,moneyCost:9e5,info:"Uploads the architecture and design details of a Hacknet Node's Network Interface Card (NIC) into the brain. This allows the user to engineer a custom NIC for the Hacknet Node that offers better performance.

    This augmentation:
    Increases the amount of money produced by Hacknet Nodes by 10%.
    Decreases the cost of purchasing a Hacknet Node by 10%.",hacknet_node_money_mult:1.1,hacknet_node_purchase_cost_mult:.9});ue.addToFactions(["Netburners"]),x(o.AugmentationNames.HacknetNodeNICUpload)&&delete a.Augmentations[o.AugmentationNames.HacknetNodeNICUpload],O(ue);const me=new r.Augmentation({name:o.AugmentationNames.HacknetNodeKernelDNI,repCost:3e3,moneyCost:8e6,info:"Installs a Direct-Neural Interface jack into the arm that is capable of connecting to a Hacknet Node. This lets the user access and manipulate the Node's kernel using the mind's electrochemical signals.

    This augmentation increases the amount of money produced by Hacknet Nodes by 25%.",hacknet_node_money_mult:1.25});me.addToFactions(["Netburners"]),x(o.AugmentationNames.HacknetNodeKernelDNI)&&delete a.Augmentations[o.AugmentationNames.HacknetNodeKernelDNI],O(me);const pe=new r.Augmentation({name:o.AugmentationNames.HacknetNodeCoreDNI,repCost:5e3,moneyCost:12e6,info:"Installs a Direct-Neural Interface jack into the arm that is capable of connecting to a Hacknet Node. This lets the user access and manipulate the Node's processing logic using the mind's electrochemical signals.

    This augmentation increases the amount of money produced by Hacknet Nodes by 45%.",hacknet_node_money_mult:1.45});pe.addToFactions(["Netburners"]),x(o.AugmentationNames.HacknetNodeCoreDNI)&&delete a.Augmentations[o.AugmentationNames.HacknetNodeCoreDNI],O(pe);const he=new r.Augmentation({name:o.AugmentationNames.NeuroFluxGovernor,repCost:500,moneyCost:75e4,info:"A device that is embedded in the back of the neck. The NeuroFlux Governor monitors and regulates nervous impulses coming to and from the spinal column, essentially 'governing' the body. By doing so, it improves the functionality of the body's nervous system.

    This is a special augmentation because it can be leveled up infinitely. Each level of this augmentation increases ALL of the player's multipliers by 1%.",hacking_chance_mult:1.01,hacking_speed_mult:1.01,hacking_money_mult:1.01,hacking_grow_mult:1.01,hacking_mult:1.01,strength_mult:1.01,defense_mult:1.01,dexterity_mult:1.01,agility_mult:1.01,charisma_mult:1.01,hacking_exp_mult:1.01,strength_exp_mult:1.01,defense_exp_mult:1.01,dexterity_exp_mult:1.01,agility_exp_mult:1.01,charisma_exp_mult:1.01,company_rep_mult:1.01,faction_rep_mult:1.01,crime_money_mult:1.01,crime_success_mult:1.01,hacknet_node_money_mult:1.01,hacknet_node_purchase_cost_mult:.99,hacknet_node_ram_cost_mult:.99,hacknet_node_core_cost_mult:.99,hacknet_node_level_cost_mult:.99,work_money_mult:1.01});let de=0;for(let e=0;e
    This augmentation increases the player's experience gain rate for all stats by 10%.",hacking_exp_mult:1.1,strength_exp_mult:1.1,defense_exp_mult:1.1,dexterity_exp_mult:1.1,agility_exp_mult:1.1,charisma_exp_mult:1.1});ye.addToFactions(["CyberSec"]),x(o.AugmentationNames.Neurotrainer1)&&delete a.Augmentations[o.AugmentationNames.Neurotrainer1],O(ye);const fe=new r.Augmentation({name:o.AugmentationNames.Neurotrainer2,repCost:4e3,moneyCost:9e6,info:"A decentralized cranial implant that improves the brain's ability to learn. This is a more powerful version of the Neurotrainer I augmentation, but it does not require Neurotrainer I to be installed as a prerequisite.

    This augmentation increases the player's experience gain rate for all stats by 15%.",hacking_exp_mult:1.15,strength_exp_mult:1.15,defense_exp_mult:1.15,dexterity_exp_mult:1.15,agility_exp_mult:1.15,charisma_exp_mult:1.15});fe.addToFactions(["BitRunners","NiteSec"]),x(o.AugmentationNames.Neurotrainer2)&&delete a.Augmentations[o.AugmentationNames.Neurotrainer2],O(fe);const be=new r.Augmentation({name:o.AugmentationNames.Neurotrainer3,repCost:1e4,moneyCost:26e6,info:"A decentralized cranial implant that improves the brain's ability to learn. This is a more powerful version of the Neurotrainer I and Neurotrainer II augmentation, but it does not require either of them to be installed as a prerequisite.

    This augmentation increases the player's experience gain rate for all stats by 20%.",hacking_exp_mult:1.2,strength_exp_mult:1.2,defense_exp_mult:1.2,dexterity_exp_mult:1.2,agility_exp_mult:1.2,charisma_exp_mult:1.2});be.addToFactions(["NWO","Four Sigma"]),x(o.AugmentationNames.Neurotrainer3)&&delete a.Augmentations[o.AugmentationNames.Neurotrainer3],O(be);const Ee=new r.Augmentation({name:o.AugmentationNames.Hypersight,repCost:6e4,moneyCost:55e7,info:"A bionic eye implant that grants sight capabilities far beyond those of a natural human. Embedded circuitry within the implant provides the ability to detect heat and movement through solid objects such as wells, thus providing 'x-ray vision'-like capabilities.

    This augmentation:
    Increases the player's dexterity by 40%.
    Increases the player's hacking speed by 3%.
    Increases the amount of money the player gains from hacking by 10%.",dexterity_mult:1.4,hacking_speed_mult:1.03,hacking_money_mult:1.1});Ee.addToFactions(["Blade Industries","KuaiGong International"]),x(o.AugmentationNames.Hypersight)&&delete a.Augmentations[o.AugmentationNames.Hypersight],O(Ee);const ve=new r.Augmentation({name:o.AugmentationNames.LuminCloaking1,repCost:600,moneyCost:1e6,info:"A skin implant that reinforces the skin with highly-advanced synthetic cells. These cells, when powered, have a negative refractive index. As a result, they bend light around the skin, making the user much harder to see from the naked eye.

    This augmentation:
    Increases the player's agility by 5%
    Increases the amount of money the player gains from crimes by 10%.",agility_mult:1.05,crime_money_mult:1.1});ve.addToFactions(["Slum Snakes","Tetrads"]),x(o.AugmentationNames.LuminCloaking1)&&delete a.Augmentations[o.AugmentationNames.LuminCloaking1],O(ve);const ke=new r.Augmentation({name:o.AugmentationNames.LuminCloaking2,repCost:2e3,moneyCost:6e6,info:"This is a more advanced version of the LuminCloaking-V2 augmentation. This skin implant reinforces the skin with highly-advanced synthetic cells. These cells, when powered, are capable of not only bending light but also of bending heat, making the user more resilient as well as stealthy.

    This augmentation:
    Increases the player's agility by 10%
    Increases the player's defense by 10%
    Increases the amount of money the player gains from crimes by 25%.",prereqs:[o.AugmentationNames.LuminCloaking1],agility_mult:1.1,defense_mult:1.1,crime_money_mult:1.25});ke.addToFactions(["Slum Snakes","Tetrads"]),x(o.AugmentationNames.LuminCloaking2)&&delete a.Augmentations[o.AugmentationNames.LuminCloaking2],O(ke);const Ce=new r.Augmentation({name:o.AugmentationNames.SmartSonar,repCost:9e3,moneyCost:15e6,info:"A cochlear implant that helps the player detect and locate enemies using sound propagation.

    This augmentation:
    Increases the player's dexterity by 10%.
    Increases the player's dexterity experience gain rate by 15%.
    Increases the amount of money the player gains from crimes by 25%.",dexterity_mult:1.1,dexterity_exp_mult:1.15,crime_money_mult:1.25});Ce.addToFactions(["Slum Snakes"]),x(o.AugmentationNames.SmartSonar)&&delete a.Augmentations[o.AugmentationNames.SmartSonar],O(Ce);const Oe=new r.Augmentation({name:o.AugmentationNames.PowerRecirculator,repCost:1e4,moneyCost:36e6,info:"The body's nerves are attached with polypyrrole nanocircuits that are capable of capturing wasted energy (in the form of heat) and converting it back into usable power.

    This augmentation:
    Increases all of the player's stats by 5%.
    Increases the player's experience gain rate for all stats by 10%.",hacking_mult:1.05,strength_mult:1.05,defense_mult:1.05,dexterity_mult:1.05,agility_mult:1.05,charisma_mult:1.05,hacking_exp_mult:1.1,strength_exp_mult:1.1,defense_exp_mult:1.1,dexterity_exp_mult:1.1,agility_exp_mult:1.1,charisma_exp_mult:1.1});Oe.addToFactions(["Tetrads","The Dark Army","The Syndicate","NWO"]),x(o.AugmentationNames.PowerRecirculator)&&delete a.Augmentations[o.AugmentationNames.PowerRecirculator],O(Oe);const Pe=new r.Augmentation({name:o.AugmentationNames.QLink,repCost:75e4,moneyCost:5e12,info:"A brain implant that wirelessly connects you to the Illuminati's quantum supercomputer, allowing you to access and use its incredible computing power.

    This augmentation:
    Increases the player's hacking skill by 75%.
    Increases the player's hacking speed by 100%.
    Increases the player's chance of successfully performing a hack by 150%.
    Increases the amount of money the player gains from hacking by 300%.",hacking_mult:1.75,hacking_speed_mult:2,hacking_chance_mult:2.5,hacking_money_mult:4});Pe.addToFactions(["Illuminati"]),x(o.AugmentationNames.QLink)&&delete a.Augmentations[o.AugmentationNames.QLink],O(Pe);const Se=new r.Augmentation({name:o.AugmentationNames.TheRedPill,repCost:1e6,moneyCost:0,info:"It's time to leave the cave."});Se.addToFactions(["Daedalus"]),x(o.AugmentationNames.TheRedPill)&&delete a.Augmentations[o.AugmentationNames.TheRedPill],O(Se);const Te=new r.Augmentation({name:o.AugmentationNames.SPTN97,repCost:5e5,moneyCost:975e6,info:"The SPTN-97 gene is injected into the genome. The SPTN-97 gene is an artificially-synthesized gene that was developed by DARPA to create super-soldiers through genetic modification. The gene was outlawed in 2056.

    This augmentation:
    Increases all of the player's combat stats by 75%.
    Increases the player's hacking skill by 15%.",strength_mult:1.75,defense_mult:1.75,dexterity_mult:1.75,agility_mult:1.75,hacking_mult:1.15});Te.addToFactions(["The Covenant"]),x(o.AugmentationNames.SPTN97)&&delete a.Augmentations[o.AugmentationNames.SPTN97],O(Te);const Me=new r.Augmentation({name:o.AugmentationNames.HiveMind,repCost:6e5,moneyCost:11e8,info:"A brain implant developed by ECorp. They do not reveal what exactly the implant does, but they promise that it will greatly enhance your abilities.",hacking_grow_mult:3});Me.addToFactions(["ECorp"]),x(o.AugmentationNames.HiveMind)&&delete a.Augmentations[o.AugmentationNames.HiveMind],O(Me);const xe=new r.Augmentation({name:o.AugmentationNames.CordiARCReactor,repCost:45e4,moneyCost:1e9,info:"The thoracic cavity is equipped with a small chamber designed to hold and sustain hydrogen plasma. The plasma is used to generate fusion power through nuclear fusion, providing limitless amount of clean energy for the body.

    This augmentation:
    Increases all of the player's combat stats by 35%.
    Increases all of the player's combat stat experience gain rate by 35%.",strength_mult:1.35,defense_mult:1.35,dexterity_mult:1.35,agility_mult:1.35,strength_exp_mult:1.35,defense_exp_mult:1.35,dexterity_exp_mult:1.35,agility_exp_mult:1.35});xe.addToFactions(["MegaCorp"]),x(o.AugmentationNames.CordiARCReactor)&&delete a.Augmentations[o.AugmentationNames.CordiARCReactor],O(xe);const we=new r.Augmentation({name:o.AugmentationNames.SmartJaw,repCost:15e4,moneyCost:55e7,info:"A bionic jaw that contains advanced hardware and software capable of psychoanalyzing and profiling the personality of others using optical imaging software.

    This augmentation:
    Increases the player's charisma by 50%.
    Increases the player's charisma experience gain rate by 50%.
    Increases the amount of reputation the player gains for a company by 25%.
    Increases the amount of reputation the player gains for a faction by 25%.",charisma_mult:1.5,charisma_exp_mult:1.5,company_rep_mult:1.25,faction_rep_mult:1.25});we.addToFactions(["Bachman & Associates"]),x(o.AugmentationNames.SmartJaw)&&delete a.Augmentations[o.AugmentationNames.SmartJaw],O(we);const Ae=new r.Augmentation({name:o.AugmentationNames.Neotra,repCost:225e3,moneyCost:575e6,info:"A highly-advanced techno-organic drug that is injected into the skeletal and integumentary system. The drug permanently modifies the DNA of the body's skin and bone cells, granting them the ability to repair and restructure themselves.

    This augmentation increases the player's strength and defense by 55%.",strength_mult:1.55,defense_mult:1.55});Ae.addToFactions(["Blade Industries"]),x(o.AugmentationNames.Neotra)&&delete a.Augmentations[o.AugmentationNames.Neotra],O(Ae);const Re=new r.Augmentation({name:o.AugmentationNames.Xanipher,repCost:35e4,moneyCost:85e7,info:"A concoction of advanced nanobots that is orally ingested into the body. These nanobots induce physiological change and significantly improve the body's functionining in all aspects.

    This augmentation:
    Increases all of the player's stats by 20%.
    Increases the player's experience gain rate for all stats by 15%.",hacking_mult:1.2,strength_mult:1.2,defense_mult:1.2,dexterity_mult:1.2,agility_mult:1.2,charisma_mult:1.2,hacking_exp_mult:1.15,strength_exp_mult:1.15,defense_exp_mult:1.15,dexterity_exp_mult:1.15,agility_exp_mult:1.15,charisma_exp_mult:1.15});Re.addToFactions(["NWO"]),x(o.AugmentationNames.Xanipher)&&delete a.Augmentations[o.AugmentationNames.Xanipher],O(Re);const Ne=new r.Augmentation({name:o.AugmentationNames.nextSENS,repCost:175e3,moneyCost:385e6,info:"The body is genetically re-engineered to maintain a state of negligible senescence, preventing the body from deteriorating with age.

    This augmentation increases all of the player's stats by 20%.",hacking_mult:1.2,strength_mult:1.2,defense_mult:1.2,dexterity_mult:1.2,agility_mult:1.2,charisma_mult:1.2});Ne.addToFactions(["Clarke Incorporated"]),x(o.AugmentationNames.nextSENS)&&delete a.Augmentations[o.AugmentationNames.nextSENS],O(Ne);const De=new r.Augmentation({name:o.AugmentationNames.OmniTekInfoLoad,repCost:25e4,moneyCost:575e6,info:"OmniTek's data and information repository is uploaded into your brain, enhancing your programming and hacking abilities.

    This augmentation:
    Increases the player's hacking skill by 20%.
    Increases the player's hacking experience gain rate by 25%.",hacking_mult:1.2,hacking_exp_mult:1.25});De.addToFactions(["OmniTek Incorporated"]),x(o.AugmentationNames.OmniTekInfoLoad)&&delete a.Augmentations[o.AugmentationNames.OmniTekInfoLoad],O(De);const Ie=new r.Augmentation({name:o.AugmentationNames.PhotosyntheticCells,repCost:225e3,moneyCost:55e7,info:"Chloroplasts are added to epidermal stem cells and are applied to the body using a skin graft. The result is photosynthetic skin cells, allowing users to generate their own energy and nutrition using solar power.

    This augmentation increases the player's strength, defense, and agility by 40%.",strength_mult:1.4,defense_mult:1.4,agility_mult:1.4});Ie.addToFactions(["KuaiGong International"]),x(o.AugmentationNames.PhotosyntheticCells)&&delete a.Augmentations[o.AugmentationNames.PhotosyntheticCells],O(Ie);const Be=new r.Augmentation({name:o.AugmentationNames.Neurolink,repCost:35e4,moneyCost:875e6,info:"A brain implant that provides a high-bandwidth, direct neural link between your mind and BitRunners' data servers, which reportedly contain the largest database of hacking tools and information in the world.

    This augmentation:
    Increases the player's hacking skill by 15%.
    Increases the player's hacking experience gain rate by 20%.
    Increases the player's chance of successfully performing a hack by 10%.
    Increases the player's hacking speed by 5%.
    Lets the player start with the FTPCrack.exe and relaySMTP.exe programs after a reset.",hacking_mult:1.15,hacking_exp_mult:1.2,hacking_chance_mult:1.1,hacking_speed_mult:1.05});Be.addToFactions(["BitRunners"]),x(o.AugmentationNames.Neurolink)&&delete a.Augmentations[o.AugmentationNames.Neurolink],O(Be);const Le=new r.Augmentation({name:o.AugmentationNames.TheBlackHand,repCost:4e4,moneyCost:11e7,info:"A highly advanced bionic hand. This prosthetic not only enhances strength and dexterity but it is also embedded with hardware and firmware that lets the user connect to, access and hack devices and machines just by touching them.

    This augmentation:
    Increases the player's strength and dexterity by 15%.
    Increases the player's hacking skill by 10%.
    Increases the player's hacking speed by 2%.
    Increases the amount of money the player gains from hacking by 10%.",strength_mult:1.15,dexterity_mult:1.15,hacking_mult:1.1,hacking_speed_mult:1.02,hacking_money_mult:1.1});Le.addToFactions(["The Black Hand"]),x(o.AugmentationNames.TheBlackHand)&&delete a.Augmentations[o.AugmentationNames.TheBlackHand],O(Le);const We=new r.Augmentation({name:o.AugmentationNames.CRTX42AA,repCost:18e3,moneyCost:45e6,info:"The CRTX42-AA gene is injected into the genome. The CRTX42-AA is an artificially-synthesized gene that targets the visual and prefrontal cortex and improves cognitive abilities.

    This augmentation:
    Improves the player's hacking skill by 8%.
    Improves the player's hacking experience gain rate by 15%.",hacking_mult:1.08,hacking_exp_mult:1.15});We.addToFactions(["NiteSec"]),x(o.AugmentationNames.CRTX42AA)&&delete a.Augmentations[o.AugmentationNames.CRTX42AA],O(We);const je=new r.Augmentation({name:o.AugmentationNames.Neuregen,repCost:15e3,moneyCost:75e6,info:"A drug that genetically modifies the neurons in the brain. The result is that these neurons never die and continuously regenerate and strengthen themselves.

    This augmentation increases the player's hacking experience gain rate by 40%.",hacking_exp_mult:1.4});je.addToFactions(["Chongqing"]),x(o.AugmentationNames.Neuregen)&&delete a.Augmentations[o.AugmentationNames.Neuregen],O(je);const Fe=new r.Augmentation({name:o.AugmentationNames.CashRoot,repCost:5e3,moneyCost:25e6,info:"A collection of digital assets saved on a small chip. The chip is implanted into your wrist. A small jack in the chip allows you to connect it to a computer and upload the assets.

    This augmentation:
    Lets the player start with $1,000,000 after a reset.
    Lets the player start with the BruteSSH.exe program after a reset."});Fe.addToFactions(["Sector-12"]),x(o.AugmentationNames.CashRoot)&&delete a.Augmentations[o.AugmentationNames.CashRoot],O(Fe);const Ue=new r.Augmentation({name:o.AugmentationNames.NutriGen,repCost:2500,moneyCost:5e5,info:"A thermo-powered artificial nutrition generator. Endogenously synthesizes glucose, amino acids, and vitamins and redistributes them across the body. The device is powered by the body's naturally wasted energy in the form of heat.

    This augmentation:
    Increases the player's experience gain rate for all combat stats by 20%.",strength_exp_mult:1.2,defense_exp_mult:1.2,dexterity_exp_mult:1.2,agility_exp_mult:1.2});Ue.addToFactions(["New Tokyo"]),x(o.AugmentationNames.NutriGen)&&delete a.Augmentations[o.AugmentationNames.NutriGen],O(Ue);const He=new r.Augmentation({name:o.AugmentationNames.INFRARet,repCost:3e3,moneyCost:6e6,info:"A retina implant consisting of a tiny chip that sits behind the retina. This implant lets people visually detect infrared radiation.

    This augmentation:
    Increases the player's crime success rate by 25%.
    Increases the amount of money the player gains from crimes by 10%.
    Increases the player's dexterity by 10%.",crime_success_mult:1.25,crime_money_mult:1.1,dexterity_mult:1.1});He.addToFactions(["Ishima"]),x(o.AugmentationNames.INFRARet)&&delete a.Augmentations[o.AugmentationNames.INFRARet],O(He);const Ge=new r.Augmentation({name:o.AugmentationNames.DermaForce,repCost:6e3,moneyCost:1e7,info:"A synthetic skin is grafted onto the body. The skin consists of millions of nanobots capable of projecting high-density muon beams, creating an energy barrier around the user.

    This augmentation increases the player's defense by 40%.",defense_mult:1.4});Ge.addToFactions(["Volhaven"]),x(o.AugmentationNames.DermaForce)&&delete a.Augmentations[o.AugmentationNames.DermaForce],O(Ge);const Ke=new r.Augmentation({name:o.AugmentationNames.GrapheneBrachiBlades,repCost:9e4,moneyCost:5e8,info:"An upgrade to the BrachiBlades augmentation. It infuses the retractable blades with an advanced graphene material to make them much stronger and lighter.

    This augmentation:
    Increases the player's strength and defense by 40%.
    Increases the player's crime success rate by 10%.
    Increases the amount of money the player gains from crimes by 30%.",prereqs:[o.AugmentationNames.BrachiBlades],strength_mult:1.4,defense_mult:1.4,crime_success_mult:1.1,crime_money_mult:1.3});Ke.addToFactions(["Speakers for the Dead"]),x(o.AugmentationNames.GrapheneBrachiBlades)&&delete a.Augmentations[o.AugmentationNames.GrapheneBrachiBlades],O(Ke);const qe=new r.Augmentation({name:o.AugmentationNames.GrapheneBionicArms,repCost:2e5,moneyCost:75e7,info:"An upgrade to the Bionic Arms augmentation. It infuses the prosthetic arms with an advanced graphene material to make them much stronger and lighter.

    This augmentation increases the player's strength and dexterity by 85%.",prereqs:[o.AugmentationNames.BionicArms],strength_mult:1.85,dexterity_mult:1.85});qe.addToFactions(["The Dark Army"]),x(o.AugmentationNames.GrapheneBionicArms)&&delete a.Augmentations[o.AugmentationNames.GrapheneBionicArms],O(qe);const $e=new r.Augmentation({name:o.AugmentationNames.BrachiBlades,repCost:5e3,moneyCost:18e6,info:"A set of retractable plasteel blades are implanted in the arm, underneath the skin.

    This augmentation:
    Increases the player's strength and defense by 15%.
    Increases the player's crime success rate by 10%.
    Increases the amount of money the player gains from crimes by 15%.",strength_mult:1.15,defense_mult:1.15,crime_success_mult:1.1,crime_money_mult:1.15});$e.addToFactions(["The Syndicate"]),x(o.AugmentationNames.BrachiBlades)&&delete a.Augmentations[o.AugmentationNames.BrachiBlades],O($e);const Ye=new r.Augmentation({name:o.AugmentationNames.BionicArms,repCost:25e3,moneyCost:55e6,info:"Cybernetic arms created from plasteel and carbon fibers that completely replace the user's organic arms.

    This augmentation increases the user's strength and dexterity by 30%.",strength_mult:1.3,dexterity_mult:1.3});Ye.addToFactions(["Tetrads"]),x(o.AugmentationNames.BionicArms)&&delete a.Augmentations[o.AugmentationNames.BionicArms],O(Ye);const ze=new r.Augmentation({name:o.AugmentationNames.SNA,repCost:2500,moneyCost:6e6,info:"A cranial implant that affects the user's personality, making them better at negotiation in social situations.

    This augmentation:
    Increases the amount of money the player earns at a company by 10%.
    Increases the amount of reputation the player gains when working for a company or faction by 15%.",work_money_mult:1.1,company_rep_mult:1.15,faction_rep_mult:1.15});ze.addToFactions(["Tian Di Hui"]),x(o.AugmentationNames.SNA)&&delete a.Augmentations[o.AugmentationNames.SNA],O(ze);if(Object(u.factionExists)("Bladeburners")){const e=new r.Augmentation({name:o.AugmentationNames.EsperEyewear,repCost:500,moneyCost:33e6,info:"Ballistic-grade protective and retractable eyewear that was designed specially for Bladeburner units. This is implanted by installing a mechanical frame in the skull's orbit. This frame interfaces with the brain and allows the user to automatically extrude and extract the eyewear. The eyewear protects against debris, shrapnel, laser, flash, and gas. It is also embedded with a data processing chip that can be programmed to display an AR HUD and assist the user in field missions.

    This augmentation:
    Increases the player's success chance in Bladeburner contracts/operations by 3%.
    Increases the player's dexterity by 5%.",bladeburner_success_chance_mult:1.03,dexterity_mult:1.05,isSpecial:!0});e.addToFactions(["Bladeburners"]),S(e);const t=new r.Augmentation({name:o.AugmentationNames.EMS4Recombination,repCost:1e3,moneyCost:55e6,info:"A DNA recombination of the EMS-4 Gene. This genetic engineering technique was originally used on Bladeburners during the Synthoid uprising to induce wakefulness and concentration, suppress fear, reduce empathy, and improve reflexes and memory-recall among other things.

    This augmentation:
    Increases the player's sucess chance in Bladeburner contracts/operations by 3%.
    Increases the player's effectiveness in Bladeburner Field Analysis by 5%.
    Increases the player's Bladeburner stamina gain rate by 2%.",bladeburner_success_chance_mult:1.03,bladeburner_analysis_mult:1.05,bladeburner_stamina_gain_mult:1.02,isSpecial:!0});t.addToFactions(["Bladeburners"]),S(t);const n=new r.Augmentation({name:o.AugmentationNames.OrionShoulder,repCost:2500,moneyCost:11e7,info:"A bionic shoulder augmentation for the right shoulder. Using cybernetics, the ORION-MKIV shoulder enhances the strength and dexterity of the user's right arm. It also provides protection due to its crystallized graphene plating.

    This augmentation:
    Increases the player's defense by 5%.
    Increases the player's strength and dexterity by 5%.
    Increases the player's success chance in Bladeburner contracts/operations by 4%.",defense_mult:1.05,strength_mult:1.05,dexterity_mult:1.05,bladeburner_success_chance_mult:1.04,isSpecial:!0});n.addToFactions(["Bladeburners"]),S(n);const a=new r.Augmentation({name:o.AugmentationNames.HyperionV1,repCost:5e3,moneyCost:55e7,info:"A pair of mini plasma cannons embedded into the hands. The Hyperion is capable of rapidly firing bolts of high-density plasma. The weapon is meant to be used against augmented enemies as the ionized nature of the plasma disrupts the electrical systems of Augmentations. However, it can also be effective against non-augmented enemies due to its high temperature and concussive force.

    This augmentation:
    Increases the player's success chance in Bladeburner contracts/operations by 6%.",bladeburner_success_chance_mult:1.06,isSpecial:!0});a.addToFactions(["Bladeburners"]),S(a);const i=new r.Augmentation({name:o.AugmentationNames.HyperionV2,repCost:1e4,moneyCost:11e8,info:"A pair of mini plasma cannons embedded into the hands. This augmentation is more advanced and powerful than the original V1 model. This V2 model is more power-efficiency, more accurate, and can fire plasma bolts at a much higher velocity than the V1 model.

    This augmentation:
    Increases the player's success chance in Bladeburner contracts/operations by 8%.",prereqs:[o.AugmentationNames.HyperionV1],bladeburner_success_chance_mult:1.08,isSpecial:!0});i.addToFactions(["Bladeburners"]),S(i);const s=new r.Augmentation({name:o.AugmentationNames.GolemSerum,repCost:12500,moneyCost:22e8,info:"A serum that permanently enhances many aspects of a human's capabilities, including strength, speed, immune system performance, and mitochondrial efficiency. The serum was originally developed by the Chinese military in an attempt to create super soldiers.

    This augmentation:
    Increases all of the player's combat stats by 7%.
    Increases the player's Bladeburner stamina gain rate by 5%.
    ",strength_mult:1.07,defense_mult:1.07,dexterity_mult:1.07,agility_mult:1.07,bladeburner_stamina_gain_mult:1.05,isSpecial:!0});s.addToFactions(["Bladeburners"]),S(s);const l=new r.Augmentation({name:o.AugmentationNames.VangelisVirus,repCost:7500,moneyCost:55e7,info:"A synthetic symbiotic virus that is injected into the human brain tissue. The Vangelis virus heightens the senses and focus of its host, and also enhances its intuition.

    This augmentation:
    Increases the player's effectiveness in Bladeburner Field Analysis by 10%.
    Increases the player's success chance in Bladeburner contracts/operations by 4%.
    Increases the player's dexterity experience gain rate by 10%.",dexterity_exp_mult:1.1,bladeburner_analysis_mult:1.1,bladeburner_success_chance_mult:1.04,isSpecial:!0});l.addToFactions(["Bladeburners"]),S(l);const c=new r.Augmentation({name:o.AugmentationNames.VangelisVirus3,repCost:15e3,moneyCost:22e8,info:"An improved version of Vangelis, a synthetic symbiotic virus that is injected into the human brain tissue. On top of the benefits of the original virus, this also grants an accelerated healing factor and enhanced agility/reflexes.

    This augmentation:
    Increases the player's effectiveness in Bladeburner Field Analysis by 15%.
    Increases the player's defense and dexterity experience gain rate by 10%.
    Increases the player's success chance in Bladeburner contracts/operations by 5%.",prereqs:[o.AugmentationNames.VangelisVirus],defense_exp_mult:1.1,dexterity_exp_mult:1.1,bladeburner_analysis_mult:1.15,bladeburner_success_chance_mult:1.05,isSpecial:!0});c.addToFactions(["Bladeburners"]),S(c);const u=new r.Augmentation({name:o.AugmentationNames.INTERLINKED,repCost:1e4,moneyCost:11e8,info:"The DNA is genetically modified to enhance the human's body extracellular matrix (ECM). This improves the ECM's ability to structurally support the body and grants heightened strength and durability.

    This augmentation:
    Increases the player's experience gain rate for all combat stats by 5%.
    Increases the player's Bladeburner max stamina by 10%.",strength_exp_mult:1.05,defense_exp_mult:1.05,dexterity_exp_mult:1.05,agility_exp_mult:1.05,bladeburner_max_stamina_mult:1.1,isSpecial:!0});u.addToFactions(["Bladeburners"]),S(u);const m=new r.Augmentation({name:o.AugmentationNames.BladeRunner,repCost:8e3,moneyCost:165e7,info:"A cybernetic foot augmentation that was specially created for Bladeburners during the Synthoid Uprising. The organic musculature of the human foot is enhanced with flexible carbon nanotube matrices that are controlled by intelligent servo-motors.

    This augmentation:
    Increases the player's agility by 5%.
    Increases the player's Bladeburner max stamina by 5%.
    Increases the player's Bladeburner stamina gain rate by 5%.
    ",agility_mult:1.05,bladeburner_max_stamina_mult:1.05,bladeburner_stamina_gain_mult:1.05,isSpecial:!0});m.addToFactions(["Bladeburners"]),S(m);const p=new r.Augmentation({name:o.AugmentationNames.BladeArmor,repCost:5e3,moneyCost:275e6,info:"A powered exoskeleton suit (exosuit) designed as armor for Bladeburner units. This exoskeleton is incredibly adaptable and can protect the wearer from blunt, piercing, concussive, thermal, chemical, and electric trauma. It also enhances the user's strength and agility.

    This augmentation:
    Increases all of the player's combat stats by 4%.
    Increases the player's Bladeburner stamina gain rate by 2%.
    Increases the player's success chance in Bladeburner contracts/operations by 3%.",strength_mult:1.04,defense_mult:1.04,dexterity_mult:1.04,agility_mult:1.04,bladeburner_stamina_gain_mult:1.02,bladeburner_success_chance_mult:1.03,isSpecial:!0});p.addToFactions(["Bladeburners"]),S(p);const h=new r.Augmentation({name:o.AugmentationNames.BladeArmorPowerCells,repCost:7500,moneyCost:55e7,info:"Upgrades the BLADE-51b Tesla Armor with Ion Power Cells, which are capable of more efficiently storing and using power.

    This augmentation:
    Increases the player's success chance in Bladeburner contracts/operations by 5%.
    Increases the player's Bladeburner stamina gain rate by 2%.
    Increases the player's Bladeburner max stamina by 5%.",prereqs:[o.AugmentationNames.BladeArmor],bladeburner_success_chance_mult:1.05,bladeburner_stamina_gain_mult:1.02,bladeburner_max_stamina_mult:1.05,isSpecial:!0});h.addToFactions(["Bladeburners"]),S(h);const d=new r.Augmentation({name:o.AugmentationNames.BladeArmorEnergyShielding,repCost:8500,moneyCost:11e8,info:"Upgrades the BLADE-51b Tesla Armor with a plasma energy propulsion system that is capable of projecting an energy shielding force field.

    This augmentation:
    Increases the player's defense by 5%.
    Increases the player's success chance in Bladeburner contracts/operations by 6%.",prereqs:[o.AugmentationNames.BladeArmor],defense_mult:1.05,bladeburner_success_chance_mult:1.06,isSpecial:!0});d.addToFactions(["Bladeburners"]),S(d);const g=new r.Augmentation({name:o.AugmentationNames.BladeArmorUnibeam,repCost:12500,moneyCost:33e8,info:"Upgrades the BLADE-51b Tesla Armor with a concentrated deuterium-fluoride laser weapon. It's precision an accuracy makes it useful for quickly neutralizing threats while keeping casualties to a minimum.

    This augmentation:
    Increases the player's success chance in Bladeburner contracts/operations by 8%.",prereqs:[o.AugmentationNames.BladeArmor],bladeburner_success_chance_mult:1.08,isSpecial:!0});g.addToFactions(["Bladeburners"]),S(g);const _=new r.Augmentation({name:o.AugmentationNames.BladeArmorOmnibeam,repCost:25e3,moneyCost:55e8,info:"Upgrades the BLADE-51b Tesla Armor Unibeam augmentation to use multiple-fiber system. The upgraded weapon uses multiple fiber laser modules that combine together to form a single, more powerful beam of up to 2000MW.

    This augmentation:
    Increases the player's success chance in Bladeburner contracts/operations by 10%.",prereqs:[o.AugmentationNames.BladeArmorUnibeam],bladeburner_success_chance_mult:1.1,isSpecial:!0});_.addToFactions(["Bladeburners"]),S(_);const y=new r.Augmentation({name:o.AugmentationNames.BladeArmorIPU,repCost:6e3,moneyCost:22e7,info:"Upgrades the BLADE-51b Tesla Armor with an AI Information Processing Unit that was specially designed to analyze Synthoid related data and information.

    This augmentation:
    Increases the player's effectiveness in Bladeburner Field Analysis by 15%.
    Increases the player's success chance in Bladeburner contracts/operations by 2%.",prereqs:[o.AugmentationNames.BladeArmor],bladeburner_analysis_mult:1.15,bladeburner_success_chance_mult:1.02,isSpecial:!0});y.addToFactions(["Bladeburners"]),S(y);const f=new r.Augmentation({name:o.AugmentationNames.BladesSimulacrum,repCost:500,moneyCost:3e10,info:"A highly-advanced matter phase-shifter module that is embedded in the brainstem and cerebellum. This augmentation allows the user to project and control a holographic simulacrum within an extremely large radius. These specially-modified holograms were specially weaponized by Bladeburner units to be used against Synthoids.

    This augmentation allows you to perform Bladeburner actions and other actions (such as working, commiting crimes, etc.) at the same time.",isSpecial:!0});f.addToFactions(["Bladeburners"]),S(f)}for(var e in _e=Math.pow(c.CONSTANTS.MultipleAugMultiplier,p.Player.queuedAugmentations.length),a.Augmentations)a.Augmentations.hasOwnProperty(e)&&(a.Augmentations[e].baseCost*=_e);p.Player.reapplyAllAugmentations()}function S(e){if(!(e instanceof r.Augmentation))throw new Error("Invalid argument 'newAugObject' passed into resetAugmentation");var t=e.name;x(t)&&delete a.Augmentations[t],O(e)}function T(e,t=!1){a.Augmentations[e.name].owned=!0;const n=a.Augmentations[e.name];for(const e in n.mults)null==p.Player[e]?console.warn(`Augmentation has unrecognized multiplier property: ${e}`):p.Player[e]*=n.mults[e];if(e.name===o.AugmentationNames.NeuroFluxGovernor&&!t){a.Augmentations[e.name].level=e.level;for(let t=0;t"):console.log("ERROR. Invalid augmentation")}if(p.Player.queuedAugmentations=[],Object(y.dialogBoxCreate)("You slowly drift to sleep as scientists put you under in order to install the following Augmentations:
    "+t+"
    You wake up in your home...you feel different..."),Object(h.a)(),e&&Object(b.isString)(e)){var i=p.Player.getHomeComputer();for(const t of i.scripts)if(t.filename===e){if(t.ramUsage>i.maxRam-i.ramUsed)return;const e=new g.RunningScript(t,[]);e.threads=1,Object(m.e)(e,i)}}}function x(e){return a.Augmentations.hasOwnProperty(e)}function w(e){_.routing.isOn(_.Page.Augmentations)&&e instanceof HTMLElement&&C.a.render(v.a.createElement(s.AugmentationsRoot,{exportGameFn:d.b.exportGame.bind(d.b),installAugmentationsFn:M}),e)}function A(e){return(e instanceof r.Augmentation?e.name:e)===o.AugmentationNames.NeuroFluxGovernor}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});const r=n(8),a=n(257),i=n(18);class o{constructor(e=""){this.alreadyInvited=!1,this.augmentations=[],this.favor=0,this.isBanned=!1,this.isMember=!1,this.name="",this.playerReputation=0,this.rolloverRep=0,this.name=e}static fromJSON(e){return i.Generic_fromJSON(o,e.data)}getInfo(){const e=a.FactionInfos[this.name];if(null==e)throw new Error(`Missing faction from FactionInfos: ${this.name} this probably means the faction got corrupted somehow`);return e}gainFavor(){null==this.favor&&(this.favor=0),null==this.rolloverRep&&(this.rolloverRep=0);const e=this.getFavorGain();2===e.length?(this.favor+=e[0],this.rolloverRep=e[1]):console.error("Invalid result from getFavorGain() function")}getFavorGain(){null==this.favor&&(this.favor=0),null==this.rolloverRep&&(this.rolloverRep=0);var e=0,t=this.playerReputation+this.rolloverRep;let n=r.CONSTANTS.FactionReputationToFavorBase*Math.pow(r.CONSTANTS.FactionReputationToFavorMult,this.favor);for(;t>0&&t>=n;)++e,t-=n,n*=r.CONSTANTS.FactionReputationToFavorMult;return[e,t]}toJSON(){return i.Generic_toJSON("Faction",this)}}t.Faction=o,i.Reviver.constructors.Faction=o},function(e,t,n){"use strict";n.d(t,"a",function(){return f}),n.d(t,"b",function(){return _}),n.d(t,"e",function(){return g}),n.d(t,"d",function(){return b}),n.d(t,"c",function(){return v});var r=n(65),a=(n(17),n(11)),i=n(4),o=n(33),s=n(71),l=n(0),c=n(80),u=n(23),m=n(19),p=n(9),h=n(18);function d(e,t=!1){e.recvd=!0,!t&&m.Settings.SuppressMessages||g(e),function(e,t){var n=Object(u.GetServerByHostname)(t);if(null==n)return void console.warn(`Could not find server ${t}`);for(var r=0;r

    This message was saved as "+e.filename+" onto your home computer.";Object(p.dialogBoxCreate)(t)}function _(){var e=f[E.Jumper0],t=f[E.Jumper1],n=f[E.Jumper2],r=f[E.Jumper3],u=f[E.Jumper4],m=f[E.CyberSecTest],h=f[E.NiteSecTest],g=f[E.BitRunnersTest],_=f[E.RedPill],y=!1;if(a.Augmentations[i.AugmentationNames.TheRedPill].owned&&(y=!0),_&&y&&0===l.Player.sourceFiles.length&&!c.b&&!s.c)p.dialogBoxOpened||d(_,!0);else if(_&&y)c.b||s.c||p.dialogBoxOpened||d(_);else if(e&&!e.recvd&&l.Player.hacking_skill>=25){d(e);const t=o.Programs.Flight.name,n=l.Player.getHomeComputer();n.programs.includes(t)||n.programs.push(t)}else t&&!t.recvd&&l.Player.hacking_skill>=40?d(t):m&&!m.recvd&&l.Player.hacking_skill>=50?d(m):n&&!n.recvd&&l.Player.hacking_skill>=175?d(n):h&&!h.recvd&&l.Player.hacking_skill>=200?d(h):r&&!r.recvd&&l.Player.hacking_skill>=350?d(r):u&&!u.recvd&&l.Player.hacking_skill>=490?d(u):g&&!g.recvd&&l.Player.hacking_skill>=500&&d(g)}function y(e){f[e.filename]=e}let f={};function b(e){f=JSON.parse(e,h.Reviver)}let E={Jumper0:"j0.msg",Jumper1:"j1.msg",Jumper2:"j2.msg",Jumper3:"j3.msg",Jumper4:"j4.msg",CyberSecTest:"csec-test.msg",NiteSecTest:"nitesec-test.msg",BitRunnersTest:"19dfj3l1nd.msg",RedPill:"icarus.msg"};function v(){f={},y(new r.Message(E.Jumper0,"I know you can sense it. I know you're searching for it. It's why you spend night after night at your computer.

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

    Use this program to track your progress

    The fl1ght.exe program was added to your home computer

    -jump3R")),y(new r.Message(E.Jumper1,"Soon you will be contacted by a hacking group known as CyberSec. They can help you with your search.

    You should join them, garner their favor, and exploit them for their Augmentations. But do not trust them. They are not what they seem. No one is.

    -jump3R")),y(new r.Message(E.Jumper2,"Do not try to save the world. There is no world to save. If you want to find the truth, worry only about yourself. Ethics and morals will get you killed.

    Watch out for a hacking group known as NiteSec.

    -jump3R")),y(new r.Message(E.Jumper3,"You must learn to walk before you can run. And you must run before you can fly. Look for the black hand.

    I.I.I.I

    -jump3R")),y(new r.Message(E.Jumper4,"To find what you are searching for, you must understand the bits. The bits are all around us. The runners will help you.

    -jump3R")),y(new r.Message(E.CyberSecTest,"We've been watching you. Your skills are very impressive. But you're wasting your talents. If you join us, you can put your skills to good use and change the world for the better. If you join us, we can unlock your full potential.

    But first, you must pass our test. Find and hack our server using the Terminal.

    -CyberSec")),y(new r.Message(E.NiteSecTest,"People say that the corrupted governments and corporations rule the world. Yes, maybe they do. But do you know who everyone really fears? People like us. Because they can't hide from us. Because they can't fight shadows and ideas with bullets.

    Join us, and people will fear you, too.

    Find and hack our hidden server using the Terminal. Then, we will contact you again.

    -NiteSec")),y(new r.Message(E.BitRunnersTest,"We know what you are doing. We know what drives you. We know what you are looking for.

    We can help you find the answers.

    run4theh111z")),y(new r.Message(E.RedPill,"@)(#V%*N)@(#*)*C)@#%*)*V)@#(*%V@)(#VN%*)@#(*%
    )@B(*#%)@)M#B*%V)____FIND___#$@)#%(B*)@#(*%B)
    @_#(%_@#M(BDSPOMB__THE-CAVE_#)$(*@#$)@#BNBEGB
    DFLSMFVMV)#@($*)@#*$MV)@#(*$V)M#(*$)M@(#*VM$)"))}},function(e,t,n){"use strict";(function(e){n.d(t,"a",function(){return C}),n.d(t,"c",function(){return h}),n.d(t,"d",function(){return g}),n.d(t,"b",function(){return d});var r=n(8),a=n(14),i=n(51),o=n(0),s=n(9),l=n(7),c=n(89),u=n(16),m=n(49),p=n(30);n(656);let h=!1,d=null;function g(e,t){h=e,d=e?t:null}e(document).keydown(function(e){if(h&&d&&0!=d.selectedNode.length)switch(e.keyCode){case 65:d.actionButtons[0].click();break;case 83:d.actionButtons[1].click();break;case 87:d.actionButtons[2].click();break;case 70:d.actionButtons[3].click();break;case 82:d.actionButtons[4].click();break;case 68:d.actionButtons[5].click()}});let _={Core:"CPU Core Node",Firewall:"Firewall Node",Database:"Database Node",Spam:"Spam Node",Transfer:"Transfer Node",Shield:"Shield Node"},y="Attacking",f="Scanning",b="Weakening",E="Fortifying",v="Overflowing";function k(e,t){this.type=e,this.atk=t.atk?t.atk:0,this.def=t.def?t.def:0,this.hp=t.hp?t.hp:0,this.maxhp=this.hp,this.plyrCtrl=!1,this.enmyCtrl=!1,this.pos=[0,0],this.el=null,this.action=null,this.targetedCount=0,this.conn=null}function C(e,t){this.faction=t,this.started=!1,this.time=18e4,this.playerCores=[],this.playerNodes=[],this.playerAtk=0,this.playerDef=0,this.enemyCores=[],this.enemyDatabases=[],this.enemyNodes=[],this.enemyAtk=0,this.enemyDef=0,this.miscNodes=[],this.selectedNode=[],this.actionButtons=[],this.availablePositions=[];for(var n=0;n<8;++n)for(var a=0;a<8;++a)this.availablePositions.push([n,a]);this.map=[];for(var i=0;i<8;++i)this.map.push([null,null,null,null,null,null,null,null]);this.jsplumbinstance=null,this.difficulty=e/r.CONSTANTS.HackingMissionRepToDiffConversion+1,console.log("difficulty: "+this.difficulty),this.reward=250+e/r.CONSTANTS.HackingMissionRepToRewardConversion}function O(e){e.selectedNode.length>0&&(e.selectedNode.forEach(function(t){t.deselect(e.actionButtons)}),e.selectedNode.length=0)}k.prototype.setPosition=function(e,t){this.pos=[e,t]},k.prototype.setControlledByPlayer=function(){this.plyrCtrl=!0,this.enmyCtrl=!1,this.el&&(this.el.classList.remove("hack-mission-enemy-node"),this.el.classList.add("hack-mission-player-node"))},k.prototype.setControlledByEnemy=function(){this.plyrCtrl=!1,this.enmyCtrl=!0,this.el&&(this.el.classList.remove("hack-mission-player-node"),this.el.classList.add("hack-mission-enemy-node"))},k.prototype.select=function(e){if(!this.enmyCtrl){this.el.classList.add("hack-mission-player-node-active");for(var t=0;t(this.start(),!1));var m=document.createElement("a");m.innerHTML="Forfeit Mission (Exit)",m.classList.add("a-link-button"),m.classList.add("hack-mission-header-element"),m.style.display="inline-block",m.addEventListener("click",()=>(this.finishMission(!1),!1));var p=document.createElement("p");p.setAttribute("id","hacking-mission-timer"),p.style.display="inline-block",p.style.margin="6px";var h=document.createElement("span");h.style.display="block",h.classList.add("hack-mission-action-buttons-container");for(var d=0;d<6;++d)this.actionButtons.push(document.createElement("a")),this.actionButtons[d].style.display="inline-block",this.actionButtons[d].classList.add("a-link-button-inactive"),this.actionButtons[d].classList.add("tooltip"),this.actionButtons[d].classList.add("hack-mission-header-element"),h.appendChild(this.actionButtons[d]);this.actionButtons[0].innerText="Attack(a)";var g=document.createElement("span");g.classList.add("tooltiptexthigh"),g.innerText="Lowers the targeted node's HP. The effectiveness of this depends on this node's Attack level, your hacking level, and the opponent's defense level.",this.actionButtons[0].appendChild(g),this.actionButtons[1].innerText="Scan(s)";var k=document.createElement("span");k.classList.add("tooltiptexthigh"),k.innerText="Lowers the targeted node's defense. The effectiveness of this depends on this node's Attack level, your hacking level, and the opponent's defense level.",this.actionButtons[1].appendChild(k),this.actionButtons[2].innerText="Weaken(w)";var C=document.createElement("span");C.classList.add("tooltiptexthigh"),C.innerText="Lowers the targeted node's attack. The effectiveness of this depends on this node's Attack level, your hacking level, and the opponent's defense level.",this.actionButtons[2].appendChild(C),this.actionButtons[3].innerText="Fortify(f)";var O=document.createElement("span");O.classList.add("tooltiptexthigh"),O.innerText="Raises this node's Defense level. The effectiveness of this depends on your hacking level",this.actionButtons[3].appendChild(O),this.actionButtons[4].innerText="Overflow(r)";var P=document.createElement("span");P.classList.add("tooltiptexthigh"),P.innerText="Raises this node's Attack level but lowers its Defense level. The effectiveness of this depends on your hacking level.",this.actionButtons[4].appendChild(P),this.actionButtons[5].innerText="Drop Connection(d)";var S=document.createElement("span");S.classList.add("tooltiptexthigh"),S.innerText="Removes this Node's current connection to some target Node, if it has one. This can also be done by simply clicking the white connection line.",this.actionButtons[5].appendChild(S);var T=document.createElement("p"),M=document.createElement("p");T.style.display="inline-block",M.style.display="inline-block",T.style.color="#00ccff",M.style.color="red",T.style.margin="4px",M.style.margin="4px",T.setAttribute("id","hacking-mission-player-stats"),M.setAttribute("id","hacking-mission-enemy-stats"),h.appendChild(T),h.appendChild(M),this.actionButtons[0].addEventListener("click",()=>{this.selectedNode.length>0?this.selectedNode[0].type===_.Core&&(this.setActionButtonsActive(this.selectedNode[0].type),this.setActionButton(y,!1),this.selectedNode.forEach(function(e){e.action=y})):console.log("ERR: Pressing Action button without selected node")}),this.actionButtons[1].addEventListener("click",()=>{if(this.selectedNode.length>0){var e=this.selectedNode[0].type;e!==_.Core&&e!==_.Transfer||(this.setActionButtonsActive(e),this.setActionButton(f,!1),this.selectedNode.forEach(function(e){e.action=f}))}else console.log("ERR: Pressing Action button without selected node")}),this.actionButtons[2].addEventListener("click",()=>{if(this.selectedNode.length>0){var e=this.selectedNode[0].type;e!==_.Core&&e!==_.Transfer||(this.setActionButtonsActive(e),this.setActionButton(b,!1),this.selectedNode.forEach(function(e){e.action=b}))}else console.log("ERR: Pressing Action button without selected node")}),this.actionButtons[3].addEventListener("click",()=>{this.selectedNode.length>0?(this.setActionButtonsActive(this.selectedNode[0].type),this.setActionButton(E,!1),this.selectedNode.forEach(function(e){e.action=E})):console.log("ERR: Pressing Action button without selected node")}),this.actionButtons[4].addEventListener("click",()=>{if(this.selectedNode.length>0){var e=this.selectedNode[0].type;e!==_.Core&&e!==_.Transfer||(this.setActionButtonsActive(e),this.setActionButton(v,!1),this.selectedNode.forEach(function(e){e.action=v}))}else console.log("ERR: Pressing Action button without selected node")}),this.actionButtons[5].addEventListener("click",()=>{this.selectedNode.length>0?this.selectedNode.forEach(function(e){if(e.conn){var t=e.conn.endpoints;t[0].detachFrom(t[1])}e.action=E}):console.log("ERR: Pressing Action button without selected node")});var x=document.createElement("p");e.appendChild(a),e.appendChild(i),e.appendChild(c),e.appendChild(u),e.appendChild(m),e.appendChild(p),e.appendChild(h),e.appendChild(x)},C.prototype.setActionButtonsInactive=function(){for(var e=0;ePlayer Defense: "+Object(l.formatNumber)(this.playerDef,1),e=0;for(t=0;tEnemy Defense: "+Object(l.formatNumber)(this.enemyDef,1)},C.prototype.calculateDefenses=function(){for(var e=0,t=0;tPlayer Defense: "+Object(l.formatNumber)(this.playerDef,1),e=0;for(t=0;tEnemy Defense: "+Object(l.formatNumber)(this.enemyDef,1)},C.prototype.removeAvailablePosition=function(e,t){for(var n=0;nDef: "+Object(l.formatNumber)(e.def,1),n.innerHTML=r,t.appendChild(n),document.getElementById("hacking-mission-map").appendChild(t)},C.prototype.updateNodeDomElement=function(e){if(null!=e.el){var t,n="hacking-mission-node-"+e.pos[0]+"-"+e.pos[1],r=(document.getElementById(n),document.getElementById(n+"-txt"));switch(e.type){case _.Core:t="CPU Core
    HP: "+Object(l.formatNumber)(e.hp,1);break;case _.Firewall:t="Firewall
    HP: "+Object(l.formatNumber)(e.hp,1);break;case _.Database:t="Database
    HP: "+Object(l.formatNumber)(e.hp,1);break;case _.Spam:t="Spam
    HP: "+Object(l.formatNumber)(e.hp,1);break;case _.Transfer:t="Transfer
    HP: "+Object(l.formatNumber)(e.hp,1);break;case _.Shield:default:t="Shield
    HP: "+Object(l.formatNumber)(e.hp,1)}t+="
    Atk: "+Object(l.formatNumber)(e.atk,1)+"
    Def: "+Object(l.formatNumber)(e.def,1),e.action&&(t+="
    "+e.action),r.innerHTML=t}else console.log("ERR: Calling updateNodeDomElement on a Node without an element")},C.prototype.getNodeFromElement=function(e){var t=(Object(m.isString)(e)?e:e.id).replace("hacking-mission-node-","").split("-");if(2!=t.length)return console.log("ERROR Parsing Hacking Mission Node Id. Could not find coordinates"),null;var n=t[0],r=t[1];return isNaN(n)||isNaN(r)||n>=8||r>=8||n<0||r<0?(console.log("ERROR: Unexpected values for x and y: "+n+", "+r),null):this.map[n][r]},C.prototype.configurePlayerNodeElement=function(e){null==this.getNodeFromElement(e)&&console.log("Error getting Node object");var t=this;function n(){!function(e,t){var n=e.getNodeFromElement(t);null==n&&console.log("Error getting Node object"),n.plyrCtrl&&(O(e),n.select(e.actionButtons),e.selectedNode.push(n))}(t,e)}e.addEventListener("click",n),e.addEventListener("dblclick",function(){!function(e,t){var n=e.getNodeFromElement(t);if(null==n&&console.log("ERROR: Getting Node Object in multiselectNode()"),n.plyrCtrl){O(e);var r=n.type;r===_.Core?e.playerCores.forEach(function(t){t.select(e.actionButtons),e.selectedNode.push(t)}):e.playerNodes.forEach(function(t){t.type===r&&(t.select(e.actionButtons),e.selectedNode.push(t))})}}(t,e)}),e.firstChild&&e.firstChild.addEventListener("click",n)},C.prototype.configureEnemyNodeElement=function(e){for(var t=this.getNodeFromElement(e),n=0;n0&&this.map[t-1][n].plyrCtrl)||(!!(t<7&&this.map[t+1][n].plyrCtrl)||(!!(n>0&&this.map[t][n-1].plyrCtrl)||!!(n<7&&this.map[t][n+1].plyrCtrl)))},C.prototype.nodeReachableByEnemy=function(e){if(null==e)return!1;var t=e.pos[0],n=e.pos[1];return!!(t>0&&this.map[t-1][n].enmyCtrl)||(!!(t<7&&this.map[t+1][n].enmyCtrl)||(!!(n>0&&this.map[t][n-1].enmyCtrl)||!!(n<7&&this.map[t][n+1].enmyCtrl)))},C.prototype.start=function(){this.started=!0,this.initJsPlumb();var e=Object(p.clearEventListeners)("hack-mission-start-btn");e.classList.remove("a-link-button"),e.classList.add("a-link-button-inactive")},C.prototype.initJsPlumb=function(){var e=jsPlumb.getInstance({DragOptions:{cursor:"pointer",zIndex:2e3},PaintStyle:{gradient:{stops:[[0,"#FFFFFF"],[1,"#FFFFFF"]]},stroke:"#FFFFFF",strokeWidth:8}});this.jsplumbinstance=e;for(var t=0;t{if(!this.getNodeFromElement(e.source).enmyCtrl){var n=e.endpoints;n[0].detachFrom(n[1])}}),e.bind("connection",e=>{var t=this.getNodeFromElement(e.target);this.getNodeFromElement(e.source).enmyCtrl||(this.nodeReachable(t)?(this.getNodeFromElement(e.source).conn=e.connection,++(t=this.getNodeFromElement(e.target)).targetedCount):e.sourceEndpoint.detachFrom(e.targetEndpoint))}),e.bind("connectionDetached",(e,t)=>{this.getNodeFromElement(e.source).conn=null,this.getNodeFromElement(e.target).untarget()})},C.prototype.dropAllConnectionsFromNode=function(e){for(var t=this.jsplumbinstance.getAllConnections(),n=t.length-1;n>=0;--n)t[n].source==e.el&&t[n].endpoints[0].detachFrom(t[n].endpoints[1])},C.prototype.dropAllConnectionsToNode=function(e){for(var t=this.jsplumbinstance.getAllConnections(),n=t.length-1;n>=0;--n)t[n].target==e.el&&t[n].endpoints[0].detachFrom(t[n].endpoints[1]);e.beingTargeted=!1};var P=0;C.prototype.process=function(e=1){if(this.started&&!((P+=e)<2)){var t=!1;this.playerCores.forEach(e=>{t|=this.processNode(e,P)}),this.playerNodes.forEach(e=>{e.type!==_.Transfer&&e.type!==_.Shield&&e.type!==_.Firewall||(t|=this.processNode(e,P))}),this.enemyCores.forEach(e=>{this.enemyAISelectAction(e),t|=this.processNode(e,P)}),this.enemyNodes.forEach(e=>{e.type!==_.Transfer&&e.type!==_.Shield&&e.type!==_.Firewall||(this.enemyAISelectAction(e),t|=this.processNode(e,P))}),this.enemyDatabases.forEach(e=>{e.maxhp+=.1*P,e.hp+=.1*P}),t&&(this.calculateAttacks(),this.calculateDefenses()),0!==this.enemyDatabases.length?0!==this.playerCores.length?(this.miscNodes.forEach(e=>{e.def+=.1*P,e.maxhp+=.05*P,e.hp+=.1*P,e.hp>e.maxhp&&(e.hp=e.maxhp),this.updateNodeDomElement(e)}),this.time-=P*a.Engine._idleSpeed,this.time<=0?this.finishMission(!1):(this.updateTimer(),P=0)):this.finishMission(!1):this.finishMission(!0)}},C.prototype.processNode=function(e,t=1){if(null!=e.action){var n,a,i=null;e.conn&&(null==(i=null!=e.conn.target?this.getNodeFromElement(e.conn.target):this.getNodeFromElement(e.conn.targetId))||(i.plyrCtrl?(n=this.playerDef,a=this.enemyAtk):i.enmyCtrl?(n=this.enemyDef,a=this.playerAtk):(n=i.def,a=e.plyrCtrl?this.playerAtk:this.enemyAtk)));var s=!1,l=e.plyrCtrl,c=this.difficulty*r.CONSTANTS.HackingMissionDifficultyToHacking;switch(e.action){case y:if(null==i)break;if(null==e.conn)break;var u=this.calculateAttackDamage(a,n,l?o.Player.hacking_skill:c);i.hp-=u/5*t;break;case f:if(null==i)break;if(null==e.conn)break;var m=this.calculateScanEffect(a,n,l?o.Player.hacking_skill:c);i.def-=m/5*t,s=!0;break;case b:if(null==i)break;if(null==e.conn)break;m=this.calculateWeakenEffect(a,n,l?o.Player.hacking_skill:c);i.atk-=m/5*t,s=!0;break;case E:m=this.calculateFortifyEffect(o.Player.hacking_skill);e.def+=m/5*t,s=!0;break;case v:m=this.calculateOverflowEffect(o.Player.hacking_skill);if(e.def{0===e.targetedCount&&(e.def*=r.CONSTANTS.HackingMissionMiscDefenseIncrease)})}return this.updateNodeDomElement(e),i&&this.updateNodeDomElement(i),s}},C.prototype.enemyAISelectAction=function(e){if(null!=e)switch(e.type){case _.Core:if(null==e.conn){if(0===this.miscNodes.length){var t=Object(u.getRandomInt)(0,this.playerNodes.length-1);if(n=0===this.playerNodes.length?null:this.playerNodes[t],this.nodeReachableByEnemy(n))e.conn=this.jsplumbinstance.connect({source:e.el,target:n.el}),++n.targetedCount;else{if(t=Object(u.getRandomInt)(0,this.playerCores.length-1),0===this.playerCores.length)return;n=this.playerCores[t],this.nodeReachableByEnemy(n)&&(e.conn=this.jsplumbinstance.connect({source:e.el,target:n.el}),++n.targetedCount)}}else{t=Object(u.getRandomInt)(0,this.miscNodes.length-1);var n=this.miscNodes[t];this.nodeReachableByEnemy(n)&&(e.conn=this.jsplumbinstance.connect({source:e.el,target:n.el}),++n.targetedCount)}e.action=E}else{var r;null==(r=e.conn.target?this.getNodeFromElement(e.conn.target):this.getNodeFromElement(e.conn.targetId))&&console.log("Error getting Target node Object in enemyAISelectAction()"),r.def>this.enemyAtk+15?e.def<50?e.action=E:e.action=v:Math.abs(r.def-this.enemyAtk)<=15?e.action=f:e.action=y}break;case _.Transfer:e.def<125?e.action=E:e.action=v;break;case _.Firewall:case _.Shield:e.action=E}};C.prototype.calculateAttackDamage=function(e,t,n=0){return Math.max(.55*(e+n/80-t),1)},C.prototype.calculateScanEffect=function(e,t,n=0){return Math.max(.6*(e+n/25-.95*t),2)},C.prototype.calculateWeakenEffect=function(e,t,n=0){return Math.max(e+n/25-.95*t,2)},C.prototype.calculateFortifyEffect=function(e=0){return.9*e/130},C.prototype.calculateOverflowEffect=function(e=0){return.95*e/130},C.prototype.updateTimer=function(){var e=document.getElementById("hacking-mission-timer"),t=Math.round(this.time/1e3),n=Math.trunc(t/60);t%=60;var r=("0"+n).slice(-2)+":"+("0"+t).slice(-2);e.innerText="Time left: "+r},C.prototype.finishMission=function(e){if(h=!1,d=null,e){var t=1+this.faction.favor/100;console.log("Hacking mission base reward: "+this.reward),console.log("favorMult: "+t),console.log("rep mult: "+o.Player.faction_rep_mult);var n=this.reward*o.Player.faction_rep_mult*t;Object(s.dialogBoxCreate)("Mission won! You earned "+Object(l.formatNumber)(n,3)+" reputation with "+this.faction.name),o.Player.gainIntelligenceExp(this.difficulty*r.CONSTANTS.IntelligenceHackingMissionBaseExpGain),this.faction.playerReputation+=n}else Object(s.dialogBoxCreate)("Mission lost/forfeited! You did not gain any faction reputation.");for(var c=document.getElementById("mission-container");c.firstChild;)c.removeChild(c.firstChild);document.getElementById("mainmenu-container").style.visibility="visible",document.getElementById("character-overview-wrapper").style.visibility="visible",a.Engine.loadFactionContent(),Object(i.displayFactionContent)(this.faction.name)}}).call(this,n(85))},function(e,t,n){"use strict";n.d(t,"b",function(){return o}),n.d(t,"c",function(){return s}),n.d(t,"a",function(){return l});var r=n(0),a=n(39),i=n(5);function o(e,t,n){return`ERROR: bladeburner.${e}() failed due to an invalid action specified. `+`Type: ${t}, Name: ${n}. Note that for contracts and operations, the `+"name of the operation is case-sensitive."}function s(e,t){return`bladeburner.${e}() failed with exception: `+t}function l(e,t){const n=`${t}() failed because you do not `+"currently have access to the Bladeburner API. To access the Bladeburner APIyou must be employed at the Bladeburner division, AND you must either be in BitNode-7 or have Source-File 7.";if(!(r.Player.bladeburner instanceof a.a&&(7===r.Player.bitNodeN||r.Player.sourceFiles.some(e=>7===e.n))))throw Object(i.b)(e,n)}},function(module,__webpack_exports__,__webpack_require__){"use strict";(function($){__webpack_require__.d(__webpack_exports__,"b",function(){return postNetburnerText}),__webpack_require__.d(__webpack_exports__,"a",function(){return Terminal});var _Terminal_DirectoryHelpers__WEBPACK_IMPORTED_MODULE_0__=__webpack_require__(76),_Terminal_DirectoryHelpers__WEBPACK_IMPORTED_MODULE_0___default=__webpack_require__.n(_Terminal_DirectoryHelpers__WEBPACK_IMPORTED_MODULE_0__),_Terminal_determineAllPossibilitiesForTabCompletion__WEBPACK_IMPORTED_MODULE_1__=__webpack_require__(273),_Terminal_determineAllPossibilitiesForTabCompletion__WEBPACK_IMPORTED_MODULE_1___default=__webpack_require__.n(_Terminal_determineAllPossibilitiesForTabCompletion__WEBPACK_IMPORTED_MODULE_1__),_Terminal_HelpText__WEBPACK_IMPORTED_MODULE_2__=__webpack_require__(181),_Terminal_HelpText__WEBPACK_IMPORTED_MODULE_2___default=__webpack_require__.n(_Terminal_HelpText__WEBPACK_IMPORTED_MODULE_2__),_Terminal_tabCompletion__WEBPACK_IMPORTED_MODULE_3__=__webpack_require__(272),_Terminal_tabCompletion__WEBPACK_IMPORTED_MODULE_3___default=__webpack_require__.n(_Terminal_tabCompletion__WEBPACK_IMPORTED_MODULE_3__),_Alias__WEBPACK_IMPORTED_MODULE_4__=__webpack_require__(63),_Alias__WEBPACK_IMPORTED_MODULE_4___default=__webpack_require__.n(_Alias__WEBPACK_IMPORTED_MODULE_4__),_BitNode_BitNodeMultipliers__WEBPACK_IMPORTED_MODULE_5__=__webpack_require__(20),_BitNode_BitNodeMultipliers__WEBPACK_IMPORTED_MODULE_5___default=__webpack_require__.n(_BitNode_BitNodeMultipliers__WEBPACK_IMPORTED_MODULE_5__),_CodingContracts__WEBPACK_IMPORTED_MODULE_6__=__webpack_require__(48),_CodingContracts__WEBPACK_IMPORTED_MODULE_6___default=__webpack_require__.n(_CodingContracts__WEBPACK_IMPORTED_MODULE_6__),_Constants__WEBPACK_IMPORTED_MODULE_7__=__webpack_require__(8),_Constants__WEBPACK_IMPORTED_MODULE_7___default=__webpack_require__.n(_Constants__WEBPACK_IMPORTED_MODULE_7__),_Programs_Programs__WEBPACK_IMPORTED_MODULE_8__=__webpack_require__(33),_Programs_Programs__WEBPACK_IMPORTED_MODULE_8___default=__webpack_require__.n(_Programs_Programs__WEBPACK_IMPORTED_MODULE_8__),_DarkWeb_DarkWeb__WEBPACK_IMPORTED_MODULE_9__=__webpack_require__(208),_DarkWeb_DarkWebItems__WEBPACK_IMPORTED_MODULE_10__=__webpack_require__(99),_DarkWeb_DarkWebItems__WEBPACK_IMPORTED_MODULE_10___default=__webpack_require__.n(_DarkWeb_DarkWebItems__WEBPACK_IMPORTED_MODULE_10__),_engine__WEBPACK_IMPORTED_MODULE_11__=__webpack_require__(14),_Fconf_Fconf__WEBPACK_IMPORTED_MODULE_12__=__webpack_require__(127),_Fconf_FconfSettings__WEBPACK_IMPORTED_MODULE_13__=__webpack_require__(35),_Fconf_FconfSettings__WEBPACK_IMPORTED_MODULE_13___default=__webpack_require__.n(_Fconf_FconfSettings__WEBPACK_IMPORTED_MODULE_13__),_Hacking__WEBPACK_IMPORTED_MODULE_14__=__webpack_require__(56),_Hacknet_HacknetServer__WEBPACK_IMPORTED_MODULE_15__=__webpack_require__(34),_Hacknet_HacknetServer__WEBPACK_IMPORTED_MODULE_15___default=__webpack_require__.n(_Hacknet_HacknetServer__WEBPACK_IMPORTED_MODULE_15__),_InteractiveTutorial__WEBPACK_IMPORTED_MODULE_16__=__webpack_require__(40),_Literature__WEBPACK_IMPORTED_MODULE_17__=__webpack_require__(129),_Message_Message__WEBPACK_IMPORTED_MODULE_18__=__webpack_require__(65),_Message_Message__WEBPACK_IMPORTED_MODULE_18___default=__webpack_require__.n(_Message_Message__WEBPACK_IMPORTED_MODULE_18__),_Message_MessageHelpers__WEBPACK_IMPORTED_MODULE_19__=__webpack_require__(70),_NetscriptWorker__WEBPACK_IMPORTED_MODULE_20__=__webpack_require__(62),_Netscript_killWorkerScript__WEBPACK_IMPORTED_MODULE_21__=__webpack_require__(66),_Netscript_killWorkerScript__WEBPACK_IMPORTED_MODULE_21___default=__webpack_require__.n(_Netscript_killWorkerScript__WEBPACK_IMPORTED_MODULE_21__),_Netscript_WorkerScriptStartStopEventEmitter__WEBPACK_IMPORTED_MODULE_22__=__webpack_require__(102),_Netscript_WorkerScriptStartStopEventEmitter__WEBPACK_IMPORTED_MODULE_22___default=__webpack_require__.n(_Netscript_WorkerScriptStartStopEventEmitter__WEBPACK_IMPORTED_MODULE_22__),_Player__WEBPACK_IMPORTED_MODULE_23__=__webpack_require__(0),_RedPill__WEBPACK_IMPORTED_MODULE_24__=__webpack_require__(80),_Script_RunningScript__WEBPACK_IMPORTED_MODULE_25__=__webpack_require__(125),_Script_RunningScript__WEBPACK_IMPORTED_MODULE_25___default=__webpack_require__.n(_Script_RunningScript__WEBPACK_IMPORTED_MODULE_25__),_Script_RunningScriptHelpers__WEBPACK_IMPORTED_MODULE_26__=__webpack_require__(171),_Script_RunningScriptHelpers__WEBPACK_IMPORTED_MODULE_26___default=__webpack_require__.n(_Script_RunningScriptHelpers__WEBPACK_IMPORTED_MODULE_26__),_Script_ScriptHelpers__WEBPACK_IMPORTED_MODULE_27__=__webpack_require__(74),_Script_ScriptHelpersTS__WEBPACK_IMPORTED_MODULE_28__=__webpack_require__(60),_Script_ScriptHelpersTS__WEBPACK_IMPORTED_MODULE_28___default=__webpack_require__.n(_Script_ScriptHelpersTS__WEBPACK_IMPORTED_MODULE_28__),_Server_AllServers__WEBPACK_IMPORTED_MODULE_29__=__webpack_require__(21),_Server_AllServers__WEBPACK_IMPORTED_MODULE_29___default=__webpack_require__.n(_Server_AllServers__WEBPACK_IMPORTED_MODULE_29__),_Server_Server__WEBPACK_IMPORTED_MODULE_30__=__webpack_require__(112),_Server_Server__WEBPACK_IMPORTED_MODULE_30___default=__webpack_require__.n(_Server_Server__WEBPACK_IMPORTED_MODULE_30__),_Server_ServerHelpers__WEBPACK_IMPORTED_MODULE_31__=__webpack_require__(23),_Server_ServerHelpers__WEBPACK_IMPORTED_MODULE_31___default=__webpack_require__.n(_Server_ServerHelpers__WEBPACK_IMPORTED_MODULE_31__),_Settings_Settings__WEBPACK_IMPORTED_MODULE_32__=__webpack_require__(19),_Settings_Settings__WEBPACK_IMPORTED_MODULE_32___default=__webpack_require__.n(_Settings_Settings__WEBPACK_IMPORTED_MODULE_32__),_Server_SpecialServerIps__WEBPACK_IMPORTED_MODULE_33__=__webpack_require__(38),_Server_SpecialServerIps__WEBPACK_IMPORTED_MODULE_33___default=__webpack_require__.n(_Server_SpecialServerIps__WEBPACK_IMPORTED_MODULE_33__),_TextFile__WEBPACK_IMPORTED_MODULE_34__=__webpack_require__(96),_TextFile__WEBPACK_IMPORTED_MODULE_34___default=__webpack_require__.n(_TextFile__WEBPACK_IMPORTED_MODULE_34__),_utils_SetTimeoutRef__WEBPACK_IMPORTED_MODULE_35__=__webpack_require__(64),_utils_SetTimeoutRef__WEBPACK_IMPORTED_MODULE_35___default=__webpack_require__.n(_utils_SetTimeoutRef__WEBPACK_IMPORTED_MODULE_35__),_ui_navigationTracking__WEBPACK_IMPORTED_MODULE_36__=__webpack_require__(12),_ui_navigationTracking__WEBPACK_IMPORTED_MODULE_36___default=__webpack_require__.n(_ui_navigationTracking__WEBPACK_IMPORTED_MODULE_36__),_ui_numeralFormat__WEBPACK_IMPORTED_MODULE_37__=__webpack_require__(2),_ui_numeralFormat__WEBPACK_IMPORTED_MODULE_37___default=__webpack_require__.n(_ui_numeralFormat__WEBPACK_IMPORTED_MODULE_37__),_utils_helpers_keyCodes__WEBPACK_IMPORTED_MODULE_38__=__webpack_require__(27),_utils_helpers_keyCodes__WEBPACK_IMPORTED_MODULE_38___default=__webpack_require__.n(_utils_helpers_keyCodes__WEBPACK_IMPORTED_MODULE_38__),_utils_helpers_addOffset__WEBPACK_IMPORTED_MODULE_39__=__webpack_require__(89),_utils_helpers_addOffset__WEBPACK_IMPORTED_MODULE_39___default=__webpack_require__.n(_utils_helpers_addOffset__WEBPACK_IMPORTED_MODULE_39__),_utils_helpers_isString__WEBPACK_IMPORTED_MODULE_40__=__webpack_require__(49),_utils_helpers_isString__WEBPACK_IMPORTED_MODULE_40___default=__webpack_require__.n(_utils_helpers_isString__WEBPACK_IMPORTED_MODULE_40__),_utils_helpers_arrayToString__WEBPACK_IMPORTED_MODULE_41__=__webpack_require__(83),_utils_helpers_arrayToString__WEBPACK_IMPORTED_MODULE_41___default=__webpack_require__.n(_utils_helpers_arrayToString__WEBPACK_IMPORTED_MODULE_41__),_utils_helpers_getTimestamp__WEBPACK_IMPORTED_MODULE_42__=__webpack_require__(151),_utils_helpers_getTimestamp__WEBPACK_IMPORTED_MODULE_42___default=__webpack_require__.n(_utils_helpers_getTimestamp__WEBPACK_IMPORTED_MODULE_42__),_utils_LogBox__WEBPACK_IMPORTED_MODULE_43__=__webpack_require__(106),_utils_LogBox__WEBPACK_IMPORTED_MODULE_43___default=__webpack_require__.n(_utils_LogBox__WEBPACK_IMPORTED_MODULE_43__),_utils_YesNoBox__WEBPACK_IMPORTED_MODULE_44__=__webpack_require__(45),_utils_YesNoBox__WEBPACK_IMPORTED_MODULE_44___default=__webpack_require__.n(_utils_YesNoBox__WEBPACK_IMPORTED_MODULE_44__),_ui_postToTerminal__WEBPACK_IMPORTED_MODULE_45__=__webpack_require__(6),_ui_postToTerminal__WEBPACK_IMPORTED_MODULE_45___default=__webpack_require__.n(_ui_postToTerminal__WEBPACK_IMPORTED_MODULE_45__),autosize__WEBPACK_IMPORTED_MODULE_46__=__webpack_require__(271),autosize__WEBPACK_IMPORTED_MODULE_46___default=__webpack_require__.n(autosize__WEBPACK_IMPORTED_MODULE_46__),jszip__WEBPACK_IMPORTED_MODULE_47__=__webpack_require__(270),jszip__WEBPACK_IMPORTED_MODULE_47___default=__webpack_require__.n(jszip__WEBPACK_IMPORTED_MODULE_47__),file_saver__WEBPACK_IMPORTED_MODULE_48__=__webpack_require__(269),file_saver__WEBPACK_IMPORTED_MODULE_48___default=__webpack_require__.n(file_saver__WEBPACK_IMPORTED_MODULE_48__);function postNetburnerText(){Object(_ui_postToTerminal__WEBPACK_IMPORTED_MODULE_45__.post)("Bitburner v"+_Constants__WEBPACK_IMPORTED_MODULE_7__.CONSTANTS.Version)}function isNumber(e){return"string"==typeof e&&(!isNaN(e)&&!isNaN(parseFloat(e)))}$(document).keydown(function(e){if(_ui_navigationTracking__WEBPACK_IMPORTED_MODULE_36__.routing.isOn(_ui_navigationTracking__WEBPACK_IMPORTED_MODULE_36__.Page.Terminal)){var t=document.getElementById("terminal-input-text-box");if(null==t||e.ctrlKey||e.shiftKey||Terminal.contractOpen||t.focus(),e.keyCode===_utils_helpers_keyCodes__WEBPACK_IMPORTED_MODULE_38__.KEY.ENTER){e.preventDefault();const n=t.value,r=Terminal.currDir;Object(_ui_postToTerminal__WEBPACK_IMPORTED_MODULE_45__.post)("["+(_Fconf_FconfSettings__WEBPACK_IMPORTED_MODULE_13__.FconfSettings.ENABLE_TIMESTAMPS?Object(_utils_helpers_getTimestamp__WEBPACK_IMPORTED_MODULE_42__.getTimestamp)()+" ":"")+_Player__WEBPACK_IMPORTED_MODULE_23__.Player.getCurrentServer().hostname+` ~${r}]> ${n}`),n.length>0&&(Terminal.resetTerminalInput(),Terminal.executeCommands(n))}if(e.keyCode===_utils_helpers_keyCodes__WEBPACK_IMPORTED_MODULE_38__.KEY.C&&e.ctrlKey&&(_engine__WEBPACK_IMPORTED_MODULE_11__.Engine._actionInProgress?(Object(_ui_postToTerminal__WEBPACK_IMPORTED_MODULE_45__.post)("Cancelling..."),_engine__WEBPACK_IMPORTED_MODULE_11__.Engine._actionInProgress=!1,Terminal.finishAction(!0)):_Fconf_FconfSettings__WEBPACK_IMPORTED_MODULE_13__.FconfSettings.ENABLE_BASH_HOTKEYS&&Terminal.resetTerminalInput()),e.keyCode===_utils_helpers_keyCodes__WEBPACK_IMPORTED_MODULE_38__.KEY.L&&e.ctrlKey&&(e.preventDefault(),Terminal.executeCommand("clear")),e.keyCode===_utils_helpers_keyCodes__WEBPACK_IMPORTED_MODULE_38__.KEY.UPARROW||_Fconf_FconfSettings__WEBPACK_IMPORTED_MODULE_13__.FconfSettings.ENABLE_BASH_HOTKEYS&&e.keyCode===_utils_helpers_keyCodes__WEBPACK_IMPORTED_MODULE_38__.KEY.P&&e.ctrlKey){if(_Fconf_FconfSettings__WEBPACK_IMPORTED_MODULE_13__.FconfSettings.ENABLE_BASH_HOTKEYS&&e.preventDefault(),null==t)return;var n=Terminal.commandHistoryIndex;if(0==(a=Terminal.commandHistory.length))return;(n<0||n>a)&&(Terminal.commandHistoryIndex=a),0!=n&&--Terminal.commandHistoryIndex;var r=Terminal.commandHistory[Terminal.commandHistoryIndex];t.value=r,Object(_utils_SetTimeoutRef__WEBPACK_IMPORTED_MODULE_35__.setTimeoutRef)(function(){t.selectionStart=t.selectionEnd=1e4},0)}if(e.keyCode===_utils_helpers_keyCodes__WEBPACK_IMPORTED_MODULE_38__.KEY.DOWNARROW||_Fconf_FconfSettings__WEBPACK_IMPORTED_MODULE_13__.FconfSettings.ENABLE_BASH_HOTKEYS&&e.keyCode===_utils_helpers_keyCodes__WEBPACK_IMPORTED_MODULE_38__.KEY.M&&e.ctrlKey){if(_Fconf_FconfSettings__WEBPACK_IMPORTED_MODULE_13__.FconfSettings.ENABLE_BASH_HOTKEYS&&e.preventDefault(),null==t)return;var a;n=Terminal.commandHistoryIndex;if(0==(a=Terminal.commandHistory.length))return;if((n<0||n>a)&&(Terminal.commandHistoryIndex=a),n==a||n==a-1)Terminal.commandHistoryIndex=a,t.value="";else{++Terminal.commandHistoryIndex;r=Terminal.commandHistory[Terminal.commandHistoryIndex];t.value=r}}if(e.keyCode===_utils_helpers_keyCodes__WEBPACK_IMPORTED_MODULE_38__.KEY.TAB){if(e.preventDefault(),null==t)return;let n=t.value;if(""==n)return;const r=n.lastIndexOf(";");-1!==r&&(n=n.slice(r+1));const a=(n=(n=n.trim()).replace(/\s\s+/g," ")).split(" ");let i=a.length-2;i<-1&&(i=0);const o=Object(_Terminal_determineAllPossibilitiesForTabCompletion__WEBPACK_IMPORTED_MODULE_1__.determineAllPossibilitiesForTabCompletion)(_Player__WEBPACK_IMPORTED_MODULE_23__.Player,n,i,Terminal.currDir);if(0==o.length)return;let s="",l="";if(0==a.length)return;1==a.length?l=a[0]:2==a.length?(l=a[0],s=a[1]):3==a.length?(l=a[0]+" "+a[1],s=a[2]):(s=a.pop(),l=a.join(" ")),Object(_Terminal_tabCompletion__WEBPACK_IMPORTED_MODULE_3__.tabCompletion)(l,s,o),t.focus()}_Fconf_FconfSettings__WEBPACK_IMPORTED_MODULE_13__.FconfSettings.ENABLE_BASH_HOTKEYS&&(e.keyCode===_utils_helpers_keyCodes__WEBPACK_IMPORTED_MODULE_38__.KEY.A&&e.ctrlKey&&(e.preventDefault(),Terminal.moveTextCursor("home")),e.keyCode===_utils_helpers_keyCodes__WEBPACK_IMPORTED_MODULE_38__.KEY.E&&e.ctrlKey&&(e.preventDefault(),Terminal.moveTextCursor("end")),e.keyCode===_utils_helpers_keyCodes__WEBPACK_IMPORTED_MODULE_38__.KEY.B&&e.ctrlKey&&(e.preventDefault(),Terminal.moveTextCursor("prevchar")),e.keyCode===_utils_helpers_keyCodes__WEBPACK_IMPORTED_MODULE_38__.KEY.B&&e.altKey&&(e.preventDefault(),Terminal.moveTextCursor("prevword")),e.keyCode===_utils_helpers_keyCodes__WEBPACK_IMPORTED_MODULE_38__.KEY.F&&e.ctrlKey&&(e.preventDefault(),Terminal.moveTextCursor("nextchar")),e.keyCode===_utils_helpers_keyCodes__WEBPACK_IMPORTED_MODULE_38__.KEY.F&&e.altKey&&(e.preventDefault(),Terminal.moveTextCursor("nextword")),e.keyCode!==_utils_helpers_keyCodes__WEBPACK_IMPORTED_MODULE_38__.KEY.H&&e.keyCode!==_utils_helpers_keyCodes__WEBPACK_IMPORTED_MODULE_38__.KEY.D||!e.ctrlKey||(Terminal.modifyInput("backspace"),e.preventDefault()))}});let terminalCtrlPressed=!1,shiftKeyPressed=!1;$(document).ready(function(){_ui_navigationTracking__WEBPACK_IMPORTED_MODULE_36__.routing.isOn(_ui_navigationTracking__WEBPACK_IMPORTED_MODULE_36__.Page.Terminal)&&$(".terminal-input").focus()}),$(document).keydown(function(e){if(_ui_navigationTracking__WEBPACK_IMPORTED_MODULE_36__.routing.isOn(_ui_navigationTracking__WEBPACK_IMPORTED_MODULE_36__.Page.Terminal))if(e.which==_utils_helpers_keyCodes__WEBPACK_IMPORTED_MODULE_38__.KEY.CTRL)terminalCtrlPressed=!0;else if(e.shiftKey)shiftKeyPressed=!0;else if(terminalCtrlPressed||shiftKeyPressed||Terminal.contractOpen);else{var t=document.getElementById("terminal-input-text-box");null!=t&&t.focus(),terminalCtrlPressed=!1,shiftKeyPressed=!1}}),$(document).keyup(function(e){_ui_navigationTracking__WEBPACK_IMPORTED_MODULE_36__.routing.isOn(_ui_navigationTracking__WEBPACK_IMPORTED_MODULE_36__.Page.Terminal)&&(e.which==_utils_helpers_keyCodes__WEBPACK_IMPORTED_MODULE_38__.KEY.CTRL&&(terminalCtrlPressed=!1),e.shiftKey&&(shiftKeyPressed=!1))});let Terminal={hackFlag:!1,analyzeFlag:!1,actionStarted:!1,actionTime:0,commandHistory:[],commandHistoryIndex:0,contractOpen:!1,currDir:"/",resetTerminalInput:function(){const e=Terminal.currDir;_Fconf_FconfSettings__WEBPACK_IMPORTED_MODULE_13__.FconfSettings.WRAP_INPUT?(document.getElementById("terminal-input-td").innerHTML=`
    [${_Player__WEBPACK_IMPORTED_MODULE_23__.Player.getCurrentServer().hostname} ~${e}]$
    `+'",v.noCloneChecked=!!e.cloneNode(!0).lastChild.defaultValue}();var xe=s.documentElement,we=/^key/,Ce=/^(?:mouse|pointer|contextmenu|drag|drop)|click/,ke=/^([^.]*)(?:\.(.+)|)/;function Ee(){return!0}function Ae(){return!1}function _e(){try{return s.activeElement}catch(e){}}function Se(e,t,n,r,i,o){var s,a;if("object"==typeof t){for(a in"string"!=typeof n&&(r=r||n,n=void 0),t)Se(e,a,n,r,t[a],o);return e}if(null==r&&null==i?(i=n,r=n=void 0):null==i&&("string"==typeof n?(i=r,r=void 0):(i=r,r=n,n=void 0)),!1===i)i=Ae;else if(!i)return e;return 1===o&&(s=i,(i=function(e){return k().off(e),s.apply(this,arguments)}).guid=s.guid||(s.guid=k.guid++)),e.each(function(){k.event.add(this,t,i,r,n)})}k.event={global:{},add:function(e,t,n,r,i){var o,s,a,l,u,c,h,d,f,p,g,m=Z.get(e);if(m)for(n.handler&&(n=(o=n).handler,i=o.selector),i&&k.find.matchesSelector(xe,i),n.guid||(n.guid=k.guid++),(l=m.events)||(l=m.events={}),(s=m.handle)||(s=m.handle=function(t){return void 0!==k&&k.event.triggered!==t.type?k.event.dispatch.apply(e,arguments):void 0}),u=(t=(t||"").match(j)||[""]).length;u--;)f=g=(a=ke.exec(t[u])||[])[1],p=(a[2]||"").split(".").sort(),f&&(h=k.event.special[f]||{},f=(i?h.delegateType:h.bindType)||f,h=k.event.special[f]||{},c=k.extend({type:f,origType:g,data:r,handler:n,guid:n.guid,selector:i,needsContext:i&&k.expr.match.needsContext.test(i),namespace:p.join(".")},o),(d=l[f])||((d=l[f]=[]).delegateCount=0,h.setup&&!1!==h.setup.call(e,r,p,s)||e.addEventListener&&e.addEventListener(f,s)),h.add&&(h.add.call(e,c),c.handler.guid||(c.handler.guid=n.guid)),i?d.splice(d.delegateCount++,0,c):d.push(c),k.event.global[f]=!0)},remove:function(e,t,n,r,i){var o,s,a,l,u,c,h,d,f,p,g,m=Z.hasData(e)&&Z.get(e);if(m&&(l=m.events)){for(u=(t=(t||"").match(j)||[""]).length;u--;)if(f=g=(a=ke.exec(t[u])||[])[1],p=(a[2]||"").split(".").sort(),f){for(h=k.event.special[f]||{},d=l[f=(r?h.delegateType:h.bindType)||f]||[],a=a[2]&&new RegExp("(^|\\.)"+p.join("\\.(?:.*\\.|)")+"(\\.|$)"),s=o=d.length;o--;)c=d[o],!i&&g!==c.origType||n&&n.guid!==c.guid||a&&!a.test(c.namespace)||r&&r!==c.selector&&("**"!==r||!c.selector)||(d.splice(o,1),c.selector&&d.delegateCount--,h.remove&&h.remove.call(e,c));s&&!d.length&&(h.teardown&&!1!==h.teardown.call(e,p,m.handle)||k.removeEvent(e,f,m.handle),delete l[f])}else for(f in l)k.event.remove(e,f+t[u],n,r,!0);k.isEmptyObject(l)&&Z.remove(e,"handle events")}},dispatch:function(e){var t,n,r,i,o,s,a=k.event.fix(e),l=new Array(arguments.length),u=(Z.get(this,"events")||{})[a.type]||[],c=k.event.special[a.type]||{};for(l[0]=a,t=1;t=1))for(;u!==this;u=u.parentNode||this)if(1===u.nodeType&&("click"!==e.type||!0!==u.disabled)){for(o=[],s={},n=0;n-1:k.find(i,this,null,[u]).length),s[i]&&o.push(r);o.length&&a.push({elem:u,handlers:o})}return u=this,l\x20\t\r\n\f]*)[^>]*)\/>/gi,De=/\s*$/g;function Be(e,t){return T(e,"table")&&T(11!==t.nodeType?t:t.firstChild,"tr")&&k(e).children("tbody")[0]||e}function Me(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function Pe(e){return"true/"===(e.type||"").slice(0,5)?e.type=e.type.slice(5):e.removeAttribute("type"),e}function Re(e,t){var n,r,i,o,s,a,l,u;if(1===t.nodeType){if(Z.hasData(e)&&(o=Z.access(e),s=Z.set(t,o),u=o.events))for(i in delete s.handle,s.events={},u)for(n=0,r=u[i].length;n1&&"string"==typeof p&&!v.checkClone&&Te.test(p))return e.each(function(i){var o=e.eq(i);g&&(t[0]=p.call(this,i,o.html())),Ie(o,t,n,r)});if(d&&(o=(i=be(t,e[0].ownerDocument,!1,e,r)).firstChild,1===i.childNodes.length&&(i=o),o||r)){for(a=(s=k.map(me(i,"script"),Me)).length;h")},clone:function(e,t,n){var r,i,o,s,a=e.cloneNode(!0),l=k.contains(e.ownerDocument,e);if(!(v.noCloneChecked||1!==e.nodeType&&11!==e.nodeType||k.isXMLDoc(e)))for(s=me(a),r=0,i=(o=me(e)).length;r0&&ve(s,!l&&me(e,"script")),a},cleanData:function(e){for(var t,n,r,i=k.event.special,o=0;void 0!==(n=e[o]);o++)if(X(n)){if(t=n[Z.expando]){if(t.events)for(r in t.events)i[r]?k.event.remove(n,r):k.removeEvent(n,r,t.handle);n[Z.expando]=void 0}n[J.expando]&&(n[J.expando]=void 0)}}}),k.fn.extend({detach:function(e){return je(this,e,!0)},remove:function(e){return je(this,e)},text:function(e){return U(this,function(e){return void 0===e?k.text(this):this.empty().each(function(){1!==this.nodeType&&11!==this.nodeType&&9!==this.nodeType||(this.textContent=e)})},null,e,arguments.length)},append:function(){return Ie(this,arguments,function(e){1!==this.nodeType&&11!==this.nodeType&&9!==this.nodeType||Be(this,e).appendChild(e)})},prepend:function(){return Ie(this,arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=Be(this,e);t.insertBefore(e,t.firstChild)}})},before:function(){return Ie(this,arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this)})},after:function(){return Ie(this,arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this.nextSibling)})},empty:function(){for(var e,t=0;null!=(e=this[t]);t++)1===e.nodeType&&(k.cleanData(me(e,!1)),e.textContent="");return this},clone:function(e,t){return e=null!=e&&e,t=null==t?e:t,this.map(function(){return k.clone(this,e,t)})},html:function(e){return U(this,function(e){var t=this[0]||{},n=0,r=this.length;if(void 0===e&&1===t.nodeType)return t.innerHTML;if("string"==typeof e&&!De.test(e)&&!ge[(fe.exec(e)||["",""])[1].toLowerCase()]){e=k.htmlPrefilter(e);try{for(;n=0&&(l+=Math.max(0,Math.ceil(e["offset"+t[0].toUpperCase()+t.slice(1)]-o-l-a-.5))),l}function Je(e,t,n){var r=$e(e),i=ze(e,t,r),o="border-box"===k.css(e,"boxSizing",!1,r),s=o;if(Ne.test(i)){if(!n)return i;i="auto"}return s=s&&(v.boxSizingReliable()||i===e.style[t]),("auto"===i||!parseFloat(i)&&"inline"===k.css(e,"display",!1,r))&&(i=e["offset"+t[0].toUpperCase()+t.slice(1)],s=!0),(i=parseFloat(i)||0)+Ze(e,t,n||(o?"border":"content"),s,r,i)+"px"}function et(e,t,n,r,i){return new et.prototype.init(e,t,n,r,i)}k.extend({cssHooks:{opacity:{get:function(e,t){if(t){var n=ze(e,"opacity");return""===n?"1":n}}}},cssNumber:{animationIterationCount:!0,columnCount:!0,fillOpacity:!0,flexGrow:!0,flexShrink:!0,fontWeight:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{},style:function(e,t,n,r){if(e&&3!==e.nodeType&&8!==e.nodeType&&e.style){var i,o,s,a=Y(t),l=Ue.test(t),u=e.style;if(l||(t=Xe(a)),s=k.cssHooks[t]||k.cssHooks[a],void 0===n)return s&&"get"in s&&void 0!==(i=s.get(e,!1,r))?i:u[t];"string"===(o=typeof n)&&(i=ie.exec(n))&&i[1]&&(n=le(e,t,i),o="number"),null!=n&&n==n&&("number"===o&&(n+=i&&i[3]||(k.cssNumber[a]?"":"px")),v.clearCloneStyle||""!==n||0!==t.indexOf("background")||(u[t]="inherit"),s&&"set"in s&&void 0===(n=s.set(e,n,r))||(l?u.setProperty(t,n):u[t]=n))}},css:function(e,t,n,r){var i,o,s,a=Y(t);return Ue.test(t)||(t=Xe(a)),(s=k.cssHooks[t]||k.cssHooks[a])&&"get"in s&&(i=s.get(e,!0,n)),void 0===i&&(i=ze(e,t,r)),"normal"===i&&t in Ke&&(i=Ke[t]),""===n||n?(o=parseFloat(i),!0===n||isFinite(o)?o||0:i):i}}),k.each(["height","width"],function(e,t){k.cssHooks[t]={get:function(e,n,r){if(n)return!Ve.test(k.css(e,"display"))||e.getClientRects().length&&e.getBoundingClientRect().width?Je(e,t,r):ae(e,Ge,function(){return Je(e,t,r)})},set:function(e,n,r){var i,o=$e(e),s="border-box"===k.css(e,"boxSizing",!1,o),a=r&&Ze(e,t,r,s,o);return s&&v.scrollboxSize()===o.position&&(a-=Math.ceil(e["offset"+t[0].toUpperCase()+t.slice(1)]-parseFloat(o[t])-Ze(e,t,"border",!1,o)-.5)),a&&(i=ie.exec(n))&&"px"!==(i[3]||"px")&&(e.style[t]=n,n=k.css(e,t)),Qe(0,n,a)}}}),k.cssHooks.marginLeft=He(v.reliableMarginLeft,function(e,t){if(t)return(parseFloat(ze(e,"marginLeft"))||e.getBoundingClientRect().left-ae(e,{marginLeft:0},function(){return e.getBoundingClientRect().left}))+"px"}),k.each({margin:"",padding:"",border:"Width"},function(e,t){k.cssHooks[e+t]={expand:function(n){for(var r=0,i={},o="string"==typeof n?n.split(" "):[n];r<4;r++)i[e+oe[r]+t]=o[r]||o[r-2]||o[0];return i}},"margin"!==e&&(k.cssHooks[e+t].set=Qe)}),k.fn.extend({css:function(e,t){return U(this,function(e,t,n){var r,i,o={},s=0;if(Array.isArray(t)){for(r=$e(e),i=t.length;s1)}}),k.Tween=et,et.prototype={constructor:et,init:function(e,t,n,r,i,o){this.elem=e,this.prop=n,this.easing=i||k.easing._default,this.options=t,this.start=this.now=this.cur(),this.end=r,this.unit=o||(k.cssNumber[n]?"":"px")},cur:function(){var e=et.propHooks[this.prop];return e&&e.get?e.get(this):et.propHooks._default.get(this)},run:function(e){var t,n=et.propHooks[this.prop];return this.options.duration?this.pos=t=k.easing[this.easing](e,this.options.duration*e,0,1,this.options.duration):this.pos=t=e,this.now=(this.end-this.start)*t+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),n&&n.set?n.set(this):et.propHooks._default.set(this),this}},et.prototype.init.prototype=et.prototype,et.propHooks={_default:{get:function(e){var t;return 1!==e.elem.nodeType||null!=e.elem[e.prop]&&null==e.elem.style[e.prop]?e.elem[e.prop]:(t=k.css(e.elem,e.prop,""))&&"auto"!==t?t:0},set:function(e){k.fx.step[e.prop]?k.fx.step[e.prop](e):1!==e.elem.nodeType||null==e.elem.style[k.cssProps[e.prop]]&&!k.cssHooks[e.prop]?e.elem[e.prop]=e.now:k.style(e.elem,e.prop,e.now+e.unit)}}},et.propHooks.scrollTop=et.propHooks.scrollLeft={set:function(e){e.elem.nodeType&&e.elem.parentNode&&(e.elem[e.prop]=e.now)}},k.easing={linear:function(e){return e},swing:function(e){return.5-Math.cos(e*Math.PI)/2},_default:"swing"},k.fx=et.prototype.init,k.fx.step={};var tt,nt,rt=/^(?:toggle|show|hide)$/,it=/queueHooks$/;function ot(){nt&&(!1===s.hidden&&n.requestAnimationFrame?n.requestAnimationFrame(ot):n.setTimeout(ot,k.fx.interval),k.fx.tick())}function st(){return n.setTimeout(function(){tt=void 0}),tt=Date.now()}function at(e,t){var n,r=0,i={height:e};for(t=t?1:0;r<4;r+=2-t)i["margin"+(n=oe[r])]=i["padding"+n]=e;return t&&(i.opacity=i.width=e),i}function lt(e,t,n){for(var r,i=(ut.tweeners[t]||[]).concat(ut.tweeners["*"]),o=0,s=i.length;o1)},removeAttr:function(e){return this.each(function(){k.removeAttr(this,e)})}}),k.extend({attr:function(e,t,n){var r,i,o=e.nodeType;if(3!==o&&8!==o&&2!==o)return void 0===e.getAttribute?k.prop(e,t,n):(1===o&&k.isXMLDoc(e)||(i=k.attrHooks[t.toLowerCase()]||(k.expr.match.bool.test(t)?ct:void 0)),void 0!==n?null===n?void k.removeAttr(e,t):i&&"set"in i&&void 0!==(r=i.set(e,n,t))?r:(e.setAttribute(t,n+""),n):i&&"get"in i&&null!==(r=i.get(e,t))?r:null==(r=k.find.attr(e,t))?void 0:r)},attrHooks:{type:{set:function(e,t){if(!v.radioValue&&"radio"===t&&T(e,"input")){var n=e.value;return e.setAttribute("type",t),n&&(e.value=n),t}}}},removeAttr:function(e,t){var n,r=0,i=t&&t.match(j);if(i&&1===e.nodeType)for(;n=i[r++];)e.removeAttribute(n)}}),ct={set:function(e,t,n){return!1===t?k.removeAttr(e,n):e.setAttribute(n,n),n}},k.each(k.expr.match.bool.source.match(/\w+/g),function(e,t){var n=ht[t]||k.find.attr;ht[t]=function(e,t,r){var i,o,s=t.toLowerCase();return r||(o=ht[s],ht[s]=i,i=null!=n(e,t,r)?s:null,ht[s]=o),i}});var dt=/^(?:input|select|textarea|button)$/i,ft=/^(?:a|area)$/i;function pt(e){return(e.match(j)||[]).join(" ")}function gt(e){return e.getAttribute&&e.getAttribute("class")||""}function mt(e){return Array.isArray(e)?e:"string"==typeof e&&e.match(j)||[]}k.fn.extend({prop:function(e,t){return U(this,k.prop,e,t,arguments.length>1)},removeProp:function(e){return this.each(function(){delete this[k.propFix[e]||e]})}}),k.extend({prop:function(e,t,n){var r,i,o=e.nodeType;if(3!==o&&8!==o&&2!==o)return 1===o&&k.isXMLDoc(e)||(t=k.propFix[t]||t,i=k.propHooks[t]),void 0!==n?i&&"set"in i&&void 0!==(r=i.set(e,n,t))?r:e[t]=n:i&&"get"in i&&null!==(r=i.get(e,t))?r:e[t]},propHooks:{tabIndex:{get:function(e){var t=k.find.attr(e,"tabindex");return t?parseInt(t,10):dt.test(e.nodeName)||ft.test(e.nodeName)&&e.href?0:-1}}},propFix:{for:"htmlFor",class:"className"}}),v.optSelected||(k.propHooks.selected={get:function(e){var t=e.parentNode;return t&&t.parentNode&&t.parentNode.selectedIndex,null},set:function(e){var t=e.parentNode;t&&(t.selectedIndex,t.parentNode&&t.parentNode.selectedIndex)}}),k.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){k.propFix[this.toLowerCase()]=this}),k.fn.extend({addClass:function(e){var t,n,r,i,o,s,a,l=0;if(y(e))return this.each(function(t){k(this).addClass(e.call(this,t,gt(this)))});if((t=mt(e)).length)for(;n=this[l++];)if(i=gt(n),r=1===n.nodeType&&" "+pt(i)+" "){for(s=0;o=t[s++];)r.indexOf(" "+o+" ")<0&&(r+=o+" ");i!==(a=pt(r))&&n.setAttribute("class",a)}return this},removeClass:function(e){var t,n,r,i,o,s,a,l=0;if(y(e))return this.each(function(t){k(this).removeClass(e.call(this,t,gt(this)))});if(!arguments.length)return this.attr("class","");if((t=mt(e)).length)for(;n=this[l++];)if(i=gt(n),r=1===n.nodeType&&" "+pt(i)+" "){for(s=0;o=t[s++];)for(;r.indexOf(" "+o+" ")>-1;)r=r.replace(" "+o+" "," ");i!==(a=pt(r))&&n.setAttribute("class",a)}return this},toggleClass:function(e,t){var n=typeof e,r="string"===n||Array.isArray(e);return"boolean"==typeof t&&r?t?this.addClass(e):this.removeClass(e):y(e)?this.each(function(n){k(this).toggleClass(e.call(this,n,gt(this),t),t)}):this.each(function(){var t,i,o,s;if(r)for(i=0,o=k(this),s=mt(e);t=s[i++];)o.hasClass(t)?o.removeClass(t):o.addClass(t);else void 0!==e&&"boolean"!==n||((t=gt(this))&&Z.set(this,"__className__",t),this.setAttribute&&this.setAttribute("class",t||!1===e?"":Z.get(this,"__className__")||""))})},hasClass:function(e){var t,n,r=0;for(t=" "+e+" ";n=this[r++];)if(1===n.nodeType&&(" "+pt(gt(n))+" ").indexOf(t)>-1)return!0;return!1}});var vt=/\r/g;k.fn.extend({val:function(e){var t,n,r,i=this[0];return arguments.length?(r=y(e),this.each(function(n){var i;1===this.nodeType&&(null==(i=r?e.call(this,n,k(this).val()):e)?i="":"number"==typeof i?i+="":Array.isArray(i)&&(i=k.map(i,function(e){return null==e?"":e+""})),(t=k.valHooks[this.type]||k.valHooks[this.nodeName.toLowerCase()])&&"set"in t&&void 0!==t.set(this,i,"value")||(this.value=i))})):i?(t=k.valHooks[i.type]||k.valHooks[i.nodeName.toLowerCase()])&&"get"in t&&void 0!==(n=t.get(i,"value"))?n:"string"==typeof(n=i.value)?n.replace(vt,""):null==n?"":n:void 0}}),k.extend({valHooks:{option:{get:function(e){var t=k.find.attr(e,"value");return null!=t?t:pt(k.text(e))}},select:{get:function(e){var t,n,r,i=e.options,o=e.selectedIndex,s="select-one"===e.type,a=s?null:[],l=s?o+1:i.length;for(r=o<0?l:s?o:0;r-1)&&(n=!0);return n||(e.selectedIndex=-1),o}}}}),k.each(["radio","checkbox"],function(){k.valHooks[this]={set:function(e,t){if(Array.isArray(t))return e.checked=k.inArray(k(e).val(),t)>-1}},v.checkOn||(k.valHooks[this].get=function(e){return null===e.getAttribute("value")?"on":e.value})}),v.focusin="onfocusin"in n;var yt=/^(?:focusinfocus|focusoutblur)$/,bt=function(e){e.stopPropagation()};k.extend(k.event,{trigger:function(e,t,r,i){var o,a,l,u,c,h,d,f,g=[r||s],m=p.call(e,"type")?e.type:e,v=p.call(e,"namespace")?e.namespace.split("."):[];if(a=f=l=r=r||s,3!==r.nodeType&&8!==r.nodeType&&!yt.test(m+k.event.triggered)&&(m.indexOf(".")>-1&&(m=(v=m.split(".")).shift(),v.sort()),c=m.indexOf(":")<0&&"on"+m,(e=e[k.expando]?e:new k.Event(m,"object"==typeof e&&e)).isTrigger=i?2:3,e.namespace=v.join("."),e.rnamespace=e.namespace?new RegExp("(^|\\.)"+v.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,e.result=void 0,e.target||(e.target=r),t=null==t?[e]:k.makeArray(t,[e]),d=k.event.special[m]||{},i||!d.trigger||!1!==d.trigger.apply(r,t))){if(!i&&!d.noBubble&&!b(r)){for(u=d.delegateType||m,yt.test(u+m)||(a=a.parentNode);a;a=a.parentNode)g.push(a),l=a;l===(r.ownerDocument||s)&&g.push(l.defaultView||l.parentWindow||n)}for(o=0;(a=g[o++])&&!e.isPropagationStopped();)f=a,e.type=o>1?u:d.bindType||m,(h=(Z.get(a,"events")||{})[e.type]&&Z.get(a,"handle"))&&h.apply(a,t),(h=c&&a[c])&&h.apply&&X(a)&&(e.result=h.apply(a,t),!1===e.result&&e.preventDefault());return e.type=m,i||e.isDefaultPrevented()||d._default&&!1!==d._default.apply(g.pop(),t)||!X(r)||c&&y(r[m])&&!b(r)&&((l=r[c])&&(r[c]=null),k.event.triggered=m,e.isPropagationStopped()&&f.addEventListener(m,bt),r[m](),e.isPropagationStopped()&&f.removeEventListener(m,bt),k.event.triggered=void 0,l&&(r[c]=l)),e.result}},simulate:function(e,t,n){var r=k.extend(new k.Event,n,{type:e,isSimulated:!0});k.event.trigger(r,null,t)}}),k.fn.extend({trigger:function(e,t){return this.each(function(){k.event.trigger(e,t,this)})},triggerHandler:function(e,t){var n=this[0];if(n)return k.event.trigger(e,t,n,!0)}}),v.focusin||k.each({focus:"focusin",blur:"focusout"},function(e,t){var n=function(e){k.event.simulate(t,e.target,k.event.fix(e))};k.event.special[t]={setup:function(){var r=this.ownerDocument||this,i=Z.access(r,t);i||r.addEventListener(e,n,!0),Z.access(r,t,(i||0)+1)},teardown:function(){var r=this.ownerDocument||this,i=Z.access(r,t)-1;i?Z.access(r,t,i):(r.removeEventListener(e,n,!0),Z.remove(r,t))}}});var xt=n.location,wt=Date.now(),Ct=/\?/;k.parseXML=function(e){var t;if(!e||"string"!=typeof e)return null;try{t=(new n.DOMParser).parseFromString(e,"text/xml")}catch(e){t=void 0}return t&&!t.getElementsByTagName("parsererror").length||k.error("Invalid XML: "+e),t};var kt=/\[\]$/,Et=/\r?\n/g,At=/^(?:submit|button|image|reset|file)$/i,_t=/^(?:input|select|textarea|keygen)/i;function St(e,t,n,r){var i;if(Array.isArray(t))k.each(t,function(t,i){n||kt.test(e)?r(e,i):St(e+"["+("object"==typeof i&&null!=i?t:"")+"]",i,n,r)});else if(n||"object"!==C(t))r(e,t);else for(i in t)St(e+"["+i+"]",t[i],n,r)}k.param=function(e,t){var n,r=[],i=function(e,t){var n=y(t)?t():t;r[r.length]=encodeURIComponent(e)+"="+encodeURIComponent(null==n?"":n)};if(Array.isArray(e)||e.jquery&&!k.isPlainObject(e))k.each(e,function(){i(this.name,this.value)});else for(n in e)St(n,e[n],t,i);return r.join("&")},k.fn.extend({serialize:function(){return k.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var e=k.prop(this,"elements");return e?k.makeArray(e):this}).filter(function(){var e=this.type;return this.name&&!k(this).is(":disabled")&&_t.test(this.nodeName)&&!At.test(e)&&(this.checked||!de.test(e))}).map(function(e,t){var n=k(this).val();return null==n?null:Array.isArray(n)?k.map(n,function(e){return{name:t.name,value:e.replace(Et,"\r\n")}}):{name:t.name,value:n.replace(Et,"\r\n")}}).get()}});var Ft=/%20/g,Dt=/#.*$/,Tt=/([?&])_=[^&]*/,Lt=/^(.*?):[ \t]*([^\r\n]*)$/gm,Bt=/^(?:GET|HEAD)$/,Mt=/^\/\//,Pt={},Rt={},Ot="*/".concat("*"),It=s.createElement("a");function jt(e){return function(t,n){"string"!=typeof t&&(n=t,t="*");var r,i=0,o=t.toLowerCase().match(j)||[];if(y(n))for(;r=o[i++];)"+"===r[0]?(r=r.slice(1)||"*",(e[r]=e[r]||[]).unshift(n)):(e[r]=e[r]||[]).push(n)}}function Nt(e,t,n,r){var i={},o=e===Rt;function s(a){var l;return i[a]=!0,k.each(e[a]||[],function(e,a){var u=a(t,n,r);return"string"!=typeof u||o||i[u]?o?!(l=u):void 0:(t.dataTypes.unshift(u),s(u),!1)}),l}return s(t.dataTypes[0])||!i["*"]&&s("*")}function $t(e,t){var n,r,i=k.ajaxSettings.flatOptions||{};for(n in t)void 0!==t[n]&&((i[n]?e:r||(r={}))[n]=t[n]);return r&&k.extend(!0,e,r),e}It.href=xt.href,k.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:xt.href,type:"GET",isLocal:/^(?:about|app|app-storage|.+-extension|file|res|widget):$/.test(xt.protocol),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":Ot,text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript"},contents:{xml:/\bxml\b/,html:/\bhtml/,json:/\bjson\b/},responseFields:{xml:"responseXML",text:"responseText",json:"responseJSON"},converters:{"* text":String,"text html":!0,"text json":JSON.parse,"text xml":k.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(e,t){return t?$t($t(e,k.ajaxSettings),t):$t(k.ajaxSettings,e)},ajaxPrefilter:jt(Pt),ajaxTransport:jt(Rt),ajax:function(e,t){"object"==typeof e&&(t=e,e=void 0),t=t||{};var r,i,o,a,l,u,c,h,d,f,p=k.ajaxSetup({},t),g=p.context||p,m=p.context&&(g.nodeType||g.jquery)?k(g):k.event,v=k.Deferred(),y=k.Callbacks("once memory"),b=p.statusCode||{},x={},w={},C="canceled",E={readyState:0,getResponseHeader:function(e){var t;if(c){if(!a)for(a={};t=Lt.exec(o);)a[t[1].toLowerCase()]=t[2];t=a[e.toLowerCase()]}return null==t?null:t},getAllResponseHeaders:function(){return c?o:null},setRequestHeader:function(e,t){return null==c&&(e=w[e.toLowerCase()]=w[e.toLowerCase()]||e,x[e]=t),this},overrideMimeType:function(e){return null==c&&(p.mimeType=e),this},statusCode:function(e){var t;if(e)if(c)E.always(e[E.status]);else for(t in e)b[t]=[b[t],e[t]];return this},abort:function(e){var t=e||C;return r&&r.abort(t),A(0,t),this}};if(v.promise(E),p.url=((e||p.url||xt.href)+"").replace(Mt,xt.protocol+"//"),p.type=t.method||t.type||p.method||p.type,p.dataTypes=(p.dataType||"*").toLowerCase().match(j)||[""],null==p.crossDomain){u=s.createElement("a");try{u.href=p.url,u.href=u.href,p.crossDomain=It.protocol+"//"+It.host!=u.protocol+"//"+u.host}catch(e){p.crossDomain=!0}}if(p.data&&p.processData&&"string"!=typeof p.data&&(p.data=k.param(p.data,p.traditional)),Nt(Pt,p,t,E),c)return E;for(d in(h=k.event&&p.global)&&0==k.active++&&k.event.trigger("ajaxStart"),p.type=p.type.toUpperCase(),p.hasContent=!Bt.test(p.type),i=p.url.replace(Dt,""),p.hasContent?p.data&&p.processData&&0===(p.contentType||"").indexOf("application/x-www-form-urlencoded")&&(p.data=p.data.replace(Ft,"+")):(f=p.url.slice(i.length),p.data&&(p.processData||"string"==typeof p.data)&&(i+=(Ct.test(i)?"&":"?")+p.data,delete p.data),!1===p.cache&&(i=i.replace(Tt,"$1"),f=(Ct.test(i)?"&":"?")+"_="+wt+++f),p.url=i+f),p.ifModified&&(k.lastModified[i]&&E.setRequestHeader("If-Modified-Since",k.lastModified[i]),k.etag[i]&&E.setRequestHeader("If-None-Match",k.etag[i])),(p.data&&p.hasContent&&!1!==p.contentType||t.contentType)&&E.setRequestHeader("Content-Type",p.contentType),E.setRequestHeader("Accept",p.dataTypes[0]&&p.accepts[p.dataTypes[0]]?p.accepts[p.dataTypes[0]]+("*"!==p.dataTypes[0]?", "+Ot+"; q=0.01":""):p.accepts["*"]),p.headers)E.setRequestHeader(d,p.headers[d]);if(p.beforeSend&&(!1===p.beforeSend.call(g,E,p)||c))return E.abort();if(C="abort",y.add(p.complete),E.done(p.success),E.fail(p.error),r=Nt(Rt,p,t,E)){if(E.readyState=1,h&&m.trigger("ajaxSend",[E,p]),c)return E;p.async&&p.timeout>0&&(l=n.setTimeout(function(){E.abort("timeout")},p.timeout));try{c=!1,r.send(x,A)}catch(e){if(c)throw e;A(-1,e)}}else A(-1,"No Transport");function A(e,t,s,a){var u,d,f,x,w,C=t;c||(c=!0,l&&n.clearTimeout(l),r=void 0,o=a||"",E.readyState=e>0?4:0,u=e>=200&&e<300||304===e,s&&(x=function(e,t,n){for(var r,i,o,s,a=e.contents,l=e.dataTypes;"*"===l[0];)l.shift(),void 0===r&&(r=e.mimeType||t.getResponseHeader("Content-Type"));if(r)for(i in a)if(a[i]&&a[i].test(r)){l.unshift(i);break}if(l[0]in n)o=l[0];else{for(i in n){if(!l[0]||e.converters[i+" "+l[0]]){o=i;break}s||(s=i)}o=o||s}if(o)return o!==l[0]&&l.unshift(o),n[o]}(p,E,s)),x=function(e,t,n,r){var i,o,s,a,l,u={},c=e.dataTypes.slice();if(c[1])for(s in e.converters)u[s.toLowerCase()]=e.converters[s];for(o=c.shift();o;)if(e.responseFields[o]&&(n[e.responseFields[o]]=t),!l&&r&&e.dataFilter&&(t=e.dataFilter(t,e.dataType)),l=o,o=c.shift())if("*"===o)o=l;else if("*"!==l&&l!==o){if(!(s=u[l+" "+o]||u["* "+o]))for(i in u)if((a=i.split(" "))[1]===o&&(s=u[l+" "+a[0]]||u["* "+a[0]])){!0===s?s=u[i]:!0!==u[i]&&(o=a[0],c.unshift(a[1]));break}if(!0!==s)if(s&&e.throws)t=s(t);else try{t=s(t)}catch(e){return{state:"parsererror",error:s?e:"No conversion from "+l+" to "+o}}}return{state:"success",data:t}}(p,x,E,u),u?(p.ifModified&&((w=E.getResponseHeader("Last-Modified"))&&(k.lastModified[i]=w),(w=E.getResponseHeader("etag"))&&(k.etag[i]=w)),204===e||"HEAD"===p.type?C="nocontent":304===e?C="notmodified":(C=x.state,d=x.data,u=!(f=x.error))):(f=C,!e&&C||(C="error",e<0&&(e=0))),E.status=e,E.statusText=(t||C)+"",u?v.resolveWith(g,[d,C,E]):v.rejectWith(g,[E,C,f]),E.statusCode(b),b=void 0,h&&m.trigger(u?"ajaxSuccess":"ajaxError",[E,p,u?d:f]),y.fireWith(g,[E,C]),h&&(m.trigger("ajaxComplete",[E,p]),--k.active||k.event.trigger("ajaxStop")))}return E},getJSON:function(e,t,n){return k.get(e,t,n,"json")},getScript:function(e,t){return k.get(e,void 0,t,"script")}}),k.each(["get","post"],function(e,t){k[t]=function(e,n,r,i){return y(n)&&(i=i||r,r=n,n=void 0),k.ajax(k.extend({url:e,type:t,dataType:i,data:n,success:r},k.isPlainObject(e)&&e))}}),k._evalUrl=function(e){return k.ajax({url:e,type:"GET",dataType:"script",cache:!0,async:!1,global:!1,throws:!0})},k.fn.extend({wrapAll:function(e){var t;return this[0]&&(y(e)&&(e=e.call(this[0])),t=k(e,this[0].ownerDocument).eq(0).clone(!0),this[0].parentNode&&t.insertBefore(this[0]),t.map(function(){for(var e=this;e.firstElementChild;)e=e.firstElementChild;return e}).append(this)),this},wrapInner:function(e){return y(e)?this.each(function(t){k(this).wrapInner(e.call(this,t))}):this.each(function(){var t=k(this),n=t.contents();n.length?n.wrapAll(e):t.append(e)})},wrap:function(e){var t=y(e);return this.each(function(n){k(this).wrapAll(t?e.call(this,n):e)})},unwrap:function(e){return this.parent(e).not("body").each(function(){k(this).replaceWith(this.childNodes)}),this}}),k.expr.pseudos.hidden=function(e){return!k.expr.pseudos.visible(e)},k.expr.pseudos.visible=function(e){return!!(e.offsetWidth||e.offsetHeight||e.getClientRects().length)},k.ajaxSettings.xhr=function(){try{return new n.XMLHttpRequest}catch(e){}};var Wt={0:200,1223:204},zt=k.ajaxSettings.xhr();v.cors=!!zt&&"withCredentials"in zt,v.ajax=zt=!!zt,k.ajaxTransport(function(e){var t,r;if(v.cors||zt&&!e.crossDomain)return{send:function(i,o){var s,a=e.xhr();if(a.open(e.type,e.url,e.async,e.username,e.password),e.xhrFields)for(s in e.xhrFields)a[s]=e.xhrFields[s];for(s in e.mimeType&&a.overrideMimeType&&a.overrideMimeType(e.mimeType),e.crossDomain||i["X-Requested-With"]||(i["X-Requested-With"]="XMLHttpRequest"),i)a.setRequestHeader(s,i[s]);t=function(e){return function(){t&&(t=r=a.onload=a.onerror=a.onabort=a.ontimeout=a.onreadystatechange=null,"abort"===e?a.abort():"error"===e?"number"!=typeof a.status?o(0,"error"):o(a.status,a.statusText):o(Wt[a.status]||a.status,a.statusText,"text"!==(a.responseType||"text")||"string"!=typeof a.responseText?{binary:a.response}:{text:a.responseText},a.getAllResponseHeaders()))}},a.onload=t(),r=a.onerror=a.ontimeout=t("error"),void 0!==a.onabort?a.onabort=r:a.onreadystatechange=function(){4===a.readyState&&n.setTimeout(function(){t&&r()})},t=t("abort");try{a.send(e.hasContent&&e.data||null)}catch(e){if(t)throw e}},abort:function(){t&&t()}}}),k.ajaxPrefilter(function(e){e.crossDomain&&(e.contents.script=!1)}),k.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/\b(?:java|ecma)script\b/},converters:{"text script":function(e){return k.globalEval(e),e}}}),k.ajaxPrefilter("script",function(e){void 0===e.cache&&(e.cache=!1),e.crossDomain&&(e.type="GET")}),k.ajaxTransport("script",function(e){var t,n;if(e.crossDomain)return{send:function(r,i){t=k("