Initial commit for company code refactor. Split out all components into separate files and converted to typescript

This commit is contained in:
danielyxie 2018-11-15 17:28:23 -08:00
parent 23eef62332
commit d6bdc9433a
22 changed files with 170903 additions and 1557 deletions

58316
dist/engine.bundle.js vendored

File diff suppressed because one or more lines are too long

111061
dist/vendor.bundle.js vendored

File diff suppressed because one or more lines are too long

@ -2,7 +2,7 @@
<html lang="en">
<head>
<meta charset="utf-8">
<title>Bitburner</title>
<title>Bitburner - development</title>
<link rel="apple-touch-icon" sizes="180x180" href="dist/apple-touch-icon.png">
<link rel="icon" type="image/png" sizes="32x32" href="dist/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="dist/favicon-16x16.png">
@ -109,7 +109,7 @@
<div id="script-editor-filename-wrapper">
<p id="script-editor-filename-tag"> <strong style="background-color:#555;">Script name: </strong></p>
<input id="script-editor-filename" type="text" maxlength="30" tabindex="1"/>
<input id="script-editor-filename" type="text" maxlength="30" tabindex="1" />
</div>
<div id="javascript-editor"></div>
@ -159,7 +159,7 @@
<fieldset>
<label for="script-editor-option-maxerr" class="tooltip">Max Error Count</label>
<input type="range" max="1000" min="50" value="200" step="1" name="script-editor-option-maxerr" id="script-editor-option-maxerr"/>
<input type="range" max="1000" min="50" value="200" step="1" name="script-editor-option-maxerr" id="script-editor-option-maxerr" />
<em id="script-editor-option-maxerror-value-label" style="font-style: normal;"></em>
</fieldset>
</div> <!-- End script editor options panel -->
@ -170,7 +170,7 @@
<table id="terminal">
<tr id="terminal-input">
<td id="terminal-input-td" tabindex="2">$
<input type="text" id="terminal-input-text-box" class="terminal-input" tabindex="1" onfocus="this.value = this.value;"/>
<input type="text" id="terminal-input-text-box" class="terminal-input" tabindex="1" onfocus="this.value = this.value;" />
</td>
</tr>
</table>
@ -187,7 +187,7 @@
provides information about each script's production. The scripts are categorized by the hostname of the servers on which
they are running. </p>
<p id="active-scripts-total-prod">Total online production of
Active scripts: <span class="money-gold"><span id="active-scripts-total-production-active">$0.000</span> / sec</span><br/>
Active scripts: <span class="money-gold"><span id="active-scripts-total-production-active">$0.000</span> / sec</span><br />
Total online production since last Aug installation: <span id="active-scripts-total-prod-aug-total" class="money-gold">$0.000</span>
(<span class="money-gold"><span id="active-scripts-total-prod-aug-avg" class="money-gold">$0.000</span> / sec</span>)</p>
<ul class="active-scripts-list" id="active-scripts-list" style="list-style: none;">
@ -201,19 +201,19 @@
The Hacknet is a global, decentralized network of machines. It is used by hackers all around
the world to anonymously share computing power and perform distributed cyberattacks without the
fear of being traced.
<br/><br/>
<br /><br />
Here, you can purchase a Hacknet Node, a specialized machine that can connect and contribute its
resources to the Hacknet network. This allows you to take a small percentage of profits
from hacks performed on the network. Essentially, you are renting out your Node's computing power.
<br/><br/>
<br /><br />
Each Hacknet Node you purchase will passively earn you money. Each Hacknet Node can be upgraded
in order to increase its computing power and thereby increase the profit you earn from it.
</p>
<a id="hacknet-nodes-purchase-button" class="a-link-button"> Purchase Hacknet Node </a>
<br/>
<br />
<div id="hacknet-nodes-money-multipliers-div">
<p id="hacknet-nodes-money">
<span>Money:</span><span id="hacknet-nodes-player-money" class="money-gold"></span><br/>
<span>Money:</span><span id="hacknet-nodes-player-money" class="money-gold"></span><br />
<span>Total Hacknet Node Production:</span><span id="hacknet-nodes-total-production" class="money-gold"></span>
</p>
<span id="hacknet-nodes-multipliers">
@ -471,7 +471,8 @@
<!-- Tutorial content -->
<div id="tutorial-container" class="generic-menupage-container">
<a id="tutorial-getting-started-link" class="a-link-button" href="http://bitburner.wikia.com/wiki/Chapt3rs_Guide_to_Getting_Started_with_Bitburner" target="_blank"> Getting Started </a>
<a id="tutorial-getting-started-link" class="a-link-button"
href="http://bitburner.wikia.com/wiki/Chapt3rs_Guide_to_Getting_Started_with_Bitburner" target="_blank"> Getting Started </a>
<a id="tutorial-networking-link" class="a-link-button"> Servers & Networking </a>
<a id="tutorial-hacking-link" class="a-link-button"> Hacking </a>
<a id="tutorial-scripts-link" class="a-link-button"> Scripts </a>
@ -480,7 +481,8 @@
<a id="tutorial-jobs-link" class="a-link-button"> Companies and Infiltration </a>
<a id="tutorial-factions-link" class="a-link-button"> Factions </a>
<a id="tutorial-augmentations-link" class="a-link-button"> Augmentations </a>
<a id="tutorial-shortcuts-link" class="a-link-button" href="https://bitburner.wikia.com/wiki/Shortcuts" target="_blank"> Keyboard Shortcuts </a>
<a id="tutorial-shortcuts-link" class="a-link-button"
href="https://bitburner.wikia.com/wiki/Shortcuts" target="_blank"> Keyboard Shortcuts </a>
<a id="tutorial-back-button" class="a-link-button"> Back </a>
<p id="tutorial-text"> </p>
@ -571,7 +573,7 @@
<p id="location-slums-description">
You have entered the Slums, a poverty-ridden district filled with gangs, criminals, and
other shadowy entities. The city's government and police have neglected this area for years...
<br/><br/><br/>
<br /><br /><br />
In the Slums, you can commit crimes to earn money and experience. Crime attempts are not always
successful. Your chance at successfully committing a crime is determined by your stats.
</p>
@ -618,7 +620,7 @@
<div id="stock-market-container" class="generic-menupage-container">
<p>
Welcome to the World Stock Exchange (WSE)! <br/><br/>
Welcome to the World Stock Exchange (WSE)! <br /><br />
To begin trading, you must first purchase an account. WSE accounts will persist
after you 'reset' by installing Augmentations.
@ -631,7 +633,7 @@
TIX, short for Trade Information eXchange, is the communications protocol supported by the WSE.
Purchasing access to the TIX API lets you write code to create your own algorithmic/automated
trading strategies.
<br/><br/>
<br /><br />
If you purchase access to the TIX API, you will retain that access even after
you 'reset' by installing Augmentations.
</p>
@ -641,7 +643,7 @@
<p>
Four Sigma's (4S) Market Data Feed provides information about stocks
that will help your trading strategies.
<br/><br/>
<br /><br />
If you purchase access to 4S Market Data and/or the 4S TIX API, you will
retain that access even after you 'reset' by installing Augmentations.
</p>
@ -659,7 +661,7 @@
<a id="stock-market-mode" class="a-link-button tooltip"></a>
<a id="stock-market-expand-tickers" class="a-link-button tooltip">Expand tickers</a>
<a id="stock-market-collapse-tickers" class="a-link-button tooltip">Collapse tickers</a>
<br/><br/>
<br /><br />
<input id="stock-market-watchlist-filter" type="text" placeholder="Filter Stocks by symbol (comma-separated list)"/>
<a id="stock-market-watchlist-filter-update" class="a-link-button"> Update Watchlist </a>
<ul id="stock-market-list" style="list-style:none;">
@ -689,7 +691,7 @@
<div id="yes-no-text-input-box-container" class="popup-box-container">
<div id="yes-no-text-input-box-content" class="popup-box-content">
<p id="yes-no-text-input-box-text"> </p>
<input type="text" id="yes-no-text-input-box-input" pattern="[a-zA-Z0-9-_]" maxlength="30"/>
<input type="text" id="yes-no-text-input-box-input" pattern="[a-zA-Z0-9-_]" maxlength="30" />
<button id="yes-no-text-input-box-yes" class="popup-box-button"> Yes </button>
<button id="yes-no-text-input-box-no" class="popup-box-button"> No </button>
</div>
@ -701,7 +703,7 @@
<p id="faction-invitation-box-text"> </p>
<p id="faction-invitation-box-message"> </p>
<p id="faction-invitation-box-warning">
Would you like to join? <br/> <br/>
Would you like to join? <br /> <br />
Warning: Joining this faction may prevent you from joining other factions during this run!
</p>
<button id="faction-invitation-box-yes" class="popup-box-button"> Yes </button>
@ -714,8 +716,8 @@
<div id="infiltration-box-content" class="popup-box-content">
<p id="infiltration-box-text"> </p>
<button id="infiltration-box-sell" class="a-link-button"> Sell on Black Market </button> <br/><br/>
<select id="infiltration-faction-select"> </select> <br/>
<button id="infiltration-box-sell" class="a-link-button"> Sell on Black Market </button> <br /><br />
<select id="infiltration-faction-select"> </select> <br />
<button id="infiltration-box-faction" class="a-link-button"> Give to Faction for Reputation </button>
</div>
@ -801,7 +803,7 @@
<div id="game-options-content" class="game-options-box">
<button id="game-options-close-button">&times;</button>
<h1> Game Options </h1>
<br/>
<br />
<div id="game-options-left-panel">
<!-- Netscript execution time -->
<fieldset>
@ -813,7 +815,7 @@
</span>
</label>
<input type="range" max="100" min="10" step="1" name="settingsNSExecTimeRangeVal" id="settingsNSExecTimeRangeVal" value="25"/>
<input type ="range" max="100" min="10" step="1" name="settingsNSExecTimeRangeVal" id="settingsNSExecTimeRangeVal" value="25" />
<em id="settingsNSExecTimeRangeValLabel" style="font-style: normal;"></em>
</fieldset>
@ -827,7 +829,7 @@
</span>
</label>
<input type="range" max="100" min="20" step="1" name="settingsNSLogRangeVal" id="settingsNSLogRangeVal" value="50"/>
<input type="range" max="100" min="20" step="1" name="settingsNSLogRangeVal" id="settingsNSLogRangeVal" value="50" />
<em id="settingsNSLogRangeValLabel" style="font-style: normal;"></em>
</fieldset>
@ -841,7 +843,7 @@
</span>
</label>
<input type="range" max="100" min="20" step="1" name="settingsNSPortRangeVal" id="settingsNSPortRangeVal" value="50"/>
<input type="range" max="100" min="20" step="1" name="settingsNSPortRangeVal" id="settingsNSPortRangeVal" value="50" />
<em id="settingsNSPortRangeValLabel" style="font-style: normal;"></em>
</fieldset>
@ -853,7 +855,7 @@
</span>
</label>
<input type="range" max="600" min="0" step="1" name="settingsAutosaveIntervalVal" id="settingsAutosaveIntervalVal" value="60"/>
<input type="range" max="600" min="0" step="1" name="settingsAutosaveIntervalVal" id="settingsAutosaveIntervalVal" value="60" />
<em id="settingsAutosaveIntervalValLabel" style="font-style: normal;"></em>
</fieldset>
@ -965,7 +967,7 @@
<a id="save-game-link" class="a-link-button" style="display:inline-block;width:46%;"> Save Game </a>
<a id="delete-game-link" class="a-link-button" style="display:inline-block;width:46%;"> Delete Game </a>
<a id="export-game-link" class="a-link-button" style="display:inline-block;width:46%;"> Export Game </a>
<input type="file" id="import-game-file-selector" name="file"/>
<input type="file" id="import-game-file-selector" name="file" />
<a id="import-game-link" class="a-link-button" style="display:inline-block;width:46%;"> Import Game </a>
<a id="debug-delete-scripts-link" class="a-link-button tooltip" style="display:block;width:46%;">
(DEBUG) Delete Active Scripts

