This commit is contained in:
danielyxie 2019-07-15 21:40:13 -07:00 committed by danielyxie
parent 916ef06913
commit 59cf1d5baf
11 changed files with 220 additions and 75103 deletions

75004
dist/engine.bundle.js vendored

File diff suppressed because one or more lines are too long

@ -1,2 +1,2 @@
!function(n){function t(t){for(var e,i,f=t[0],c=t[1],l=t[2],p=0,s=[];p<f.length;p++)i=f[p],u[i]&&s.push(u[i][0]),u[i]=0;for(e in c)Object.prototype.hasOwnProperty.call(c,e)&&(n[e]=c[e]);for(a&&a(t);s.length;)s.shift()();return r.push.apply(r,l||[]),o()}function o(){for(var n,t=0;t<r.length;t++){for(var o=r[t],e=!0,f=1;f<o.length;f++){var c=o[f];0!==u[c]&&(e=!1)}e&&(r.splice(t--,1),n=i(i.s=o[0]))}return n}var e={},u={1:0},r=[];function i(t){if(e[t])return e[t].exports;var o=e[t]={i:t,l:!1,exports:{}};return n[t].call(o.exports,o,o.exports,i),o.l=!0,o.exports}i.m=n,i.c=e,i.d=function(n,t,o){i.o(n,t)||Object.defineProperty(n,t,{enumerable:!0,get:o})},i.r=function(n){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(n,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(n,"__esModule",{value:!0})},i.t=function(n,t){if(1&t&&(n=i(n)),8&t)return n;if(4&t&&"object"==typeof n&&n&&n.__esModule)return n;var o=Object.create(null);if(i.r(o),Object.defineProperty(o,"default",{enumerable:!0,value:n}),2&t&&"string"!=typeof n)for(var e in n)i.d(o,e,function(t){return n[t]}.bind(null,e));return o},i.n=function(n){var t=n&&n.__esModule?function(){return n.default}:function(){return n};return i.d(t,"a",t),t},i.o=function(n,t){return Object.prototype.hasOwnProperty.call(n,t)},i.p="";var f=window.webpackJsonp=window.webpackJsonp||[],c=f.push.bind(f);f.push=t,f=f.slice();for(var l=0;l<f.length;l++)t(f[l]);var a=c;r.push([361,0]),o()}({304:function(n,t,o){},306:function(n,t,o){},308:function(n,t,o){},310:function(n,t,o){},312:function(n,t,o){},314:function(n,t,o){},316:function(n,t,o){},318:function(n,t,o){},320:function(n,t,o){},322:function(n,t,o){},324:function(n,t,o){},326:function(n,t,o){},328:function(n,t,o){},330:function(n,t,o){},332:function(n,t,o){},334:function(n,t,o){},336:function(n,t,o){},338:function(n,t,o){},340:function(n,t,o){},342:function(n,t,o){},344:function(n,t,o){},346:function(n,t,o){},348:function(n,t,o){},350:function(n,t,o){},352:function(n,t,o){},354:function(n,t,o){},356:function(n,t,o){},358:function(n,t,o){},361:function(n,t,o){"use strict";o.r(t);o(360),o(358),o(356),o(354),o(352),o(350),o(348),o(346),o(344),o(342),o(340),o(338),o(336),o(334),o(332),o(330),o(328),o(326),o(324),o(322),o(320),o(318),o(316),o(314),o(312),o(310),o(308),o(306),o(304)}}); !function(n){function t(t){for(var e,i,f=t[0],c=t[1],l=t[2],p=0,s=[];p<f.length;p++)i=f[p],u[i]&&s.push(u[i][0]),u[i]=0;for(e in c)Object.prototype.hasOwnProperty.call(c,e)&&(n[e]=c[e]);for(a&&a(t);s.length;)s.shift()();return r.push.apply(r,l||[]),o()}function o(){for(var n,t=0;t<r.length;t++){for(var o=r[t],e=!0,f=1;f<o.length;f++){var c=o[f];0!==u[c]&&(e=!1)}e&&(r.splice(t--,1),n=i(i.s=o[0]))}return n}var e={},u={1:0},r=[];function i(t){if(e[t])return e[t].exports;var o=e[t]={i:t,l:!1,exports:{}};return n[t].call(o.exports,o,o.exports,i),o.l=!0,o.exports}i.m=n,i.c=e,i.d=function(n,t,o){i.o(n,t)||Object.defineProperty(n,t,{enumerable:!0,get:o})},i.r=function(n){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(n,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(n,"__esModule",{value:!0})},i.t=function(n,t){if(1&t&&(n=i(n)),8&t)return n;if(4&t&&"object"==typeof n&&n&&n.__esModule)return n;var o=Object.create(null);if(i.r(o),Object.defineProperty(o,"default",{enumerable:!0,value:n}),2&t&&"string"!=typeof n)for(var e in n)i.d(o,e,function(t){return n[t]}.bind(null,e));return o},i.n=function(n){var t=n&&n.__esModule?function(){return n.default}:function(){return n};return i.d(t,"a",t),t},i.o=function(n,t){return Object.prototype.hasOwnProperty.call(n,t)},i.p="";var f=window.webpackJsonp=window.webpackJsonp||[],c=f.push.bind(f);f.push=t,f=f.slice();for(var l=0;l<f.length;l++)t(f[l]);var a=c;r.push([362,0]),o()}({305:function(n,t,o){},307:function(n,t,o){},309:function(n,t,o){},311:function(n,t,o){},313:function(n,t,o){},315:function(n,t,o){},317:function(n,t,o){},319:function(n,t,o){},321:function(n,t,o){},323:function(n,t,o){},325:function(n,t,o){},327:function(n,t,o){},329:function(n,t,o){},331:function(n,t,o){},333:function(n,t,o){},335:function(n,t,o){},337:function(n,t,o){},339:function(n,t,o){},341:function(n,t,o){},343:function(n,t,o){},345:function(n,t,o){},347:function(n,t,o){},349:function(n,t,o){},351:function(n,t,o){},353:function(n,t,o){},355:function(n,t,o){},357:function(n,t,o){},359:function(n,t,o){},362:function(n,t,o){"use strict";o.r(t);o(361),o(359),o(357),o(355),o(353),o(351),o(349),o(347),o(345),o(343),o(341),o(339),o(337),o(335),o(333),o(331),o(329),o(327),o(325),o(323),o(321),o(319),o(317),o(315),o(313),o(311),o(309),o(307),o(305)}});
//# sourceMappingURL=engineStyle.bundle.js.map //# sourceMappingURL=engineStyle.bundle.js.map

20
dist/engineStyle.css vendored

@ -1279,14 +1279,22 @@ button {
#red-pill-container { #red-pill-container {
position: fixed; } position: fixed; }
.bitnode { .bitnode.level-0 {
color: #00f; } color: red; }
.bitnode-destroyed { .bitnode.level-1 {
color: #f00; } color: yellow; }
.bitnode:hover, .bitnode.level-2 {
.bitnode-destroyed:hover { color: #48D1CC; }
.bitnode.level-3 {
color: blue; }
.bitnode.unimplemented {
color: gray; }
.bitnode:hover {
color: #fff; } color: #fff; }
/* COLORS */ /* COLORS */

24
dist/vendor.bundle.js vendored

File diff suppressed because one or more lines are too long

@ -3,6 +3,39 @@
Changelog Changelog
========= =========
v0.47.2 - 7/15/2019
-------------------
**Netscript Changes**
* Added tail() Netscript function
* hacknet.getNodeStats() function now returns an additional property for Hacknet Servers: hashCapacity
* When writing to a file, the write() function now casts the data being written to a string (using String())
* BitNode-selection page now shows what Source-File level you have for each BitNode
* Overloaded kill() function so that you can kill a script by its PID
* spawn() now only takes 10 seconds to run (decreased from 20 seconds)
* run() and exec() now return the PID of the newly-executed scripts, rather than a boolean
* (A PID is just a positive integer)
* run(), exec(), and spawn() no longer need to be await-ed in NetscriptJS
* Script parsing and RAM calculations now support ES9
* installAugmentations() no longer has a return value since it causes all scripts to die
* isBusy() now returns true if you are in a Hacking Mission
* Bug fix: workForFaction() function now properly accounts for disabled logs
* Bug fix: RAM should now be properly calculated when running a callback script with installAugmentations()
* Bug fix: Fixed bug that caused scripts killed by exit()/spawn() to "clean up" twice
**Misc Changes**
* The 'kill' Terminal command can now kill a script by its PID
* Added 'Solarized Dark' theme to CodeMirror editor
* After Infiltration, you will now return to the company page rather than the city page
* Bug fix: Stock Market UI should no longer crash for certain locale settings
* Bug fix: You can now properly remove unfinished programs (the *.exe-N%-INC files)
* Bug fix: Fixed an issue that allowed you to increase money on servers with a 'maxMoney' of 0 (like CSEC)
* Bug fix: Scripts no longer persist if they were started with syntax/import errors
* Bug fix: 'hack' and 'analyze' Terminal commands are now blocking
* Bug fix: Exp earned by duplicate sleeves at universities/gyms now takes hash upgrades into account
v0.47.1 - 6/27/2019 v0.47.1 - 6/27/2019
------------------- -------------------
* Stock Market changes: * Stock Market changes:

@ -6,7 +6,7 @@
import { IMap } from "./types"; import { IMap } from "./types";
export let CONSTANTS: IMap<any> = { export let CONSTANTS: IMap<any> = {
Version: "0.47.1", Version: "v0.47.2",
/** Max level for any skill, assuming no multipliers. Determined by max numerical value in javascript for experience /** 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 * and the skill level formula in Player.js. Note that all this means it that when experience hits MAX_INT, then
@ -197,6 +197,13 @@ export let CONSTANTS: IMap<any> = {
ClassLeadershipBaseCost: 320, ClassLeadershipBaseCost: 320,
ClassGymBaseCost: 120, ClassGymBaseCost: 120,
ClassStudyComputerScienceBaseExp: 0.5,
ClassDataStructuresBaseExp: 1,
ClassNetworksBaseExp: 2,
ClassAlgorithmsBaseExp: 4,
ClassManagementBaseExp: 2,
ClassLeadershipBaseExp: 4,
CrimeShoplift: "shoplift", CrimeShoplift: "shoplift",
CrimeRobStore: "rob a store", CrimeRobStore: "rob a store",
CrimeMug: "mug someone", CrimeMug: "mug someone",
@ -249,5 +256,7 @@ export let CONSTANTS: IMap<any> = {
* Bug fix: You can now properly remove unfinished programs (the *.exe-N%-INC files) * Bug fix: You can now properly remove unfinished programs (the *.exe-N%-INC files)
* Bug fix: Fixed an issue that allowed you to increase money on servers with a 'maxMoney' of 0 (like CSEC) * Bug fix: Fixed an issue that allowed you to increase money on servers with a 'maxMoney' of 0 (like CSEC)
* Bug fix: Scripts no longer persist if they were started with syntax/import errors * Bug fix: Scripts no longer persist if they were started with syntax/import errors
* Bug fix: 'hack' and 'analyze' Terminal commands are now blocking
* Bug fix: Exp earned by duplicate sleeves at universities/gyms now takes hash upgrades into account
` `
} }

@ -49,7 +49,6 @@ export function prestigeWorkerScripts() {
for (const ws of workerScripts.values()) { for (const ws of workerScripts.values()) {
ws.env.stopFlag = true; ws.env.stopFlag = true;
killWorkerScript(ws); killWorkerScript(ws);
console.log(`Killing ${ws.name}`);
} }
WorkerScriptStartStopEventEmitter.emitEvent(); WorkerScriptStartStopEventEmitter.emitEvent();

@ -1211,42 +1211,33 @@ export function startClass(costMult, expMult, className) {
var gameCPS = 1000 / Engine._idleSpeed; var gameCPS = 1000 / Engine._idleSpeed;
//Base exp gains per second
var baseStudyComputerScienceExp = 0.5;
var baseDataStructuresExp = 1;
var baseNetworksExp = 2;
var baseAlgorithmsExp = 4;
var baseManagementExp = 2;
var baseLeadershipExp = 4;
var baseGymExp = 1;
//Find cost and exp gain per game cycle //Find cost and exp gain per game cycle
var cost = 0; var cost = 0;
var hackExp = 0, strExp = 0, defExp = 0, dexExp = 0, agiExp = 0, chaExp = 0; var hackExp = 0, strExp = 0, defExp = 0, dexExp = 0, agiExp = 0, chaExp = 0;
const hashManager = this.hashManager; const hashManager = this.hashManager;
switch (className) { switch (className) {
case CONSTANTS.ClassStudyComputerScience: case CONSTANTS.ClassStudyComputerScience:
hackExp = baseStudyComputerScienceExp * expMult / gameCPS * hashManager.getStudyMult(); hackExp = CONSTANTS.ClassStudyComputerScienceBaseExp * expMult / gameCPS * hashManager.getStudyMult();
break; break;
case CONSTANTS.ClassDataStructures: case CONSTANTS.ClassDataStructures:
cost = CONSTANTS.ClassDataStructuresBaseCost * costMult / gameCPS; cost = CONSTANTS.ClassDataStructuresBaseCost * costMult / gameCPS;
hackExp = baseDataStructuresExp * expMult / gameCPS * hashManager.getStudyMult(); hackExp = CONSTANTS.ClassDataStructuresBaseExp * expMult / gameCPS * hashManager.getStudyMult();
break; break;
case CONSTANTS.ClassNetworks: case CONSTANTS.ClassNetworks:
cost = CONSTANTS.ClassNetworksBaseCost * costMult / gameCPS; cost = CONSTANTS.ClassNetworksBaseCost * costMult / gameCPS;
hackExp = baseNetworksExp * expMult / gameCPS * hashManager.getStudyMult(); hackExp = CONSTANTS.ClassNetworksBaseExp * expMult / gameCPS * hashManager.getStudyMult();
break; break;
case CONSTANTS.ClassAlgorithms: case CONSTANTS.ClassAlgorithms:
cost = CONSTANTS.ClassAlgorithmsBaseCost * costMult / gameCPS; cost = CONSTANTS.ClassAlgorithmsBaseCost * costMult / gameCPS;
hackExp = baseAlgorithmsExp * expMult / gameCPS * hashManager.getStudyMult(); hackExp = CONSTANTS.ClassAlgorithmsBaseExp * expMult / gameCPS * hashManager.getStudyMult();
break; break;
case CONSTANTS.ClassManagement: case CONSTANTS.ClassManagement:
cost = CONSTANTS.ClassManagementBaseCost * costMult / gameCPS; cost = CONSTANTS.ClassManagementBaseCost * costMult / gameCPS;
chaExp = baseManagementExp * expMult / gameCPS * hashManager.getStudyMult(); chaExp = CONSTANTS.ClassManagementBaseExp * expMult / gameCPS * hashManager.getStudyMult();
break; break;
case CONSTANTS.ClassLeadership: case CONSTANTS.ClassLeadership:
cost = CONSTANTS.ClassLeadershipBaseCost * costMult / gameCPS; cost = CONSTANTS.ClassLeadershipBaseCost * costMult / gameCPS;
chaExp = baseLeadershipExp * expMult / gameCPS * hashManager.getStudyMult(); chaExp = CONSTANTS.ClassLeadershipBaseExp * expMult / gameCPS * hashManager.getStudyMult();
break; break;
case CONSTANTS.ClassGymStrength: case CONSTANTS.ClassGymStrength:
cost = CONSTANTS.ClassGymBaseCost * costMult / gameCPS; cost = CONSTANTS.ClassGymBaseCost * costMult / gameCPS;

@ -9,9 +9,11 @@
import { SleeveTaskType } from "./SleeveTaskTypesEnum"; import { SleeveTaskType } from "./SleeveTaskTypesEnum";
import { IPlayer } from "../IPlayer"; import { IPlayer } from "../IPlayer";
import { Person, import {
ITaskTracker, Person,
createTaskTracker } from "../Person"; ITaskTracker,
createTaskTracker
} from "../Person";
import { Augmentation } from "../../Augmentation/Augmentation"; import { Augmentation } from "../../Augmentation/Augmentation";
@ -44,6 +46,11 @@ export class Sleeve extends Person {
return Generic_fromJSON(Sleeve, value.data); return Generic_fromJSON(Sleeve, value.data);
} }
/**
* Stores the name of the class that the player is currently taking
*/
className: string = "";
/** /**
* Stores the type of crime the sleeve is currently attempting * Stores the type of crime the sleeve is currently attempting
* Must match the name of a Crime object * Must match the name of a Crime object
@ -493,6 +500,7 @@ export class Sleeve extends Person {
break; break;
case SleeveTaskType.Class: case SleeveTaskType.Class:
case SleeveTaskType.Gym: case SleeveTaskType.Gym:
this.updateTaskGainRates(p);
retValue = this.gainExperience(p, this.gainRatesForTask, cyclesUsed); retValue = this.gainExperience(p, this.gainRatesForTask, cyclesUsed);
this.gainMoney(p, this.gainRatesForTask, cyclesUsed); this.gainMoney(p, this.gainRatesForTask, cyclesUsed);
break; break;
@ -560,6 +568,7 @@ export class Sleeve extends Person {
this.crimeType = ""; this.crimeType = "";
this.currentTaskLocation = ""; this.currentTaskLocation = "";
this.gymStatType = ""; this.gymStatType = "";
this.className = "";
} }
shockRecovery(p: IPlayer): boolean { shockRecovery(p: IPlayer): boolean {
@ -597,67 +606,50 @@ export class Sleeve extends Person {
// Set exp/money multipliers based on which university. // Set exp/money multipliers based on which university.
// Also check that the sleeve is in the right city // Also check that the sleeve is in the right city
let costMult: number = 1; let costMult: number = 1;
let expMult: number = 1;
switch (universityName.toLowerCase()) { switch (universityName.toLowerCase()) {
case LocationName.AevumSummitUniversity.toLowerCase(): case LocationName.AevumSummitUniversity.toLowerCase():
if (this.city !== CityName.Aevum) { return false; } if (this.city !== CityName.Aevum) { return false; }
this.currentTaskLocation = LocationName.AevumSummitUniversity; this.currentTaskLocation = LocationName.AevumSummitUniversity;
costMult = 4; costMult = 4;
expMult = 3;
break; break;
case LocationName.Sector12RothmanUniversity.toLowerCase(): case LocationName.Sector12RothmanUniversity.toLowerCase():
if (this.city !== CityName.Sector12) { return false; } if (this.city !== CityName.Sector12) { return false; }
this.currentTaskLocation = LocationName.Sector12RothmanUniversity; this.currentTaskLocation = LocationName.Sector12RothmanUniversity;
costMult = 3; costMult = 3;
expMult = 2;
break; break;
case LocationName.VolhavenZBInstituteOfTechnology.toLowerCase(): case LocationName.VolhavenZBInstituteOfTechnology.toLowerCase():
if (this.city !== CityName.Volhaven) { return false; } if (this.city !== CityName.Volhaven) { return false; }
this.currentTaskLocation = LocationName.VolhavenZBInstituteOfTechnology; this.currentTaskLocation = LocationName.VolhavenZBInstituteOfTechnology;
costMult = 5; costMult = 5;
expMult = 4;
break; break;
default: default:
return false; return false;
} }
// Set experience/money gains based on class // Set experience/money gains based on class
// TODO Refactor University Courses into its own class or something
const baseStudyComputerScienceExp: number = 0.5;
const baseDataStructuresExp: number = 1;
const baseNetworksExp: number = 2;
const baseAlgorithmsExp: number = 4;
const baseManagementExp: number = 2;
const baseLeadershipExp: number = 4;
switch (className.toLowerCase()) { switch (className.toLowerCase()) {
case "study computer science": case "study computer science":
this.gainRatesForTask.hack = (baseStudyComputerScienceExp * expMult * this.hacking_exp_mult);
break; break;
case "data structures": case "data structures":
this.gainRatesForTask.hack = (baseDataStructuresExp * expMult * this.hacking_exp_mult);
this.gainRatesForTask.money = -1 * (CONSTANTS.ClassDataStructuresBaseCost * costMult); this.gainRatesForTask.money = -1 * (CONSTANTS.ClassDataStructuresBaseCost * costMult);
break; break;
case "networks": case "networks":
this.gainRatesForTask.hack = (baseNetworksExp * expMult * this.hacking_exp_mult);
this.gainRatesForTask.money = -1 * (CONSTANTS.ClassNetworksBaseCost * costMult); this.gainRatesForTask.money = -1 * (CONSTANTS.ClassNetworksBaseCost * costMult);
break; break;
case "algorithms": case "algorithms":
this.gainRatesForTask.hack = (baseAlgorithmsExp * expMult * this.hacking_exp_mult); this.gainRatesForTask.money = -1 * (CONSTANTS.ClassAlgorithmsBaseCost * costMult);
this.gainRatesForTask.money = -1 * (CONSTANTS.ClassAlgorithmsBaseCost * costMult);
break; break;
case "management": case "management":
this.gainRatesForTask.cha = (baseManagementExp * expMult * this.charisma_exp_mult);
this.gainRatesForTask.money = -1 * (CONSTANTS.ClassManagementBaseCost * costMult); this.gainRatesForTask.money = -1 * (CONSTANTS.ClassManagementBaseCost * costMult);
break; break;
case "leadership": case "leadership":
this.gainRatesForTask.cha = (baseLeadershipExp * expMult * this.charisma_exp_mult);
this.gainRatesForTask.money = -1 * (CONSTANTS.ClassLeadershipBaseCost * costMult); this.gainRatesForTask.money = -1 * (CONSTANTS.ClassLeadershipBaseCost * costMult);
break; break;
default: default:
return false; return false;
} }
this.className = className;
this.currentTask = SleeveTaskType.Class; this.currentTask = SleeveTaskType.Class;
return true; return true;
} }
@ -672,6 +664,112 @@ export class Sleeve extends Person {
return true; return true;
} }
tryBuyAugmentation(p: IPlayer, aug: Augmentation): boolean {
if (!p.canAfford(aug.startingCost)) {
return false;
}
p.loseMoney(aug.startingCost);
this.installAugmentation(aug);
return true;
}
updateTaskGainRates(p: IPlayer): void {
if (this.currentTask === SleeveTaskType.Class) {
let expMult: number = 1;
switch (this.currentTaskLocation.toLowerCase()) {
case LocationName.AevumSummitUniversity.toLowerCase():
expMult = 3;
break;
case LocationName.Sector12RothmanUniversity.toLowerCase():
expMult = 2;
break;
case LocationName.VolhavenZBInstituteOfTechnology.toLowerCase():
expMult = 4;
break;
default:
return;
}
const totalExpMult = expMult * p.hashManager.getStudyMult();
switch (this.className.toLowerCase()) {
case "study computer science":
this.gainRatesForTask.hack = (CONSTANTS.ClassStudyComputerScienceBaseExp * totalExpMult * this.hacking_exp_mult);
break;
case "data structures":
this.gainRatesForTask.hack = (CONSTANTS.ClassDataStructuresBaseExp * totalExpMult * this.hacking_exp_mult);
break;
case "networks":
this.gainRatesForTask.hack = (CONSTANTS.ClassNetworksBaseExp * totalExpMult * this.hacking_exp_mult);
break;
case "algorithms":
this.gainRatesForTask.hack = (CONSTANTS.ClassAlgorithmsBaseExp * totalExpMult * this.hacking_exp_mult);
break;
case "management":
this.gainRatesForTask.cha = (CONSTANTS.ClassManagementBaseExp * totalExpMult * this.charisma_exp_mult);
break;
case "leadership":
this.gainRatesForTask.cha = (CONSTANTS.ClassLeadershipBaseExp * totalExpMult * this.charisma_exp_mult);
break;
default:
break;
}
return;
}
if (this.currentTask === SleeveTaskType.Gym) {
// Get gym exp multiplier
let expMult: number = 1;
switch (this.currentTaskLocation.toLowerCase()) {
case LocationName.AevumCrushFitnessGym.toLowerCase():
expMult = 2;
break;
case LocationName.AevumSnapFitnessGym.toLowerCase():
expMult = 5;
break;
case LocationName.Sector12IronGym.toLowerCase():
expMult = 1;
break;
case LocationName.Sector12PowerhouseGym.toLowerCase():
expMult = 10;
break;
case LocationName.VolhavenMilleniumFitnessGym:
expMult = 4;
break;
default:
return;
}
// Set stat gain rate
const baseGymExp: number = 1;
const totalExpMultiplier = p.hashManager.getTrainingMult() * expMult;
const sanitizedStat: string = this.gymStatType.toLowerCase();
if (sanitizedStat.includes("str")) {
this.gainRatesForTask.str = (baseGymExp * totalExpMultiplier * this.strength_exp_mult);
} else if (sanitizedStat.includes("def")) {
this.gainRatesForTask.def = (baseGymExp * totalExpMultiplier * this.defense_exp_mult);
} else if (sanitizedStat.includes("dex")) {
this.gainRatesForTask.dex = (baseGymExp * totalExpMultiplier * this.dexterity_exp_mult);
} else if (sanitizedStat.includes("agi")) {
this.gainRatesForTask.agi = (baseGymExp * totalExpMultiplier * this.agility_exp_mult);
}
return;
}
console.warn(`Sleeve.updateTaskGainRates() called for unexpected task type ${this.currentTask}`);
}
upgradeMemory(n: number): void {
if (n < 0) {
console.warn(`Sleeve.upgradeMemory() called with negative value: ${n}`);
return;
}
this.memory = Math.min(100, Math.round(this.memory + n));
}
/** /**
* Start work for one of the player's companies * Start work for one of the player's companies
* Returns boolean indicating success * Returns boolean indicating success
@ -698,27 +796,27 @@ export class Sleeve extends Person {
this.gainRatesForTask.hack = companyPosition.hackingExpGain * this.gainRatesForTask.hack = companyPosition.hackingExpGain *
company.expMultiplier * company.expMultiplier *
this.hacking_exp_mult * this.hacking_exp_mult *
BitNodeMultipliers.FactionWorkExpGain; BitNodeMultipliers.CompanyWorkExpGain;
this.gainRatesForTask.str = companyPosition.strengthExpGain * this.gainRatesForTask.str = companyPosition.strengthExpGain *
company.expMultiplier * company.expMultiplier *
this.strength_exp_mult * this.strength_exp_mult *
BitNodeMultipliers.FactionWorkExpGain; BitNodeMultipliers.CompanyWorkExpGain;
this.gainRatesForTask.def = companyPosition.defenseExpGain * this.gainRatesForTask.def = companyPosition.defenseExpGain *
company.expMultiplier * company.expMultiplier *
this.defense_exp_mult * this.defense_exp_mult *
BitNodeMultipliers.FactionWorkExpGain; BitNodeMultipliers.CompanyWorkExpGain;
this.gainRatesForTask.dex = companyPosition.dexterityExpGain * this.gainRatesForTask.dex = companyPosition.dexterityExpGain *
company.expMultiplier * company.expMultiplier *
this.dexterity_exp_mult * this.dexterity_exp_mult *
BitNodeMultipliers.FactionWorkExpGain; BitNodeMultipliers.CompanyWorkExpGain;
this.gainRatesForTask.agi = companyPosition.agilityExpGain * this.gainRatesForTask.agi = companyPosition.agilityExpGain *
company.expMultiplier * company.expMultiplier *
this.agility_exp_mult * this.agility_exp_mult *
BitNodeMultipliers.FactionWorkExpGain; BitNodeMultipliers.CompanyWorkExpGain;
this.gainRatesForTask.cha = companyPosition.charismaExpGain * this.gainRatesForTask.cha = companyPosition.charismaExpGain *
company.expMultiplier * company.expMultiplier *
this.charisma_exp_mult * this.charisma_exp_mult *
BitNodeMultipliers.FactionWorkExpGain; BitNodeMultipliers.CompanyWorkExpGain;
this.currentTaskLocation = companyName; this.currentTaskLocation = companyName;
this.currentTask = SleeveTaskType.Company; this.currentTask = SleeveTaskType.Company;
@ -792,60 +890,48 @@ export class Sleeve extends Person {
// Set exp/money multipliers based on which university. // Set exp/money multipliers based on which university.
// Also check that the sleeve is in the right city // Also check that the sleeve is in the right city
let costMult: number = 1; let costMult: number = 1;
let expMult: number = 1;
switch (gymName.toLowerCase()) { switch (gymName.toLowerCase()) {
case LocationName.AevumCrushFitnessGym.toLowerCase(): case LocationName.AevumCrushFitnessGym.toLowerCase():
if (this.city != CityName.Aevum) { return false; } if (this.city != CityName.Aevum) { return false; }
this.currentTaskLocation = LocationName.AevumCrushFitnessGym; this.currentTaskLocation = LocationName.AevumCrushFitnessGym;
costMult = 3; costMult = 3;
expMult = 2;
break; break;
case LocationName.AevumSnapFitnessGym.toLowerCase(): case LocationName.AevumSnapFitnessGym.toLowerCase():
if (this.city != CityName.Aevum) { return false; } if (this.city != CityName.Aevum) { return false; }
this.currentTaskLocation = LocationName.AevumSnapFitnessGym; this.currentTaskLocation = LocationName.AevumSnapFitnessGym;
costMult = 10; costMult = 10;
expMult = 5;
break; break;
case LocationName.Sector12IronGym.toLowerCase(): case LocationName.Sector12IronGym.toLowerCase():
if (this.city != CityName.Sector12) { return false; } if (this.city != CityName.Sector12) { return false; }
this.currentTaskLocation = LocationName.Sector12IronGym; this.currentTaskLocation = LocationName.Sector12IronGym;
costMult = 1; costMult = 1;
expMult = 1;
break; break;
case LocationName.Sector12PowerhouseGym.toLowerCase(): case LocationName.Sector12PowerhouseGym.toLowerCase():
if (this.city != CityName.Sector12) { return false; } if (this.city != CityName.Sector12) { return false; }
this.currentTaskLocation = LocationName.Sector12PowerhouseGym; this.currentTaskLocation = LocationName.Sector12PowerhouseGym;
costMult = 20; costMult = 20;
expMult = 10;
break; break;
case LocationName.VolhavenMilleniumFitnessGym: case LocationName.VolhavenMilleniumFitnessGym:
if (this.city != CityName.Volhaven) { return false; } if (this.city != CityName.Volhaven) { return false; }
this.currentTaskLocation = LocationName.VolhavenMilleniumFitnessGym; this.currentTaskLocation = LocationName.VolhavenMilleniumFitnessGym;
costMult = 7; costMult = 7;
expMult = 4;
break; break;
default: default:
return false; return false;
} }
// Set experience/money gains based on class // Set experience/money gains based on class
// TODO Refactor University Courses into its own class or something
const baseGymExp: number = 1;
const sanitizedStat: string = stat.toLowerCase(); const sanitizedStat: string = stat.toLowerCase();
// Set cost // Set cost
this.gainRatesForTask.money = -1 * (CONSTANTS.ClassGymBaseCost * costMult); this.gainRatesForTask.money = -1 * (CONSTANTS.ClassGymBaseCost * costMult);
// Set stat gain rate // Validate "stat" argument
if (sanitizedStat.includes("str")) { if (!sanitizedStat.includes("str")
this.gainRatesForTask.str = (baseGymExp * expMult); && !sanitizedStat.includes("def")
} else if (sanitizedStat.includes("def")) { && !sanitizedStat.includes("dex")
this.gainRatesForTask.def = (baseGymExp * expMult); && !sanitizedStat.includes("agi")) {
} else if (sanitizedStat.includes("dex")) {
this.gainRatesForTask.dex = (baseGymExp * expMult);
} else if (sanitizedStat.includes("agi")) {
this.gainRatesForTask.agi = (baseGymExp * expMult);
} else {
return false; return false;
} }
@ -855,25 +941,6 @@ export class Sleeve extends Person {
return true; return true;
} }
tryBuyAugmentation(p: IPlayer, aug: Augmentation): boolean {
if (!p.canAfford(aug.startingCost)) {
return false;
}
p.loseMoney(aug.startingCost);
this.installAugmentation(aug);
return true;
}
upgradeMemory(n: number): void {
if (n < 0) {
console.warn(`Sleeve.upgradeMemory() called with negative value: ${n}`);
return;
}
this.memory = Math.min(100, Math.round(this.memory + n));
}
/** /**
* Serialize the current object to a JSON save state. * Serialize the current object to a JSON save state.
*/ */

@ -566,6 +566,11 @@ function updateSleeveTaskSelector(sleeve: Sleeve, elems: ISleeveUIElems, allSlee
// First selector has class type // First selector has class type
for (let i = 0; i < universitySelectorOptions.length; ++i) { for (let i = 0; i < universitySelectorOptions.length; ++i) {
elems.taskDetailsSelector!.add(createOptionElement(universitySelectorOptions[i])); elems.taskDetailsSelector!.add(createOptionElement(universitySelectorOptions[i]));
// Set initial value
if (sleeve.className === universitySelectorOptions[i]) {
elems.taskDetailsSelector!.selectedIndex = i;
}
} }
// Second selector has which university // Second selector has which university

@ -707,6 +707,11 @@ let Terminal = {
}, },
executeCommand : function(command) { executeCommand : function(command) {
if (Terminal.hackFlag || Terminal.analyzeFlag) {
postError(`Cannot execute command (${command}) while an action is in progress`);
return;
}
// Process any aliases // Process any aliases
command = substituteAliases(command); command = substituteAliases(command);