diff --git a/src/BitNode.js b/src/BitNode.js
index 3ec373e48..8885a9ba7 100644
--- a/src/BitNode.js
+++ b/src/BitNode.js
@@ -34,7 +34,7 @@ BitNodes = {
"Level 3: 35%"),
BitNode3: new BitNode(3, "The Price of Civilization", "COMING SOON"), //Corporate Warfare, Run own company
BitNode4: new BitNode(4, "The Singularity", "COMING SOON"), //Everything automatable
- BitNode5: new BitNode(5, "2084", "COMING SOON"), //Big Brother
+ BitNode5: new BitNode(5, "Artificial Intelligence", "COMING SOON"), //Big Brother
BitNode6: new BitNode(6, "Hacktocracy", "COMING SOON"), //Healthy Hacknet balancing mechanic
BitNode7: new BitNode(7, "Do Androids Dream?", "COMING SOON"), //Build androids for automation
BitNode8: new BitNode(8, "Ghost of Wall Street", "COMING SOON"), //Trading only viable strategy
diff --git a/src/NetscriptFunctions.js b/src/NetscriptFunctions.js
index 10d654a92..4b23dbdd8 100644
--- a/src/NetscriptFunctions.js
+++ b/src/NetscriptFunctions.js
@@ -1,3 +1,10 @@
+function initSingularitySFFlags() {
+ //TODO
+}
+
+var hasSingularitySF = false;
+var singularitySFLvl = 1;
+
function NetscriptFunctions(workerScript) {
return {
hacknetnodes : Player.hacknetNodes,
@@ -864,7 +871,39 @@ function NetscriptFunctions(workerScript) {
throw makeRuntimeRejectMsg(workerScript, "getWeakenTime() failed. Invalid IP or hostname passed in: " + ip);
}
return scriptCalculateWeakenTime(server) / 1000; //Returns seconds
- }
+ },
+
+ /* Singularity Functions */
+ universityCourse(universityName, courseName) {
+ if (Player.isWorking) {
+ var txt = Player.singularityStopWork();
+ workerScript.scriptRef.log(txt);
+ }
+ },
+ //gymWorkout(gymName, stat);
+
+ //travelToCity(cityname);
+
+ //purchaseTor();
+
+ //homeComp.upgradeRam();
+ //homeComp.getUpgradeRamCost();
+
+ //workForCompany();
+ //applyToCompany(companyName, field);
+ //getCompanyRep(companyName);
+
+ //checkFactionInvitations();
+ //joinFaction(name);
+ //workForFaction(facName, type);
+ //getFactionRep(name);
+
+ //createProgram();
+
+ //getAugmentationCost(name);
+ //purchaseAugmentation(faction, name);
+ //installAugmentations();
+
}
}
diff --git a/src/Player.js b/src/Player.js
index 6e1d1b4e8..2b4a24ca6 100644
--- a/src/Player.js
+++ b/src/Player.js
@@ -1064,7 +1064,9 @@ PlayerObject.prototype.takeClass = function(numCycles) {
"You may cancel at any time";
}
-PlayerObject.prototype.finishClass = function() {
+//The 'sing' argument defines whether or not this function was called
+//through a Singularity Netscript function
+PlayerObject.prototype.finishClass = function(sing=false) {
this.gainWorkExp();
if (this.workMoneyGained > 0) {
@@ -1082,8 +1084,7 @@ PlayerObject.prototype.finishClass = function() {
formatNumber(this.workDexExpGained, 4) + " dexterity exp
" +
formatNumber(this.workAgiExpGained, 4) + " agility exp
" +
formatNumber(this.workChaExpGained, 4) + " charisma exp
";
-
- dialogBoxCreate(txt);
+ if (!sing) {dialogBoxCreate(txt);}
var mainMenu = document.getElementById("mainmenu-container");
mainMenu.style.visibility = "visible";
@@ -1091,6 +1092,16 @@ PlayerObject.prototype.finishClass = function() {
this.isWorking = false;
Engine.loadLocationContent();
+
+ if (sing) {return = "After " + this.className + " for " + convertTimeMsToTimeElapsedString(this.timeWorked) + ", " +
+ "you spent a total of $" + formatNumber(this.workMoneyGained * -1, 2) + ". " +
+ "You earned a total of: " +
+ formatNumber(this.workHackExpGained, 3) + " hacking exp, " +
+ formatNumber(this.workStrExpGained, 3) + " strength exp, " +
+ formatNumber(this.workDefExpGained, 3) + " defense exp, " +
+ formatNumber(this.workDexExpGained, 3) + " dexterity exp, " +
+ formatNumber(this.workAgiExpGained, 3) + " agility exp, and " +
+ formatNumber(this.workChaExpGained, 3) + " charisma exp";}
}
//The EXP and $ gains are hardcoded. Time is in ms
@@ -1232,6 +1243,20 @@ PlayerObject.prototype.finishCrime = function(cancelled) {
Engine.loadLocationContent();
}
+//Cancels the player's current "work" assignment and gives the proper rewards
+//Used only for Singularity functions, so no popups are created
+PlayerObject.prototype.singularityStopWork = function() {
+ if (!this.isWorking) {return null;}
+ switch (this.workType) {
+ case CONSTANTS.WorkTypeStudyClass:
+ return Player.finishClass(true);
+ break;
+ default:
+ console.log("ERROR: Unrecognized work type");
+ return;
+ }
+}
+
//Returns true if hospitalized, false otherwise
PlayerObject.prototype.takeDamage = function(amt) {