32
src/Company/Companies.ts Normal file

@ -0,0 +1,32 @@
// Constructs all CompanyPosition objects using the metadata in data/companypositions.ts
import { companiesMetadata } from "./data/CompaniesMetadata";
import { Company, IConstructorParams } from "./Company";
import { IMap } from "../types";
import { Reviver } from "../../utils/JSONReviver";
export let Companies: IMap<Company> = {};
function addCompany(params: IConstructorParams) {
if (Companies[params.name] != null) {
console.warn(`Duplicate Company Position being defined: ${params.name}`);
}
Companies[params.name] = new Company(params);
}
// Used to initialize new Company objects for the Companies map
// Called when creating new game or after a prestige/reset
export function initCompanies() {
companiesMetadata.forEach((e) => {
addCompany(e);
});
}
// Used to load Companies map from a save
export function loadCompanies(saveString: string) {
Companies = JSON.parse(saveString, Reviver);
}
// Utility function to check if a string is valid company name
export function companyExists(name: string) {
return Companies.hasOwnProperty(name);
}

File diff suppressed because it is too large Load Diff

135
src/Company/Company.ts Normal file

@ -0,0 +1,135 @@
import { Generic_fromJSON, Generic_toJSON, Reviver } from "../../utils/JSONReviver";
import { CompanyPosition } from "./CompanyPosition";
import { CONSTANTS } from "../Constants";
import { IMap } from "../types";
export interface IConstructorParams {
name: string;
info: string;
companyPositions: IMap<boolean>;
expMultiplier: number;
salaryMultiplier: number;
jobStatReqOffset: number;
}
const DefaultConstructorParams: IConstructorParams = {
name: "",
info: "",
companyPositions: {},
expMultiplier: 1,
salaryMultiplier: 1,
jobStatReqOffset: 0,
}
export class Company {
/**
* Initiatizes a Company from a JSON save state.
*/
static fromJSON(value: any): Company {
return Generic_fromJSON(Company, value.data);
}
/**
* Company name
*/
name: string;
/**
* Description and general information about company
*/
info: string;
/**
* Object that holds all available positions in this Company.
* Position names are held in keys.
* The values for the keys don't matter, but we'll make them booleans
*
* Must match names of Company Positions, defined in data/companypositionnames.ts
*/
companyPositions: IMap<boolean>;
/**
* Company-specific multiplier for earnings
*/
expMultiplier: number;
salaryMultiplier: number;
/**
* The additional levels of stats you need to quality for a job
* in this company.
*
* For example, the base stat requirement for an intern position is 1.
* But if a company has a offset of 200, then you would need stat(s) of 201
*/
jobStatReqOffset: number;
/**
* Properties to track the player's progress in this company
*/
isPlayerEmployed: boolean;
playerReputation: number;
favor: number;
rolloverRep: number;
constructor(p: IConstructorParams = DefaultConstructorParams) {
this.name = p.name;
this.info = p.info;
this.companyPositions = p.companyPositions;
this.expMultiplier = p.expMultiplier;
this.salaryMultiplier = p.salaryMultiplier;
this.jobStatReqOffset = p.jobStatReqOffset;
this.isPlayerEmployed = false;
this.playerReputation = 1;
this.favor = 0;
this.rolloverRep = 0;
}
hasPosition(pos: CompanyPosition | string): boolean {
if (pos instanceof CompanyPosition) {
return (this.companyPositions[pos.name] != null);
} else {
return (this.companyPositions[pos] != null);
}
}
gainFavor(): void {
if (this.favor == null) { this.favor = 0; }
if (this.rolloverRep == null) { this.rolloverRep = 0; }
var res = this.getFavorGain();
if (res.length != 2) {
console.error("Invalid result from getFavorGain() function");
return;
}
this.favor += res[0];
this.rolloverRep = res[1];
}
getFavorGain(): number[] {
if (this.favor == null) { this.favor = 0; }
if (this.rolloverRep == null) { this.rolloverRep = 0; }
let favorGain = 0, rep = this.playerReputation + this.rolloverRep;
let reqdRep = CONSTANTS.CompanyReputationToFavorBase *
Math.pow(CONSTANTS.CompanyReputationToFavorMult, this.favor);
while(rep > 0) {
if (rep >= reqdRep) {
++favorGain;
rep -= reqdRep;
} else {
break;
}
reqdRep *= CONSTANTS.FactionReputationToFavorMult;
}
return [favorGain, rep];
}
/**
* Serialize the current file to a JSON save state.
*/
toJSON(): any {
return Generic_toJSON("Company", this);
}
}
Reviver.constructors.Company = Company;

@ -1,12 +1,12 @@
import { Generic_fromJSON, Generic_toJSON, Reviver } from "/utils/JSONReviver";
import { CONSTANTS } from "/src/Constants";
import * as names from "/src/Company/data/companypositionname";
import { CONSTANTS } from "../Constants";
import * as names from "./data/CompanyPositionNames";
/* tslint:disable:completed-docs */
interface ConstructorParams {
name: string,
baseSalary: number,
export interface IConstructorParams {
name: string;
nextPosition: string | null;
baseSalary: number;
repMultiplier: number;
reqdHacking?: number;
@ -33,17 +33,15 @@ interface ConstructorParams {
}
export class CompanyPosition {
/**
* Initializes a CompanyPosition object from a JSON save state
*/
static fromJSON(value: any): CompanyPosition {
return Generic_fromJSON(CompanyPosition, value.data);
}
/**
* Position title
*/
positionName: string;
name: string;
/**
* Title of next position to be promoted to
*/
nextPosition: string | null;
/**
* Base salary for this position ($ per 200ms game cycle)
@ -54,7 +52,7 @@ export class CompanyPosition {
/**
* Reputation multiplier
*/
positionMultiplier: number;
repMultiplier: number;
/**
* Required stats to earn this position
@ -91,18 +89,19 @@ export class CompanyPosition {
agilityExpGain: number;
charismaExpGain: number;
constructor(p: ConstructorParams) {
constructor(p: IConstructorParams) {
this.name = p.name;
this.nextPosition = p.nextPosition;
this.baseSalary = p.baseSalary;
this.repMultiplier = p.repMultiplier;
this.reqdHacking = (p.reqdHacking != null) ? p.reqdHacking : 0;
this.reqdStrength = (p.reqdStrength != null) ? p.reqdStrength : 0;
this.reqdDefense = (p.reqdDefense != null) ? p.reqdDefense : 0;
this.reqdDexterity = (p.reqdDexterity != null) ? p.reqdDexterity : 0;
this.reqdAgility = (p.reqdAgility != null) ? p.reqdAgility : 0;
this.reqdCharisma = (p.reqdCharisma != null) ? p.reqdCharisma : 0;
this.reqdReputation = (p.reqdReputation != null) ? p.reqdReputation : 0;
this.requiredHacking = (p.reqdHacking != null) ? p.reqdHacking : 0;
this.requiredStrength = (p.reqdStrength != null) ? p.reqdStrength : 0;
this.requiredDefense = (p.reqdDefense != null) ? p.reqdDefense : 0;
this.requiredDexterity = (p.reqdDexterity != null) ? p.reqdDexterity : 0;
this.requiredAgility = (p.reqdAgility != null) ? p.reqdAgility : 0;
this.requiredCharisma = (p.reqdCharisma != null) ? p.reqdCharisma : 0;
this.requiredReputation = (p.reqdReputation != null) ? p.reqdReputation : 0;
this.hackingEffectiveness = (p.hackingEffectiveness != null) ? p.hackingEffectiveness : 0;
this.strengthEffectiveness = (p.strengthEffectiveness != null) ? p.strengthEffectiveness : 0;
@ -132,7 +131,7 @@ export class CompanyPosition {
const agiRatio: number = this.agilityEffectiveness * agi / CONSTANTS.MaxSkillLevel;
const chaRatio: number = this.charismaEffectiveness * cha / CONSTANTS.MaxSkillLevel;
let reputationGain: number = this.positionMultiplier * (hackRatio + strRatio + defRatio + dexRatio + agiRatio + chaRatio) / 100;
let reputationGain: number = this.repMultiplier * (hackRatio + strRatio + defRatio + dexRatio + agiRatio + chaRatio) / 100;
if (isNaN(reputationGain)) {
console.error("Company reputation gain calculated to be NaN");
reputationGain = 0;
@ -180,13 +179,4 @@ export class CompanyPosition {
isPartTimeJob(): boolean {
return names.PartTimeCompanyPositions.includes(this.name);
}
/**
* Serialize the current file to a JSON save state.
*/
toJSON(): any {
return Generic_toJSON("CompanyPosition", this);
}
}
Reviver.constructors.CompanyPosition = CompanyPosition;

@ -0,0 +1,17 @@
// Constructs all CompanyPosition objects using the metadata in data/companypositions.ts
import { companyPositionMetadata } from "./data/CompanyPositionsMetadata";
import { CompanyPosition, IConstructorParams } from "./CompanyPosition";
import { IMap } from "../types";
export const CompanyPositions: IMap<CompanyPosition> = {};
function addCompanyPosition(params: IConstructorParams) {
if (CompanyPositions[params.name] != null) {
console.warn(`Duplicate Company Position being defined: ${params.name}`);
}
CompanyPositions[params.name] = new CompanyPosition(params);
}
companyPositionMetadata.forEach((e) => {
addCompanyPosition(e);
});

@ -0,0 +1,40 @@
import { Company } from "./Company";
import { CompanyPosition } from "./CompanyPosition";
/**
* Returns a string with the given CompanyPosition's stat requirements
*/
export function getJobRequirementText(company: Company, pos: CompanyPosition, tooltiptext: boolean = false): string {
let reqText: string = "";
const offset: number = company.jobStatReqOffset;
const reqHacking: number = pos.requiredHacking > 0 ? pos.requiredHacking+offset : 0;
const reqStrength: number = pos.requiredStrength > 0 ? pos.requiredStrength+offset : 0;
const reqDefense: number = pos.requiredDefense > 0 ? pos.requiredDefense+offset : 0;
const reqDexterity: number = pos.requiredDexterity > 0 ? pos.requiredDexterity+offset : 0;
const reqAgility: number = pos.requiredDexterity > 0 ? pos.requiredDexterity+offset : 0;
const reqCharisma: number = pos.requiredCharisma > 0 ? pos.requiredCharisma+offset : 0;
const reqRep: number = pos.requiredReputation;
if (tooltiptext) {
reqText = "Requires:<br>";
reqText += (reqHacking.toString() + " hacking<br>");
reqText += (reqStrength.toString() + " strength<br>");
reqText += (reqDefense.toString() + " defense<br>");
reqText += (reqDexterity.toString() + " dexterity<br>");
reqText += (reqAgility.toString() + " agility<br>");
reqText += (reqCharisma.toString() + " charisma<br>");
reqText += (reqRep.toString() + " reputation");
} else {
reqText = "(Requires ";
if (reqHacking > 0) {reqText += (reqHacking + " hacking, ");}
if (reqStrength > 0) {reqText += (reqStrength + " strength, ");}
if (reqDefense > 0) {reqText += (reqDefense + " defense, ");}
if (reqDexterity > 0) {reqText += (reqDexterity + " dexterity, ");}
if (reqAgility > 0) {reqText += (reqAgility + " agility, ");}
if (reqCharisma > 0) {reqText += (reqCharisma + " charisma, ");}
if (reqRep > 1) {reqText += (reqRep + " reputation, ");}
reqText = reqText.substring(0, reqText.length - 2);
reqText += ")";
}
return reqText;
}

@ -0,0 +1,13 @@
// Function that returns the next Company Position in the "ladder"
// i.e. the next position to get promoted to
import { CompanyPosition } from "./CompanyPosition";
import { CompanyPositions } from "./CompanyPositions";
export function getNextCompanyPosition(currPos: CompanyPosition | null): CompanyPosition | null {
if (currPos == null) { return null; }
const nextPosName: string | null = currPos.nextPosition;
if (nextPosName == null) { return null; }
return CompanyPositions[nextPosName];
}

1
src/Company/README.md Normal file

@ -0,0 +1 @@
Implementation of Company and Job related mechanics

@ -0,0 +1,545 @@
import { IConstructorParams } from "../Company";
import { Locations } from "../../Locations";
import * as posNames from "./CompanyPositionNames";
import { SafeObjectAssign } from "../../../utils/SafeObjectAssign";
import { IMap } from "../../types";
// Create Objects containing Company Positions by category
// Will help in metadata construction later
const AllSoftwarePositions: IMap<boolean> = {};
const AllITPositions: IMap<boolean> = {};
const AllNetworkEngineerPositions: IMap<boolean> = {};
const AllTechnologyPositions: IMap<boolean> = {};
const AllBusinessPositions: IMap<boolean> = {};
const AllAgentPositions: IMap<boolean> = {};
const AllSecurityPositions: IMap<boolean> = {};
const AllSoftwareConsultantPositions: IMap<boolean> = {};
const AllBusinessConsultantPositions: IMap<boolean> = {};
const SoftwarePositionsUpToHeadOfEngineering: IMap<boolean> = {};
const SoftwarePositionsUpToLeadDeveloper: IMap<boolean> = {};
const BusinessPositionsUpToOperationsManager: IMap<boolean> = {};
const WaiterOnly: IMap<boolean> = {};
const EmployeeOnly: IMap<boolean> = {};
const PartTimeWaiterOnly: IMap<boolean> = {};
const PartTimeEmployeeOnly: IMap<boolean> = {};
const OperationsManagerOnly: IMap<boolean> = {};
const CEOOnly: IMap<boolean> = {};
posNames.SoftwareCompanyPositions.forEach((e) => {
AllSoftwarePositions[e] = true;
AllTechnologyPositions[e] = true;
});
posNames.ITCompanyPositions.forEach((e) => {
AllITPositions[e] = true;
AllTechnologyPositions[e] = true;
});
posNames.NetworkEngineerCompanyPositions.forEach((e) => {
AllNetworkEngineerPositions[e] = true;
AllTechnologyPositions[e] = true;
});
AllTechnologyPositions[posNames.SecurityEngineerCompanyPositions[0]] = true;
posNames.BusinessCompanyPositions.forEach((e) => {
AllBusinessPositions[e] = true;
});
posNames.SecurityCompanyPositions.forEach((e) => {
AllSecurityPositions[e] = true;
});
posNames.AgentCompanyPositions.forEach((e) => {
AllAgentPositions[e] = true;
});
posNames.SoftwareConsultantCompanyPositions.forEach((e) => {
AllSoftwareConsultantPositions[e] = true;
});
posNames.BusinessConsultantCompanyPositions.forEach((e) => {
AllBusinessConsultantPositions[e] = true;
});
for (let i = 0; i < posNames.SoftwareCompanyPositions.length; ++i) {
const e = posNames.SoftwareCompanyPositions[i];
if (i <= 5) {
SoftwarePositionsUpToHeadOfEngineering[e] = true;
}
if (i <= 3) {
SoftwarePositionsUpToLeadDeveloper[e] = true;
}
}
for (let i = 0; i < posNames.BusinessCompanyPositions.length; ++i) {
const e = posNames.BusinessCompanyPositions[i];
if (i <= 3) {
BusinessPositionsUpToOperationsManager[e] = true;
}
}
WaiterOnly[posNames.MiscCompanyPositions[0]] = true;
EmployeeOnly[posNames.MiscCompanyPositions[1]] = true;
PartTimeWaiterOnly[posNames.PartTimeCompanyPositions[0]] = true;
PartTimeEmployeeOnly[posNames.PartTimeCompanyPositions[1]] = true;
OperationsManagerOnly[posNames.BusinessCompanyPositions[3]] = true;
CEOOnly[posNames.BusinessCompanyPositions[5]] = true;
// Metadata
export const companiesMetadata: IConstructorParams[] = [
{
name: Locations.AevumECorp,
info: "",
companyPositions: Object.assign({},
AllTechnologyPositions,
AllBusinessPositions,
AllSecurityPositions
),
expMultiplier: 3,
salaryMultiplier: 3,
jobStatReqOffset: 249,
},
{
name: Locations.Sector12MegaCorp,
info: "",
companyPositions: Object.assign({},
AllTechnologyPositions,
AllBusinessPositions,
AllSecurityPositions
),
expMultiplier: 3,
salaryMultiplier: 3,
jobStatReqOffset: 249,
},
{
name: Locations.AevumBachmanAndAssociates,
info: "",
companyPositions: Object.assign({},
AllTechnologyPositions,
AllBusinessPositions,
AllSecurityPositions
),
expMultiplier: 2.6,
salaryMultiplier: 2.6,
jobStatReqOffset: 224,
},
{
name: Locations.Sector12BladeIndustries,
info: "",
companyPositions: Object.assign({},
AllTechnologyPositions,
AllBusinessPositions,
AllSecurityPositions
),
expMultiplier: 2.75,
salaryMultiplier: 2.75,
jobStatReqOffset: 224,
},
{
name: Locations.VolhavenNWO,
info: "",
companyPositions: Object.assign({},
AllTechnologyPositions,
AllBusinessPositions,
AllSecurityPositions
),
expMultiplier: 2.75,
salaryMultiplier: 2.75,
jobStatReqOffset: 249,
},
{
name: Locations.AevumClarkeIncorporated,
info: "",
companyPositions: Object.assign({},
AllTechnologyPositions,
AllBusinessPositions,
AllSecurityPositions
),
expMultiplier: 2.25,
salaryMultiplier: 2.25,
jobStatReqOffset: 224,
},
{
name: Locations.VolhavenOmniTekIncorporated,
info: "",
companyPositions: Object.assign({},
AllTechnologyPositions,
AllBusinessPositions,
AllSecurityPositions
),
expMultiplier: 2.25,
salaryMultiplier: 2.25,
jobStatReqOffset: 224,
},
{
name: Locations.Sector12FourSigma,
info: "",
companyPositions: Object.assign({},
AllTechnologyPositions,
AllBusinessPositions,
AllSecurityPositions
),
expMultiplier: 2.5,
salaryMultiplier: 2.5,
jobStatReqOffset: 224,
},
{
name: Locations.ChongqingKuaiGongInternational,
info: "",
companyPositions: Object.assign({},
AllTechnologyPositions,
AllBusinessPositions,
AllSecurityPositions
),
expMultiplier: 2.2,
salaryMultiplier: 2.2,
jobStatReqOffset: 224,
},
{
name: Locations.AevumFulcrumTechnologies,
info: "",
companyPositions: Object.assign({},
AllTechnologyPositions,
AllBusinessPositions
),
expMultiplier: 2,
salaryMultiplier: 2,
jobStatReqOffset: 224,
},
{
name: Locations.IshimaStormTechnologies,
info: "",
companyPositions: Object.assign({},
AllTechnologyPositions,
AllSoftwareConsultantPositions,
AllBusinessPositions
),
expMultiplier: 1.8,
salaryMultiplier: 1.8,
jobStatReqOffset: 199,
},
{
name: Locations.NewTokyoDefComm,
info: "",
companyPositions: Object.assign({},
CEOOnly,
AllTechnologyPositions,
AllSoftwareConsultantPositions
),
expMultiplier: 1.75,
salaryMultiplier: 1.75,
jobStatReqOffset: 199,
},
{
name: Locations.VolhavenHeliosLabs,
info: "",
companyPositions: Object.assign({},
CEOOnly,
AllTechnologyPositions,
AllSoftwareConsultantPositions
),
expMultiplier: 1.8,
salaryMultiplier: 1.8,
jobStatReqOffset: 199,
},
{
name: Locations.NewTokyoVitaLife,
info: "",
companyPositions: Object.assign({},
AllTechnologyPositions,
AllBusinessPositions,
AllSoftwareConsultantPositions
),
expMultiplier: 1.8,
salaryMultiplier: 1.8,
jobStatReqOffset: 199,
},
{
name: Locations.Sector12IcarusMicrosystems,
info: "",
companyPositions: Object.assign({},
AllTechnologyPositions,
AllBusinessPositions,
AllSoftwareConsultantPositions
),
expMultiplier: 1.9,
salaryMultiplier: 1.9,
jobStatReqOffset: 199,
},
{
name: Locations.Sector12UniversalEnergy,
info: "",
companyPositions: Object.assign({},
AllTechnologyPositions,
AllBusinessPositions,
AllSoftwareConsultantPositions
),
expMultiplier: 2,
salaryMultiplier: 2,
jobStatReqOffset: 199,
},
{
name: Locations.AevumGalacticCybersystems,
info: "",
companyPositions: Object.assign({},
AllTechnologyPositions,
AllBusinessPositions,
AllSoftwareConsultantPositions
),
expMultiplier: 1.9,
salaryMultiplier: 1.9,
jobStatReqOffset: 199,
},
{
name: Locations.AevumAeroCorp,
info: "",
companyPositions: Object.assign({},
CEOOnly,
OperationsManagerOnly,
AllTechnologyPositions,
AllSecurityPositions
),
expMultiplier: 1.7,
salaryMultiplier: 1.7,
jobStatReqOffset: 199,
},
{
name: Locations.VolhavenOmniaCybersystems,
info: "",
companyPositions: SafeObjectAssign(
CEOOnly,
OperationsManagerOnly,
AllTechnologyPositions,
AllSecurityPositions,
),
expMultiplier: 1.7,
salaryMultiplier: 1.7,
jobStatReqOffset: 199,
},
{
name: Locations.ChongqingSolarisSpaceSystems,
info: "",
companyPositions: SafeObjectAssign(
CEOOnly,
OperationsManagerOnly,
AllTechnologyPositions,
AllSecurityPositions,
),
expMultiplier: 1.7,
salaryMultiplier: 1.7,
jobStatReqOffset: 199,
},
{
name: Locations.Sector12DeltaOne,
info: "",
companyPositions: SafeObjectAssign(
CEOOnly,
OperationsManagerOnly,
AllTechnologyPositions,
AllSecurityPositions,
),
expMultiplier: 1.6,
salaryMultiplier: 1.6,
jobStatReqOffset: 199,
},
{
name: Locations.NewTokyoGlobalPharmaceuticals,
info: "",
companyPositions: SafeObjectAssign(
AllTechnologyPositions,
AllBusinessPositions,
AllSoftwareConsultantPositions,
AllSecurityPositions
),
expMultiplier: 1.8,
salaryMultiplier: 1.8,
jobStatReqOffset: 224,
},
{
name: Locations.IshimaNovaMedical,
info: "",
companyPositions: SafeObjectAssign(
AllTechnologyPositions,
AllBusinessPositions,
AllSoftwareConsultantPositions,
AllSecurityPositions
),
expMultiplier: 1.75,
salaryMultiplier: 1.75,
jobStatReqOffset: 199,
},
{
name: Locations.Sector12CIA,
info: "",
companyPositions: SafeObjectAssign(
SoftwarePositionsUpToHeadOfEngineering,
AllNetworkEngineerPositions,
AllITPositions,
AllSecurityPositions,
AllAgentPositions
),
expMultiplier: 2,
salaryMultiplier: 2,
jobStatReqOffset: 149,
},
{
name: Locations.Sector12NSA,
info: "",
companyPositions: SafeObjectAssign(
SoftwarePositionsUpToHeadOfEngineering,
AllNetworkEngineerPositions,
AllITPositions,
AllSecurityPositions,
AllAgentPositions
),
expMultiplier: 2,
salaryMultiplier: 2,
jobStatReqOffset: 149,
},
{
name: Locations.AevumWatchdogSecurity,
info: "",
companyPositions: SafeObjectAssign(
SoftwarePositionsUpToHeadOfEngineering,
AllNetworkEngineerPositions,
AllITPositions,
AllSecurityPositions,
AllAgentPositions,
AllSoftwareConsultantPositions
),
expMultiplier: 1.5,
salaryMultiplier: 1.5,
jobStatReqOffset: 124,
},
{
name: Locations.VolhavenLexoCorp,
info: "",
companyPositions: SafeObjectAssign(
AllTechnologyPositions,
AllSoftwareConsultantPositions,
AllBusinessPositions,
AllSecurityPositions
),
expMultiplier: 1.4,
salaryMultiplier: 1.4,
jobStatReqOffset: 99,
},
{
name: Locations.AevumRhoConstruction,
info: "",
companyPositions: SafeObjectAssign(
SoftwarePositionsUpToLeadDeveloper,
BusinessPositionsUpToOperationsManager
),
expMultiplier: 1.3,
salaryMultiplier: 1.3,
jobStatReqOffset: 49,
},
{
name: Locations.Sector12AlphaEnterprises,
info: "",
companyPositions: SafeObjectAssign(
SoftwarePositionsUpToLeadDeveloper,
BusinessPositionsUpToOperationsManager,
AllSoftwareConsultantPositions
),
expMultiplier: 1.5,
salaryMultiplier: 1.5,
jobStatReqOffset: 99,
},
{
name: Locations.AevumPolice,
info: "",
companyPositions: SafeObjectAssign(
AllSecurityPositions,
SoftwarePositionsUpToLeadDeveloper
),
expMultiplier: 1.3,
salaryMultiplier: 1.3,
jobStatReqOffset: 99,
},
{
name: Locations.VolhavenSysCoreSecurities,
info: "",
companyPositions: SafeObjectAssign(
AllTechnologyPositions
),
expMultiplier: 1.3,
salaryMultiplier: 1.3,
jobStatReqOffset: 124,
},
{
name: Locations.VolhavenCompuTek,
info: "",
companyPositions: SafeObjectAssign(
AllTechnologyPositions
),
expMultiplier: 1.2,
salaryMultiplier: 1.2,
jobStatReqOffset: 74,
},
{
name: Locations.AevumNetLinkTechnologies,
info: "",
companyPositions: SafeObjectAssign(
AllTechnologyPositions
),
expMultiplier: 1.2,
salaryMultiplier: 1.2,
jobStatReqOffset: 99,
},
{
name: Locations.Sector12CarmichaelSecurity,
info: "",
companyPositions: SafeObjectAssign(
AllTechnologyPositions,
AllAgentPositions,
AllSecurityPositions
),
expMultiplier: 1.2,
salaryMultiplier: 1.2,
jobStatReqOffset: 74,
},
{
name: Locations.Sector12FoodNStuff,
info: "",
companyPositions: SafeObjectAssign(
EmployeeOnly, PartTimeEmployeeOnly
),
expMultiplier: 1,
salaryMultiplier: 1,
jobStatReqOffset: 0,
},
{
name: Locations.Sector12JoesGuns,
info: "",
companyPositions: SafeObjectAssign(
EmployeeOnly, PartTimeEmployeeOnly
),
expMultiplier: 1,
salaryMultiplier: 1,
jobStatReqOffset: 0,
},
{
name: Locations.IshimaOmegaSoftware,
info: "",
companyPositions: SafeObjectAssign(
AllSoftwarePositions,
AllSoftwareConsultantPositions,
AllITPositions
),
expMultiplier: 1.1,
salaryMultiplier: 1.1,
jobStatReqOffset: 49,
},
{
name: Locations.NewTokyoNoodleBar,
info: "",
companyPositions: SafeObjectAssign(
WaiterOnly, PartTimeWaiterOnly
),
expMultiplier: 1,
salaryMultiplier: 1,
jobStatReqOffset: 0,
},
]

@ -0,0 +1,602 @@
// Metadata used for constructing Company Positions
import { IConstructorParams } from "../CompanyPosition";
import * as posNames from "./CompanyPositionNames";
export const companyPositionMetadata: IConstructorParams[] = [
{
name: posNames.SoftwareCompanyPositions[0], // Software Enginering Intern
nextPosition: posNames.SoftwareCompanyPositions[1], // Junior Software Engineer
baseSalary: 33,
charismaEffectiveness: 15,
charismaExpGain: 0.02,
hackingEffectiveness: 85,
hackingExpGain: 0.05,
reqdHacking: 1,
repMultiplier: 0.9,
},
{
name: posNames.SoftwareCompanyPositions[1], // Junior Software Engineer
nextPosition: posNames.SoftwareCompanyPositions[2], // Senior Software Engineer
baseSalary: 80,
charismaEffectiveness: 15,
charismaExpGain: 0.05,
hackingEffectiveness: 85,
hackingExpGain: 0.1,
reqdHacking: 51,
reqdReputation: 8e3,
repMultiplier: 1.1,
},
{
name: posNames.SoftwareCompanyPositions[2], // Senior Software Engineer
nextPosition: posNames.SoftwareCompanyPositions[3], // Lead Software Developer
baseSalary: 165,
charismaEffectiveness: 20,
charismaExpGain: 0.08,
hackingEffectiveness: 80,
hackingExpGain: 0.4,
reqdCharisma: 51,
reqdHacking: 251,
reqdReputation: 40e3,
repMultiplier: 1.3,
},
{
name: posNames.SoftwareCompanyPositions[3], // Lead Software Developer
nextPosition: posNames.SoftwareCompanyPositions[4], // Head of Software
baseSalary: 500,
charismaEffectiveness: 25,
charismaExpGain: 0.1,
hackingEffectiveness: 75,
hackingExpGain: 0.8,
reqdCharisma: 151,
reqdHacking: 401,
reqdReputation: 200e3,
repMultiplier: 1.5,
},
{
name: posNames.SoftwareCompanyPositions[4], // Head of Software
nextPosition: posNames.SoftwareCompanyPositions[5], // Head of Engineering
baseSalary: 800,
charismaEffectiveness: 25,
charismaExpGain: 0.5,
hackingEffectiveness: 75,
hackingExpGain: 1,
reqdCharisma: 251,
reqdHacking: 501,
reqdReputation: 400e3,
repMultiplier: 1.6,
},
{
name: posNames.SoftwareCompanyPositions[5], // Head of Engineering
nextPosition: posNames.SoftwareCompanyPositions[6], // Vice President of Technology
baseSalary: 1650,
charismaEffectiveness: 25,
charismaExpGain: 0.5,
hackingEffectiveness: 75,
hackingExpGain: 1.1,
reqdCharisma: 251,
reqdHacking: 501,
reqdReputation: 800e3,
repMultiplier: 1.6,
},
{
name: posNames.SoftwareCompanyPositions[6], // Vice President of Technology
nextPosition: posNames.SoftwareCompanyPositions[7], // Chief Technology Officer
baseSalary: 2310,
charismaEffectiveness: 30,
charismaExpGain: 0.6,
hackingEffectiveness: 70,
hackingExpGain: 1.2,
reqdCharisma: 401,
reqdHacking: 601,
reqdReputation: 1.6e6,
repMultiplier: 1.75,
},
{
name: posNames.SoftwareCompanyPositions[7], // Chief Technology Officer
nextPosition: null,
baseSalary: 2640,
charismaEffectiveness: 35,
charismaExpGain: 1,
hackingEffectiveness: 65,
hackingExpGain: 1.5,
reqdCharisma: 501,
reqdHacking: 751,
reqdReputation: 3.2e6,
repMultiplier: 2,
},
{
name: posNames.ITCompanyPositions[0], // IT Intern
nextPosition: posNames.ITCompanyPositions[1], // IT Analyst
baseSalary: 26,
charismaEffectiveness: 10,
charismaExpGain: 0.01,
hackingEffectiveness: 90,
hackingExpGain: 0.04,
reqdHacking: 1,
repMultiplier: 0.9,
},
{
name: posNames.ITCompanyPositions[1], // IT Analyst
nextPosition: posNames.ITCompanyPositions[2], // IT Manager
baseSalary: 66,
charismaEffectiveness: 15,
charismaExpGain: 0.02,
hackingEffectiveness: 85,
hackingExpGain: 0.08,
reqdHacking: 26,
reqdReputation: 7e3,
repMultiplier: 1.1,
},
{
name: posNames.ITCompanyPositions[2], // IT Manager
nextPosition: posNames.ITCompanyPositions[3], // Systems Administrator
baseSalary: 132,
charismaEffectiveness: 20,
charismaExpGain: 0.1,
hackingEffectiveness: 80,
hackingExpGain: 0.3,
reqdCharisma: 51,
reqdHacking: 151,
reqdReputation: 35e3,
repMultiplier: 1.3,
},
{
name: posNames.ITCompanyPositions[3], // Systems Administrator
nextPosition: posNames.SoftwareCompanyPositions[5], // Head of Engineering
baseSalary: 410,
charismaEffectiveness: 20,
charismaExpGain: 0.2,
hackingEffectiveness: 80,
hackingExpGain: 0.5,
reqdCharisma: 76,
reqdHacking: 251,
reqdReputation: 175e3,
repMultiplier: 1.4,
},
{
name: posNames.SecurityEngineerCompanyPositions[0], // Security Engineer
nextPosition: posNames.SoftwareCompanyPositions[5], // Head of Engineering
baseSalary: 121,
charismaEffectiveness: 15,
charismaExpGain: 0.05,
hackingEffectiveness: 85,
hackingExpGain: 0.4,
reqdCharisma: 26,
reqdHacking: 151,
reqdReputation: 35e3,
repMultiplier: 1.2,
},
{
name: posNames.NetworkEngineerCompanyPositions[0], // Network Engineer
nextPosition: posNames.NetworkEngineerCompanyPositions[1], // Network Adminsitrator
baseSalary: 121,
charismaEffectiveness: 15,
charismaExpGain: 0.05,
hackingEffectiveness: 85,
hackingExpGain: 0.4,
reqdCharisma: 26,
reqdHacking: 151,
reqdReputation: 35e3,
repMultiplier: 1.2,
},
{
name: posNames.NetworkEngineerCompanyPositions[1], // Network Administrator
nextPosition: posNames.SoftwareCompanyPositions[5], // Head of Engineering
baseSalary: 410,
charismaEffectiveness: 20,
charismaExpGain: 0.1,
hackingEffectiveness: 0.80,
hackingExpGain: 0.5,
reqdCharisma: 76,
reqdHacking: 251,
reqdReputation: 175e3,
repMultiplier: 1.3,
},
{
name: posNames.BusinessCompanyPositions[0], // Business Intern
nextPosition: posNames.BusinessCompanyPositions[1], // Business Analyst
baseSalary: 46,
charismaEffectiveness: 90,
charismaExpGain: 0.08,
hackingEffectiveness: 10,
hackingExpGain: 0.01,
reqdCharisma: 1,
reqdHacking: 1,
repMultiplier: 0.9,
},
{
name: posNames.BusinessCompanyPositions[1], // Business Analyst
nextPosition: posNames.BusinessCompanyPositions[2], // Business Manager
baseSalary: 100,
charismaEffectiveness: 85,
charismaExpGain: 0.15,
hackingEffectiveness: 15,
hackingExpGain: 0.02,
reqdCharisma: 51,
reqdHacking: 6,
reqdReputation: 8e3,
repMultiplier: 1.1,
},
{
name: posNames.BusinessCompanyPositions[2], // Business Manager
nextPosition: posNames.BusinessCompanyPositions[3], // Operations Manager
baseSalary: 200,
charismaEffectiveness: 85,
charismaExpGain: 0.3,
hackingEffectiveness: 15,
hackingExpGain: 0.02,
reqdCharisma: 101,
reqdHacking: 51,
reqdReputation: 40e3,
repMultiplier: 1.3,
},
{
name: posNames.BusinessCompanyPositions[3], // Operations Manager
nextPosition: posNames.BusinessCompanyPositions[4], // Chief Financial Officer
baseSalary: 660,
charismaEffectiveness: 85,
charismaExpGain: 0.4,
hackingEffectiveness: 15,
hackingExpGain: 0.02,
reqdCharisma: 226,
reqdHacking: 51,
reqdReputation: 200e3,
repMultiplier: 1.5,
},
{
name: posNames.BusinessCompanyPositions[4], // Chief Financial Officer
nextPosition: posNames.BusinessCompanyPositions[5], // Chief Executive Officer
baseSalary: 1950,
charismaEffectiveness: 90,
charismaExpGain: 1,
hackingEffectiveness: 10,
hackingExpGain: 0.05,
reqdCharisma: 501,
reqdHacking: 76,
reqdReputation: 800e3,
repMultiplier: 1.6,
},
{
name: posNames.BusinessCompanyPositions[5], // Chief Executive Officer
nextPosition: null,
baseSalary: 3900,
charismaEffectiveness: 90,
charismaExpGain: 1.5,
hackingEffectiveness: 10,
hackingExpGain: 0.05,
reqdCharisma: 751,
reqdHacking: 101,
reqdReputation: 3.2e6,
repMultiplier: 1.75,
},
{
name: posNames.SecurityCompanyPositions[0], // Police Officer
nextPosition: posNames.SecurityCompanyPositions[1], // Police Chief
baseSalary: 82,
hackingEffectiveness: 5,
strengthEffectiveness: 20,
defenseEffectiveness: 20,
dexterityEffectiveness: 20,
agilityEffectiveness: 20,
charismaEffectiveness: 15,
hackingExpGain: 0.02,
strengthExpGain: 0.08,
defenseExpGain: 0.08,
dexterityExpGain: 0.08,
agilityExpGain: 0.08,
charismaExpGain: 0.04,
reqdHacking: 11,
reqdStrength: 101,
reqdDefense: 101,
reqdDexterity: 101,
reqdAgility: 101,
reqdCharisma: 51,
reqdReputation: 8e3,
repMultiplier: 1,
},
{
name: posNames.SecurityCompanyPositions[1], // Police Chief
nextPosition: null,
baseSalary: 460,
hackingEffectiveness: 5,
strengthEffectiveness: 20,
defenseEffectiveness: 20,
dexterityEffectiveness: 20,
agilityEffectiveness: 20,
charismaEffectiveness: 15,
hackingExpGain: 0.02,
strengthExpGain: 0.1,
defenseExpGain: 0.1,
dexterityExpGain: 0.1,
agilityExpGain: 0.1,
charismaExpGain: 0.1,
reqdHacking: 101,
reqdStrength: 301,
reqdDefense: 301,
reqdDexterity: 301,
reqdAgility: 301,
reqdCharisma: 151,
reqdReputation: 36e3,
repMultiplier: 1.25,
},
{
name: posNames.SecurityCompanyPositions[2], // Security Guard
nextPosition: posNames.SecurityCompanyPositions[3], // Security Officer
baseSalary: 50,
hackingEffectiveness: 5,
strengthEffectiveness: 20,
defenseEffectiveness: 20,
dexterityEffectiveness: 20,
agilityEffectiveness: 20,
charismaEffectiveness: 15,
hackingExpGain: 0.01,
strengthExpGain: 0.04,
defenseExpGain: 0.04,
dexterityExpGain: 0.04,
agilityExpGain: 0.04,
charismaExpGain: 0.02,
reqdStrength: 51,
reqdDefense: 51,
reqdDexterity: 51,
reqdAgility: 51,
reqdCharisma: 1,
repMultiplier: 1,
},
{
name: posNames.SecurityCompanyPositions[3], // Security Officer
nextPosition: posNames.SecurityCompanyPositions[4], // Security Supervisor
baseSalary: 195,
hackingEffectiveness: 10,
strengthEffectiveness: 20,
defenseEffectiveness: 20,
dexterityEffectiveness: 20,
agilityEffectiveness: 20,
charismaEffectiveness: 10,
hackingExpGain: 0.02,
strengthExpGain: 0.1,
defenseExpGain: 0.1,
dexterityExpGain: 0.1,
agilityExpGain: 0.1,
charismaExpGain: 0.05,
reqdHacking: 26,
reqdStrength: 151,
reqdDefense: 151,
reqdDexterity: 151,
reqdAgility: 151,
reqdCharisma: 51,
reqdReputation: 8e3,
repMultiplier: 1.1,
},
{
name: posNames.SecurityCompanyPositions[4], // Security Supervisor
nextPosition: posNames.SecurityCompanyPositions[5], // Head of Security
baseSalary: 660,
hackingEffectiveness: 10,
strengthEffectiveness: 15,
defenseEffectiveness: 15,
dexterityEffectiveness: 15,
agilityEffectiveness: 15,
charismaEffectiveness: 30,
hackingExpGain: 0.02,
strengthExpGain: 0.12,
defenseExpGain: 0.12,
dexterityExpGain: 0.12,
agilityExpGain: 0.12,
charismaExpGain: 0.1,
reqdHacking: 26,
reqdStrength: 251,
reqdDefense: 251,
reqdDexterity: 251,
reqdAgility: 251,
reqdCharisma: 101,
reqdReputation: 36e3,
repMultiplier: 1.25,
},
{
name: posNames.SecurityCompanyPositions[5], // Head of Security
nextPosition: null,
baseSalary: 1320,
hackingEffectiveness: 10,
strengthEffectiveness: 15,
defenseEffectiveness: 15,
dexterityEffectiveness: 15,
agilityEffectiveness: 15,
charismaEffectiveness: 30,
hackingExpGain: 0.05,
strengthExpGain: 0.15,
defenseExpGain: 0.15,
dexterityExpGain: 0.15,
agilityExpGain: 0.15,
charismaExpGain: 0.15,
reqdHacking: 51,
reqdStrength: 501,
reqdDefense: 501,
reqdDexterity: 501,
reqdAgility: 501,
reqdCharisma: 151,
reqdReputation: 144e3,
repMultiplier: 1.4,
},
{
name: posNames.AgentCompanyPositions[0], // Field Agent
nextPosition: posNames.AgentCompanyPositions[0], // Secret Agent
baseSalary: 330,
hackingEffectiveness: 10,
strengthEffectiveness: 15,
defenseEffectiveness: 15,
dexterityEffectiveness: 20,
agilityEffectiveness: 20,
charismaEffectiveness: 20,
hackingExpGain: 0.04,
strengthExpGain: 0.08,
defenseExpGain: 0.08,
dexterityExpGain: 0.08,
agilityExpGain: 0.08,
charismaExpGain: 0.05,
reqdHacking: 101,
reqdStrength: 101,
reqdDefense: 101,
reqdDexterity: 101,
reqdAgility: 101,
reqdCharisma: 101,
reqdReputation: 8e3,
repMultiplier: 1,
},
{
name: posNames.AgentCompanyPositions[0], // Secret Agent
nextPosition: posNames.AgentCompanyPositions[0], // Special Operative
baseSalary: 990,
hackingEffectiveness: 15,
strengthEffectiveness: 15,
defenseEffectiveness: 15,
dexterityEffectiveness: 20,
agilityEffectiveness: 20,
charismaEffectiveness: 15,
hackingExpGain: 0.1,
strengthExpGain: 0.15,
defenseExpGain: 0.15,
dexterityExpGain: 0.15,
agilityExpGain: 0.15,
charismaExpGain: 0.1,
reqdHacking: 201,
reqdStrength: 251,
reqdDefense: 251,
reqdDexterity: 251,
reqdAgility: 251,
reqdCharisma: 201,
reqdReputation: 32e3,
repMultiplier: 1.25,
},
{
name: posNames.AgentCompanyPositions[0], // Special Operative
nextPosition: null,
baseSalary: 2000,
hackingEffectiveness: 15,
strengthEffectiveness: 15,
defenseEffectiveness: 15,
dexterityEffectiveness: 20,
agilityEffectiveness: 20,
charismaEffectiveness: 15,
hackingExpGain: 0.15,
strengthExpGain: 0.2,
defenseExpGain: 0.2,
dexterityExpGain: 0.2,
agilityExpGain: 0.2,
charismaExpGain: 0.15,
reqdHacking: 251,
reqdStrength: 501,
reqdDefense: 501,
reqdDexterity: 501,
reqdAgility: 501,
reqdCharisma: 251,
reqdReputation: 162e3,
repMultiplier: 1.5,
},
{
name: posNames.MiscCompanyPositions[0], // Waiter
nextPosition: null,
baseSalary: 22,
strengthEffectiveness: 10,
dexterityEffectiveness: 10,
agilityEffectiveness: 10,
charismaEffectiveness: 70,
strengthExpGain: 0.02,
defenseExpGain: 0.02,
dexterityExpGain: 0.02,
agilityExpGain: 0.02,
charismaExpGain: 0.05,
repMultiplier: 1,
},
{
name: posNames.MiscCompanyPositions[1], // Employee
nextPosition: null,
baseSalary: 22,
strengthEffectiveness: 10,
dexterityEffectiveness: 10,
agilityEffectiveness: 10,
charismaEffectiveness: 70,
strengthExpGain: 0.02,
defenseExpGain: 0.02,
dexterityExpGain: 0.02,
agilityExpGain: 0.02,
charismaExpGain: 0.04,
repMultiplier: 1,
},
{
name: posNames.SoftwareConsultantCompanyPositions[0], // Software Consultant
nextPosition: posNames.SoftwareConsultantCompanyPositions[1], // Senior Software Consultant
baseSalary: 66,
hackingEffectiveness: 80,
charismaEffectiveness: 20,
hackingExpGain: 0.08,
charismaExpGain: 0.03,
reqdHacking: 51,
repMultiplier: 1,
},
{
name: posNames.SoftwareConsultantCompanyPositions[1], // Senior Software Consultant
nextPosition: null,
baseSalary: 132,
hackingEffectiveness: 75,
charismaEffectiveness: 25,
hackingExpGain: 0.25,
charismaExpGain: 0.06,
reqdHacking: 251,
reqdCharisma: 51,
repMultiplier: 1.2,
},
{
name: posNames.BusinessConsultantCompanyPositions[0], // Business Consultant
nextPosition: posNames.BusinessConsultantCompanyPositions[1], // Senior Business Consultant
baseSalary: 66,
hackingEffectiveness: 20,
charismaEffectiveness: 80,
hackingExpGain: 0.015,
charismaExpGain: 0.15,
reqdHacking: 6,
reqdCharisma: 51,
repMultiplier: 1,
},
{
name: posNames.BusinessConsultantCompanyPositions[0], // Senior Business Consultant
nextPosition: null,
baseSalary: 525,
hackingEffectiveness: 15,
charismaEffectiveness: 85,
hackingExpGain: 0.015,
charismaExpGain: 0.3,
reqdHacking: 51,
reqdCharisma: 226,
repMultiplier: 1.2,
},
{
name: posNames.PartTimeCompanyPositions[0], // Part-time waiter
nextPosition: null,
baseSalary: 20,
strengthEffectiveness: 10,
dexterityEffectiveness: 10,
agilityEffectiveness: 10,
charismaEffectiveness: 70,
strengthExpGain: 0.0075,
defenseExpGain: 0.0075,
dexterityExpGain: 0.0075,
agilityExpGain: 0.0075,
charismaExpGain: 0.04,
repMultiplier: 1,
},
{
name: posNames.PartTimeCompanyPositions[1], // Part-time employee
nextPosition: null,
baseSalary: 20,
strengthEffectiveness: 10,
dexterityEffectiveness: 10,
agilityEffectiveness: 10,
charismaEffectiveness: 70,
strengthExpGain: 0.0075,
defenseExpGain: 0.0075,
dexterityExpGain: 0.0075,
agilityExpGain: 0.0075,
charismaExpGain: 0.03,
repMultiplier: 1,
},
]

@ -1,3 +1,5 @@
// Defs for job titles, stored in arrays and categorized by job "type"
export const SoftwareCompanyPositions: string[] = [
"Software Engineering Intern",
"Junior Software Engineer",
@ -35,8 +37,9 @@ export const BusinessCompanyPositions: string[] = [
];
export const SecurityCompanyPositions: string[] = [
"Security Guard",
"Police Officer",
"Police Chief",
"Security Guard",
"Security Officer",
"Security Supervisor",
"Head of Security"
@ -48,6 +51,11 @@ export const AgentCompanyPositions: string[] = [
"Special Operative"
];
export const MiscCompanyPositions: string[] = [
"Waiter",
"Employee"
];
export const SoftwareConsultantCompanyPositions: string[] = [
"Software Consultant",
"Senior Software Consultant"

@ -1,4 +1,6 @@
let CONSTANTS = {
import {IMap} from "./types";
export let CONSTANTS: IMap<any> = {
Version: "0.41.0",
//Max level for any skill, assuming no multipliers. Determined by max numerical value in javascript for experience
@ -515,5 +517,3 @@ let CONSTANTS = {
`
}
export {CONSTANTS};

@ -1,6 +1,8 @@
import {Bladeburner} from "./Bladeburner";
import {CompanyPositions, initCompanies,
Companies, getJobRequirementText} from "./Company";
import {CompanyPositions} from "./Company/CompanyPositions";
import {Companies} from "./Company/Companies";
import {getJobRequirementText} from "./Company/GetJobRequirementText";
import * as posNames from "./Company/data/CompanyPositionNames";
import {Corporation} from "./CompanyManagement";
import {CONSTANTS} from "./Constants";
import {Crimes} from "./Crimes";
@ -241,7 +243,7 @@ function displayLocationContent() {
locationTxtDiv1.style.display = "block";
locationTxtDiv2.style.display = "block";
locationTxtDiv3.style.display = "block";
jobTitle.innerHTML = "Job Title: " + Player.companyPosition.positionName;
jobTitle.innerHTML = "Job Title: " + Player.companyPosition;
var repGain = company.getFavorGain();
if (repGain.length != 2) {repGain = 0;}
repGain = repGain[0];
@ -301,19 +303,19 @@ function displayLocationContent() {
var hospitalTreatmentCost = (Player.max_hp - Player.hp) * CONSTANTS.HospitalCostPerHp;
//Set tooltip for job requirements
setJobRequirementTooltip(loc, CompanyPositions.SoftwareIntern, softwareJob);
setJobRequirementTooltip(loc, CompanyPositions.SoftwareConsultant, softwareConsultantJob);
setJobRequirementTooltip(loc, CompanyPositions.ITIntern, itJob);
setJobRequirementTooltip(loc, CompanyPositions.SecurityEngineer, securityEngineerJob);
setJobRequirementTooltip(loc, CompanyPositions.NetworkEngineer, networkEngineerJob);
setJobRequirementTooltip(loc, CompanyPositions.BusinessIntern, businessJob);
setJobRequirementTooltip(loc, CompanyPositions.BusinessConsultant, businessConsultantJob);
setJobRequirementTooltip(loc, CompanyPositions.SecurityGuard, securityJob);
setJobRequirementTooltip(loc, CompanyPositions.FieldAgent, agentJob);
setJobRequirementTooltip(loc, CompanyPositions.Employee, employeeJob);
setJobRequirementTooltip(loc, CompanyPositions.PartTimeEmployee, employeePartTimeJob);
setJobRequirementTooltip(loc, CompanyPositions.Waiter, waiterJob);
setJobRequirementTooltip(loc, CompanyPositions.PartTimeWaiter, waiterPartTimeJob);
setJobRequirementTooltip(loc, CompanyPositions[posNames.SoftwareCompanyPositions[0]], softwareJob);
setJobRequirementTooltip(loc, CompanyPositions[posNames.SoftwareConsultantCompanyPositions[0]], softwareConsultantJob);
setJobRequirementTooltip(loc, CompanyPositions[posNames.ITCompanyPositions[0]], itJob);
setJobRequirementTooltip(loc, CompanyPositions[posNames.SecurityEngineerCompanyPositions[0]], securityEngineerJob);
setJobRequirementTooltip(loc, CompanyPositions[posNames.NetworkEngineerCompanyPositions[0]], networkEngineerJob);
setJobRequirementTooltip(loc, CompanyPositions[posNames.BusinessCompanyPositions[0]], businessJob);
setJobRequirementTooltip(loc, CompanyPositions[posNames.BusinessConsultantCompanyPositions[0]], businessConsultantJob);
setJobRequirementTooltip(loc, CompanyPositions[posNames.SecurityCompanyPositions[0]], securityJob);
setJobRequirementTooltip(loc, CompanyPositions[posNames.AgentCompanyPositions[0]], agentJob);
setJobRequirementTooltip(loc, CompanyPositions[posNames.MiscCompanyPositions[1]], employeeJob);
setJobRequirementTooltip(loc, CompanyPositions[posNames.PartTimeCompanyPositions[1]], employeePartTimeJob);
setJobRequirementTooltip(loc, CompanyPositions[posNames.MiscCompanyPositions[0]], waiterJob);
setJobRequirementTooltip(loc, CompanyPositions[posNames.PartTimeCompanyPositions[0]], waiterPartTimeJob);
switch (loc) {
case Locations.AevumTravelAgency:
@ -1030,18 +1032,18 @@ function displayLocationContent() {
console.log("ERROR: INVALID LOCATION");
}
//Make the "Apply to be Employee and Waiter" texts disappear if you already hold the job
//Includes part-time stuff
// Make the "Apply to be Employee and Waiter" texts disappear if you already hold the job
// Includes part-time stuff
if (loc == Player.companyName) {
var currPos = Player.companyPosition;
if (currPos.positionName == CompanyPositions.Employee.positionName) {
if (currPos.name == "Employee") {
employeeJob.style.display = "none";
} else if (currPos.positionName == CompanyPositions.Waiter.positionName) {
} else if (currPos.name == "Waiter") {
waiterJob.style.display = "none";
} else if (currPos.positionName == CompanyPositions.PartTimeEmployee.positionName) {
} else if (currPos.name == "Part-time Employee") {
employeePartTimeJob.style.display = "none";
} else if (currPos.positionName == CompanyPositions.PartTimeWaiter.positionName) {
} else if (currPos.name == "Part-time Waiter") {
waiterPartTimeJob.style.display = "none";
}
}

@ -8,8 +8,10 @@ import {Augmentations, Augmentation,
import {BitNodeMultipliers} from "./BitNodeMultipliers";
import {determineCrimeSuccess, findCrime} from "./Crimes";
import {Bladeburner} from "./Bladeburner";
import {Companies, Company, CompanyPosition,
CompanyPositions, companyExists} from "./Company";
import {Company} from "./Company/Company";
import {Companies, companyExists} from "./Company/Companies";
import {CompanyPosition} from "./Company/CompanyPosition";
import {CompanyPositions} from "./Company/CompanyPositions";
import {CONSTANTS} from "./Constants";
import {Programs} from "./CreateProgram";
import {DarkWebItems} from "./DarkWeb";
@ -2692,8 +2694,8 @@ function NetscriptFunctions(workerScript) {
}
var companyPositionTitle = "";
if (Player.companyPosition instanceof CompanyPosition) {
companyPositionTitle = Player.companyPosition.positionName;
if (CompanyPositions[Player.companyPosition] instanceof CompanyPosition) {
companyPositionTitle = Player.companyPosition;
}
return {
bitnode: Player.bitNodeN,
@ -2834,7 +2836,8 @@ function NetscriptFunctions(workerScript) {
return;
}
if (Player.companyPosition == "" || !(Player.companyPosition instanceof CompanyPosition)) {
const companyPosition = CompanyPositions[Player.companyPosition];
if (Player.companyPosition === "" || !(companyPosition instanceof CompanyPosition)) {
workerScript.scriptRef.log("ERROR: workForCompany() failed because you do not have a job");
return false;
}
@ -2846,13 +2849,13 @@ function NetscriptFunctions(workerScript) {
}
}
if (Player.companyPosition.isPartTimeJob()) {
if (companyPosition.isPartTimeJob()) {
Player.startWorkPartTime();
} else {
Player.startWork();
}
if (workerScript.disableLogs.ALL == null && workerScript.disableLogs.workForCompany == null) {
workerScript.scriptRef.log("Began working at " + Player.companyName + " as a " + Player.companyPosition.positionName);
workerScript.log(`Began working at ${Player.companyName} as a ${Player.companyPosition}`);
}
return true;
},
@ -2928,11 +2931,11 @@ function NetscriptFunctions(workerScript) {
}
if (res) {
if (workerScript.disableLogs.ALL == null && workerScript.disableLogs.applyToCompany == null) {
workerScript.scriptRef.log("You were offered a new job at " + companyName + " as a " + Player.companyPosition.positionName);
workerScript.log(`You were offered a new job at ${companyName} as a ${Player.companyPosition}`);
}
} else {
if (workerScript.disableLogs.ALL == null && workerScript.disableLogs.applyToCompany == null) {
workerScript.scriptRef.log("You failed to get a new job/promotion at " + companyName + " in the " + field + " field.");
workerScript.log(`You failed to get a new job/promotion at ${companyName} in the ${field} field.`);
}
}
return res;

@ -3,9 +3,11 @@ import {Augmentations, applyAugmentation,
PlayerOwnedAugmentation} from "./Augmentations";
import {BitNodeMultipliers} from "./BitNodeMultipliers";
import {CodingContractRewardType} from "./CodingContracts";
import {Company, Companies, getNextCompanyPosition,
getJobRequirementText, CompanyPosition,
CompanyPositions} from "./Company";
import {Company} from "./Company/Company";
import {Companies} from "./Company/Companies";
import {getNextCompanyPosition} from "./Company/GetNextCompanyPosition";
import {getJobRequirementText} from "./Company/GetJobRequirementText";
import {CompanyPositions} from "./Company/CompanyPositions";
import {CONSTANTS} from "./Constants";
import {Corporation} from "./CompanyManagement";
import {Programs} from "./CreateProgram";
@ -94,8 +96,8 @@ function PlayerObject() {
this.location = "";
//Company Information
this.companyName = ""; //Name of Company, equivalent to an object from Locations
this.companyPosition = ""; //CompanyPosition object
this.companyName = ""; // Name of Company. Must match a key value in Companies map
this.companyPosition = ""; // Name of Company Position. Must match a key value in CompanyPositions map
//Servers
this.currentServer = ""; //IP address of Server currently being accessed through terminal
@ -710,13 +712,13 @@ PlayerObject.prototype.work = function(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;
}
var txt = document.getElementById("work-in-progress-text");
txt.innerHTML = "You are currently working as a " + this.companyPosition.positionName +
txt.innerHTML = "You are currently working as a " + this.companyPosition +
" at " + this.companyName + " (Current Company Reputation: " +
numeralWrapper.format(companyRep, '0,0') + ")<br><br>" +
"You have been working for " + convertTimeMsToTimeElapsedString(this.timeWorked) + "<br><br>" +
@ -838,7 +840,7 @@ PlayerObject.prototype.workPartTime = function(numCycles) {
}
var txt = document.getElementById("work-in-progress-text");
txt.innerHTML = "You are currently working as a " + this.companyPosition.positionName +
txt.innerHTML = "You are currently working as a " + this.companyPosition +
" at " + Player.companyName + " (Current Company Reputation: " +
numeralWrapper.format(companyRep, '0,0') + ")<br><br>" +
"You have been working for " + convertTimeMsToTimeElapsedString(this.timeWorked) + "<br><br>" +
@ -1070,60 +1072,116 @@ PlayerObject.prototype.finishFactionWork = function(cancelled, sing=false) {
//Money gained per game cycle
PlayerObject.prototype.getWorkMoneyGain = function() {
var bn11Mult = 1;
var company = Companies[this.companyName];
if (hasBn11SF) {
bn11Mult = 1 + (company.favor / 100);
// If player has SF-11, calculate salary multiplier from favor
let bn11Mult = 1;
const company = Companies[this.companyName];
if (hasBn11SF) { bn11Mult = 1 + (company.favor / 100); }
// Get base salary
const companyPosition = CompanyPositions[this.companyPosition];
if (companyPosition == null) {
console.error(`Could not find CompanyPosition object for ${this.companyPosition}. Work salary will be 0`);
return 0;
}
return this.companyPosition.baseSalary * company.salaryMultiplier *
this.work_money_mult * BitNodeMultipliers.CompanyWorkMoney * bn11Mult;
return companyPosition.baseSalary * company.salaryMultiplier * this.work_money_mult * BitNodeMultipliers.CompanyWorkMoney * bn11Mult;
}
//Hack exp gained per game cycle
PlayerObject.prototype.getWorkHackExpGain = function() {
var company = Companies[this.companyName];
return this.companyPosition.hackingExpGain * company.expMultiplier *
this.hacking_exp_mult * BitNodeMultipliers.CompanyWorkExpGain;
const company = Companies[this.companyName];
const companyPosition = CompanyPositions[this.companyPosition];
if (company == null || companyPosition == null) {
console.error([`Could not find Company object for ${this.companyName}`,
`or CompanyPosition object for ${this.companyPosition}.`,
`Work hack exp gain will be 0`].join(" "));
return 0;
}
return companyPosition.hackingExpGain * company.expMultiplier * this.hacking_exp_mult * BitNodeMultipliers.CompanyWorkExpGain;
}
//Str exp gained per game cycle
PlayerObject.prototype.getWorkStrExpGain = function() {
var company = Companies[this.companyName];
return this.companyPosition.strengthExpGain * company.expMultiplier *
this.strength_exp_mult * BitNodeMultipliers.CompanyWorkExpGain;
const company = Companies[this.companyName];
const companyPosition = CompanyPositions[this.companyPosition];
if (company == null || companyPosition == null) {
console.error([`Could not find Company object for ${this.companyName}`,
`or CompanyPosition object for ${this.companyPosition}.`,
`Work str exp gain will be 0`].join(" "));
return 0;
}
return this.companyPosition.strengthExpGain * company.expMultiplier * this.strength_exp_mult * BitNodeMultipliers.CompanyWorkExpGain;
}
//Def exp gained per game cycle
PlayerObject.prototype.getWorkDefExpGain = function() {
var company = Companies[this.companyName];
return this.companyPosition.defenseExpGain * company.expMultiplier *
this.defense_exp_mult * BitNodeMultipliers.CompanyWorkExpGain;
const company = Companies[this.companyName];
const companyPosition = CompanyPositions[this.companyPosition];
if (company == null || companyPosition == null) {
console.error([`Could not find Company object for ${this.companyName}`,
`or CompanyPosition object for ${this.companyPosition}.`,
`Work def exp gain will be 0`].join(" "));
return 0;
}
return this.companyPosition.defenseExpGain * company.expMultiplier * this.defense_exp_mult * BitNodeMultipliers.CompanyWorkExpGain;
}
//Dex exp gained per game cycle
PlayerObject.prototype.getWorkDexExpGain = function() {
var company = Companies[this.companyName];
return this.companyPosition.dexterityExpGain * company.expMultiplier *
this.dexterity_exp_mult * BitNodeMultipliers.CompanyWorkExpGain;
const company = Companies[this.companyName];
const companyPosition = CompanyPositions[this.companyPosition];
if (company == null || companyPosition == null) {
console.error([`Could not find Company object for ${this.companyName}`,
`or CompanyPosition object for ${this.companyPosition}.`,
`Work dex exp gain will be 0`].join(" "));
return 0;
}
return this.companyPosition.dexterityExpGain * company.expMultiplier * this.dexterity_exp_mult * BitNodeMultipliers.CompanyWorkExpGain;
}
//Agi exp gained per game cycle
PlayerObject.prototype.getWorkAgiExpGain = function() {
var company = Companies[this.companyName];
return this.companyPosition.agilityExpGain * company.expMultiplier *
this.agility_exp_mult * BitNodeMultipliers.CompanyWorkExpGain;
const company = Companies[this.companyName];
const companyPosition = CompanyPositions[this.companyPosition];
if (company == null || companyPosition == null) {
console.error([`Could not find Company object for ${this.companyName}`,
`or CompanyPosition object for ${this.companyPosition}.`,
`Work agi exp gain will be 0`].join(" "));
return 0;
}
return this.companyPosition.agilityExpGain * company.expMultiplier * this.agility_exp_mult * BitNodeMultipliers.CompanyWorkExpGain;
}
//Charisma exp gained per game cycle
PlayerObject.prototype.getWorkChaExpGain = function() {
var company = Companies[this.companyName];
return this.companyPosition.charismaExpGain * company.expMultiplier *
this.charisma_exp_mult * BitNodeMultipliers.CompanyWorkExpGain;
const company = Companies[this.companyName];
const companyPosition = CompanyPositions[this.companyPosition];
if (company == null || companyPosition == null) {
console.error([`Could not find Company object for ${this.companyName}`,
`or CompanyPosition object for ${this.companyPosition}.`,
`Work cha exp gain will be 0`].join(" "));
return 0;
}
return this.companyPosition.charismaExpGain * company.expMultiplier * this.charisma_exp_mult * BitNodeMultipliers.CompanyWorkExpGain;
}
//Reputation gained per game cycle
PlayerObject.prototype.getWorkRepGain = function() {
var company = Companies[this.companyName];
const company = Companies[this.companyName];
const companyPosition = CompanyPositions[this.companyPosition];
if (company == null || companyPosition == null) {
console.error([`Could not find Company object for ${this.companyName}`,
`or CompanyPosition object for ${this.companyPosition}.`,
`Work rep gain will be 0`].join(" "));
return 0;
}
var jobPerformance = this.companyPosition.calculateJobPerformance(this.hacking_skill, this.strength,
this.defense, this.dexterity,
this.agility, this.charisma);
@ -1133,7 +1191,7 @@ PlayerObject.prototype.getWorkRepGain = function() {
//Update reputation gain rate to account for company favor
var favorMult = 1 + (company.favor / 100);
if (isNaN(favorMult)) {favorMult = 1;}
if (isNaN(favorMult)) { favorMult = 1; }
return jobPerformance * this.company_rep_mult * favorMult;
}
@ -1612,20 +1670,25 @@ PlayerObject.prototype.hospitalize = function() {
//The 'sing' argument designates whether or not this is being called from
//the applyToCompany() Netscript Singularity function
PlayerObject.prototype.applyForJob = function(entryPosType, sing=false) {
var currCompany = "";
if (this.companyName != "") {
// Get current company and job
let currCompany = null;
if (this.companyName !== "") {
currCompany = Companies[this.companyName];
}
var currPositionName = "";
if (this.companyPosition != "") {
currPositionName = this.companyPosition.positionName;
}
var company = Companies[this.location]; //Company being applied to
if (sing && !(company instanceof Company)) {
return "ERROR: Invalid company name: " + this.location + ". applyToCompany() failed";
const currPositionName = this.companyPosition;
// Get company that's being applied to
const company = Companies[this.location]; //Company being applied to
if (!(company instanceof Company)) {
if (sing) {
return "ERROR: Invalid company name: " + this.location + ". applyToCompany() failed";
} else {
console.error(`Could not find company that matches the location: ${this.location}. Player.applyToCompany() failed`);
return;
}
}
var pos = entryPosType;
let pos = entryPosType;
if (!this.isQualified(company, pos)) {
var reqText = getJobRequirementText(company, pos);
@ -1635,8 +1698,8 @@ PlayerObject.prototype.applyForJob = function(entryPosType, sing=false) {
}
while (true) {
if (Engine.Debug) {console.log("Determining qualification for next Company Position");}
var newPos = getNextCompanyPosition(pos);
console.log("Determining qualification for next Company Position");
let newPos = getNextCompanyPosition(pos);
if (newPos == null) {break;}
//Check if this company has this position
@ -1652,9 +1715,8 @@ PlayerObject.prototype.applyForJob = function(entryPosType, sing=false) {
}
//Check if the determined job is the same as the player's current job
if (currCompany != "") {
if (currCompany.companyName == company.companyName &&
pos.positionName == currPositionName) {
if (currCompany != null) {
if (currCompany.name == company.name && pos.name == currPositionName) {
var nextPos = getNextCompanyPosition(pos);
if (nextPos == null) {
if (sing) {return false;}
@ -1673,35 +1735,27 @@ PlayerObject.prototype.applyForJob = function(entryPosType, sing=false) {
//Lose reputation from a Company if you are leaving it for another job
var leaveCompany = false;
var oldCompanyName = "";
if (currCompany != "") {
if (currCompany.companyName != company.companyName) {
let leaveCompany = false;
let oldCompanyName = "";
if (currCompany != null) {
if (currCompany.name != company.name) {
leaveCompany = true;
oldCompanyName = currCompany.companyName;
oldCompanyName = currCompany.name;
company.playerReputation -= 1000;
if (company.playerReputation < 0) {company.playerReputation = 0;}
if (company.playerReputation < 0) { company.playerReputation = 0; }
}
}
this.companyName = company.companyName;
this.companyPosition = pos;
if (this.firstJobRecvd === false) {
this.firstJobRecvd = true;
document.getElementById("job-tab").style.display = "list-item";
document.getElementById("world-menu-header").click();
document.getElementById("world-menu-header").click();
}
this.companyName = company.name;
this.companyPosition = pos.name;
if (leaveCompany) {
if (sing) {return true;}
dialogBoxCreate("Congratulations! You were offered a new job at " + this.companyName + " as a " +
pos.positionName + "!<br>" +
"You lost 1000 reputation at your old company " + oldCompanyName + " because you left.");
if (sing) { return true; }
dialogBoxCreate([`Congratulations! You were offered a new job at ${this.companyName} as a ${pos.name}!`,
`You lost 1000 reputation at your old company ${oldCompanyName} because you left.`].join("<br>"));
} else {
if (sing) {return true;}
dialogBoxCreate("Congratulations! You were offered a new job at " + this.companyName + " as a " + pos.positionName + "!");
if (sing) { return true; }
dialogBoxCreate("Congratulations! You were offered a new job at " + this.companyName + " as a " + pos.name + "!");
}
Engine.loadLocationContent();
@ -1710,32 +1764,32 @@ PlayerObject.prototype.applyForJob = function(entryPosType, sing=false) {
//Returns your next position at a company given the field (software, business, etc.)
PlayerObject.prototype.getNextCompanyPosition = function(company, entryPosType) {
var currCompany = null;
if (this.companyName != "") {
currCompany = Companies[this.companyName];
if (this.name !== "") {
currCompany = Companies[this.name];
}
//Not employed at this company, so return the entry position
if (currCompany == null || (currCompany.companyName != company.companyName)) {
if (currCompany == null || (currCompany.name != company.name)) {
return entryPosType;
}
//If the entry pos type and the player's current position have the same type,
//return the player's "nextCompanyPosition". Otherwise return the entryposType
//Employed at this company, so just return the next position if it exists.
if ((this.companyPosition.isSoftwareJob() && entryPosType.isSoftwareJob()) ||
(this.companyPosition.isITJob() && entryPosType.isITJob()) ||
(this.companyPosition.isBusinessJob() && entryPosType.isBusinessJob()) ||
(this.companyPosition.isSecurityEngineerJob() && entryPosType.isSecurityEngineerJob()) ||
(this.companyPosition.isNetworkEngineerJob() && entryPosType.isNetworkEngineerJob()) ||
(this.companyPosition.isSecurityJob() && entryPosType.isSecurityJob()) ||
(this.companyPosition.isAgentJob() && entryPosType.isAgentJob()) ||
(this.companyPosition.isSoftwareConsultantJob() && entryPosType.isSoftwareConsultantJob()) ||
(this.companyPosition.isBusinessConsultantJob() && entryPosType.isBusinessConsultantJob()) ||
(this.companyPosition.isPartTimeJob() && entryPosType.isPartTimeJob())) {
return getNextCompanyPosition(this.companyPosition);
const currentPosition = CompanyPositions[this.companyPosition];
if ((currentPosition.isSoftwareJob() && entryPosType.isSoftwareJob()) ||
(currentPosition.isITJob() && entryPosType.isITJob()) ||
(currentPosition.isBusinessJob() && entryPosType.isBusinessJob()) ||
(currentPosition.isSecurityEngineerJob() && entryPosType.isSecurityEngineerJob()) ||
(currentPosition.isNetworkEngineerJob() && entryPosType.isNetworkEngineerJob()) ||
(currentPosition.isSecurityJob() && entryPosType.isSecurityJob()) ||
(currentPosition.isAgentJob() && entryPosType.isAgentJob()) ||
(currentPosition.isSoftwareConsultantJob() && entryPosType.isSoftwareConsultantJob()) ||
(currentPosition.isBusinessConsultantJob() && entryPosType.isBusinessConsultantJob()) ||
(currentPosition.isPartTimeJob() && entryPosType.isPartTimeJob())) {
return getNextCompanyPosition(currentPosition);
}
return entryPosType;
}
@ -2177,10 +2231,12 @@ PlayerObject.prototype.checkForFactionInvitations = function() {
//Silhouette
var silhouetteFac = Factions["Silhouette"];
const companyPosition = CompanyPositions[this.companyPosition];
if (!silhouetteFac.isBanned && !silhouetteFac.isMember && !silhouetteFac.alreadyInvited &&
(this.companyPosition.positionName == CompanyPositions.CTO.positionName ||
this.companyPosition.positionName == CompanyPositions.CFO.positionName ||
this.companyPosition.positionName == CompanyPositions.CEO.positionName) &&
companyPosition != null &&
(companyPosition.name == "Chief Technology Officer" ||
companyPosition.name == "Chief Financial Officer" ||
companyPosition.name == "Chief Executive Officer") &&
this.money.gte(15000000) && this.karma <= -22) {
invitedFactions.push(silhouetteFac);
}

@ -4,7 +4,7 @@ import {Augmentations, augmentationExists,
import {initBitNodeMultipliers} from "./BitNode";
import {Bladeburner} from "./Bladeburner";
import {writeCinematicText} from "./CinematicText";
import {Companies, Company, initCompanies} from "./Company";
import {Companies, initCompanies} from "./Company/Companies";
import {Programs} from "./CreateProgram";
import {Engine} from "./engine";
import {Factions, Faction, initFactions,

@ -1,7 +1,7 @@
import {loadAliases, loadGlobalAliases,
Aliases, GlobalAliases} from "./Alias";
import {loadCompanies, Companies,
CompanyPositions} from "./Company";
import {Companies, loadCompanies} from "./Company/Companies";
import {CompanyPosition} from "./Company/CompanyPosition";
import {CONSTANTS} from "./Constants";
import {Engine} from "./engine";
import {loadFactions, Factions,
@ -187,29 +187,20 @@ function loadGame(saveString) {
if (saveObj.hasOwnProperty("VersionSave")) {
try {
var ver = JSON.parse(saveObj.VersionSave, Reviver);
if (Player.bitNodeN == null || Player.bitNodeN === 0) {
Player.setBitNodeNumber(1);
}
if (ver.startsWith("0.27.") || ver.startsWith("0.28.")) {
console.log("Evaluating changes needed for version compatibility");
if (Player.augmentations.length > 0 || Player.queuedAugmentations.length > 0 ||
Player.sourceFiles.length > 0) {
//If you have already purchased an Aug...you are far enough in the game
//that everything should be available
Player.firstFacInvRecvd = true;
Player.firstAugPurchased = true;
Player.firstJobRecvd = true;
Player.firstTimeTraveled = true;
Player.firstProgramAvailable = true;
} else {
if (Player.factions.length > 0 || Player.factionInvitations.length > 0) {
Player.firstFacInvRecvd = true;
}
if (Player.companyName !== "" || Player.companyPosition !== "") {
Player.firstJobRecvd = true;
}
if (Player.hacking_skill >= 25) {
Player.firstScriptAvailable = true;
// This version refactored the Company/job-related code
if (ver < "0.41.2") {
// Player's company position is now a string
if (Player.companyPosition !== "" || Player.companyPosition instanceof CompanyPosition) {
console.log("Changed Player.companyPosition value to be compatible with v0.41.2");
Player.companyPosition = Player.companyPosition.positionName;
}
// The "companyName" property of all Companies is renamed to "name"
for (var companyName in Companies) {
const company = Companies[companyName];
if (company.name == null && company.companyName != null) {
console.log("Changed company name property to be compatible with v0.41.2");
company.name = company.companyName;
}
}
}
@ -310,23 +301,27 @@ function loadImportedGame(saveObj, saveString) {
if (tempSaveObj.hasOwnProperty("VersionSave")) {
try {
var ver = JSON.parse(tempSaveObj.VersionSave, Reviver);
if (ver.startsWith("0.27.") || ver.startsWith("0.28.")) {
if (tempPlayer.bitNodeN == null || tempPlayer.bitNodeN == 0) {
tempPlayer.bitNodeN = 1;
// This version refactored the Company/job-related code
if (ver < "0.41.2") {
// Player's company position is now a string
if (Player.companyPosition !== "" || Player.companyPosition instanceof CompanyPosition) {
console.log("Changed Player.companyPosition value to be compatible with v0.41.2");
Player.companyPosition = Player.companyPosition.positionName;
}
if (tempPlayer.sourceFiles == null) {
tempPlayer.sourceFiles = [];
// The "companyName" property of all Companies is renamed to "name"
for (var companyName in Companies) {
const company = Companies[companyName];
if (company.name == null && company.companyName != null) {
console.log("Changed company name property to be compatible with v0.41.2");
company.name = company.companyName;
}
}
}
if (ver != CONSTANTS.Version) {
//createNewUpdateText();
}
} catch(e) {
console.log("Parsing Version save failed: " + e);
//createNewUpdateText();
console.error("Parsing Version save failed: " + e);
}
} else {
//createNewUpdateText();
}
if (tempPlayer.bitNodeN == 2 && tempPlayer.inGang() && tempSaveObj.hasOwnProperty("AllGangsSave")) {
try {
@ -405,30 +400,20 @@ function loadImportedGame(saveObj, saveString) {
if (saveObj.hasOwnProperty("VersionSave")) {
try {
var ver = JSON.parse(saveObj.VersionSave, Reviver);
if (Player.bitNodeN == null || Player.bitNodeN == 0) {
Player.setBitNodeNumber(1);
// This version refactored the Company/job-related code
if (ver < "0.41.2") {
// Player's company position is now a string
if (Player.companyPosition !== "" || Player.companyPosition instanceof CompanyPosition) {
console.log("Changed Player.companyPosition value to be compatible with v0.41.2");
Player.companyPosition = Player.companyPosition.positionName;
}
}
if (ver.startsWith("0.27.") || ver.startsWith("0.28.")) {
console.log("Evaluating changes needed for version compatibility");
if (Player.augmentations.length > 0 || Player.queuedAugmentations.length > 0 ||
Player.sourceFiles.length > 0) {
//If you have already purchased an Aug...you are far enough in the game
//that everything should be available
Player.firstFacInvRecvd = true;
Player.firstAugPurchased = true;
Player.firstJobRecvd = true;
Player.firstTimeTraveled = true;
Player.firstProgramAvailable = true;
} else {
if (Player.factions.length > 0 || Player.factionInvitations.length > 0) {
Player.firstFacInvRecvd = true;
}
if (Player.companyName !== "" || Player.companyPosition !== "") {
Player.firstJobRecvd = true;
}
if (Player.hacking_skill >= 25) {
Player.firstScriptAvailable = true;
// The "companyName" property of all Companies is renamed to "name"
for (var companyName in Companies) {
const company = Companies[companyName];
if (company.name == null && company.companyName != null) {
console.log("Changed company name property to be compatible with v0.41.2");
company.name = company.companyName;
}
}
}
@ -467,7 +452,6 @@ function loadImportedGame(saveObj, saveString) {
console.log("Importing game");
Engine.setDisplayElements(); //Sets variables for important DOM elements
Engine.init(); //Initialize buttons, work, etc.
CompanyPositions.init();
//Calculate the number of cycles have elapsed while offline
Engine._lastUpdate = new Date().getTime();

@ -25,7 +25,8 @@ import {Bladeburner} from "./Bladeburner";
import {CharacterOverview} from "./CharacterOverview";
import {cinematicTextFlag} from "./CinematicText";
import {generateRandomContract} from "./CodingContractGenerator";
import {CompanyPositions, initCompanies} from "./Company";
import {CompanyPositions} from "./Company/CompanyPositions";
import {initCompanies} from "./Company/Companies";
import {Corporation} from "./CompanyManagement";
import {CONSTANTS} from "./Constants";
import {displayCreateProgramContent,
@ -537,8 +538,8 @@ const Engine = {
removeChildrenFromElement(Engine.Display.characterInfo);
var companyPosition = "";
if (Player.companyPosition != "") {
companyPosition = Player.companyPosition.positionName;
if (Player.companyPosition !== "") {
companyPosition = Player.companyPosition;
}
var intText = "";
@ -1201,7 +1202,6 @@ const Engine = {
initSourceFiles();
Engine.setDisplayElements(); //Sets variables for important DOM elements
Engine.init(); //Initialize buttons, work, etc.
CompanyPositions.init();
initAugmentations(); //Also calls Player.reapplyAllAugmentations()
Player.reapplyAllSourceFiles();
initStockSymbols();
@ -1302,7 +1302,6 @@ const Engine = {
initForeignServers();
initCompanies();
initFactions();
CompanyPositions.init();
initAugmentations();
initMessages();
initStockSymbols();

@ -0,0 +1,7 @@
// Modified version of Object.assign() that prevents you from
// accidentally modifying the 'target' (first argument)
export function SafeObjectAssign(...args: any[]) {
const argsCopy: any[] = Array.from(arguments);
argsCopy.unshift({});
Object.assign.apply(null, argsCopy);
}