Merge pull request #512 from danielyxie/company-code-refactor

Company code refactor
This commit is contained in:
danielyxie 2018-11-17 16:25:57 -08:00 committed by GitHub
commit 0647399356
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
24 changed files with 171505 additions and 1553 deletions

58610
dist/engine.bundle.js vendored

File diff suppressed because one or more lines are too long

111046
dist/vendor.bundle.js vendored

File diff suppressed because one or more lines are too long

@ -2,7 +2,7 @@
<html lang="en"> <html lang="en">
<head> <head>
<meta charset="utf-8"> <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="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="32x32" href="dist/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="dist/favicon-16x16.png"> <link rel="icon" type="image/png" sizes="16x16" href="dist/favicon-16x16.png">
@ -474,7 +474,8 @@
<!-- Tutorial content --> <!-- Tutorial content -->
<div id="tutorial-container" class="generic-menupage-container"> <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-networking-link" class="a-link-button"> Servers & Networking </a>
<a id="tutorial-hacking-link" class="a-link-button"> Hacking </a> <a id="tutorial-hacking-link" class="a-link-button"> Hacking </a>
<a id="tutorial-scripts-link" class="a-link-button"> Scripts </a> <a id="tutorial-scripts-link" class="a-link-button"> Scripts </a>
@ -483,7 +484,8 @@
<a id="tutorial-jobs-link" class="a-link-button"> Companies and Infiltration </a> <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-factions-link" class="a-link-button"> Factions </a>
<a id="tutorial-augmentations-link" class="a-link-button"> Augmentations </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> <a id="tutorial-back-button" class="a-link-button"> Back </a>
<p id="tutorial-text"> </p> <p id="tutorial-text"> </p>

File diff suppressed because it is too large Load Diff

50
src/Company/Companies.ts Normal file

@ -0,0 +1,50 @@
// 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() {
// Save Old Company data for 'favor'
const oldCompanies = Companies;
// Re-construct all Companies
Companies = {};
companiesMetadata.forEach((e) => {
addCompany(e);
});
// Reset data
for (const companyName in Companies) {
const company = Companies[companyName];
const oldCompany = oldCompanies[companyName];
if (!(oldCompany instanceof Company)) {
// New game, so no OldCompanies data
company.favor = 0;
} else {
company.favor = oldCompanies[companyName].favor;
if (isNaN(company.favor)) { company.favor = 0; }
}
}
}
// 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);
}

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;

@ -0,0 +1,182 @@
import { CONSTANTS } from "../Constants";
import * as names from "./data/CompanyPositionNames";
/* tslint:disable:completed-docs */
export interface IConstructorParams {
name: string;
nextPosition: string | null;
baseSalary: number;
repMultiplier: number;
reqdHacking?: number;
reqdStrength?: number;
reqdDefense?: number;
reqdDexterity?: number;
reqdAgility?: number;
reqdCharisma?: number;
reqdReputation?: number;
hackingEffectiveness?: number;
strengthEffectiveness?: number;
defenseEffectiveness?: number;
dexterityEffectiveness?: number;
agilityEffectiveness?: number;
charismaEffectiveness?: number;
hackingExpGain?: number;
strengthExpGain?: number;
defenseExpGain?: number;
dexterityExpGain?: number;
agilityExpGain?: number;
charismaExpGain?: number;
}
export class CompanyPosition {
/**
* Position title
*/
name: string;
/**
* Title of next position to be promoted to
*/
nextPosition: string | null;
/**
* Base salary for this position ($ per 200ms game cycle)
* Will be multiplier by a company-specific multiplier for final salary
*/
baseSalary: number;
/**
* Reputation multiplier
*/
repMultiplier: number;
/**
* Required stats to earn this position
*/
requiredAgility: number;
requiredCharisma: number;
requiredDefense: number;
requiredDexterity: number;
requiredHacking: number;
requiredStrength: number;
/**
* Required company reputation to earn this position
*/
requiredReputation: number;
/**
* Effectiveness of each stat time for job performance
*/
hackingEffectiveness: number;
strengthEffectiveness: number;
defenseEffectiveness: number;
dexterityEffectiveness: number;
agilityEffectiveness: number;
charismaEffectiveness: number;
/**
* Experience gain for performing job (per 200ms game cycle)
*/
hackingExpGain: number;
strengthExpGain: number;
defenseExpGain: number;
dexterityExpGain: number;
agilityExpGain: number;
charismaExpGain: number;
constructor(p: IConstructorParams) {
this.name = p.name;
this.nextPosition = p.nextPosition;
this.baseSalary = p.baseSalary;
this.repMultiplier = p.repMultiplier;
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;
this.defenseEffectiveness = (p.defenseEffectiveness != null) ? p.defenseEffectiveness : 0;
this.dexterityEffectiveness = (p.dexterityEffectiveness != null) ? p.dexterityEffectiveness : 0;
this.agilityEffectiveness = (p.agilityEffectiveness != null) ? p.agilityEffectiveness : 0;
this.charismaEffectiveness = (p.charismaEffectiveness != null) ? p.charismaEffectiveness : 0;
if (Math.round(this.hackingEffectiveness + this.strengthEffectiveness + this.defenseEffectiveness +
this.dexterityEffectiveness + this.agilityEffectiveness + this.charismaEffectiveness) !== 100) {
console.error(`CompanyPosition ${this.name} parameters do not sum to 100`);
}
this.hackingExpGain = (p.hackingExpGain != null) ? p.hackingExpGain : 0;
this.strengthExpGain = (p.strengthExpGain != null) ? p.strengthExpGain : 0;
this.defenseExpGain = (p.defenseExpGain != null) ? p.defenseExpGain : 0;
this.dexterityExpGain = (p.dexterityExpGain != null) ? p.dexterityExpGain : 0;
this.agilityExpGain = (p.agilityExpGain != null) ? p.agilityExpGain : 0;
this.charismaExpGain = (p.charismaExpGain != null) ? p.charismaExpGain : 0;
}
calculateJobPerformance(hack: number, str: number, def: number, dex: number, agi: number, cha: number): number {
const hackRatio: number = this.hackingEffectiveness * hack / CONSTANTS.MaxSkillLevel;
const strRatio: number = this.strengthEffectiveness * str / CONSTANTS.MaxSkillLevel;
const defRatio: number = this.defenseEffectiveness * def / CONSTANTS.MaxSkillLevel;
const dexRatio: number = this.dexterityEffectiveness * dex / CONSTANTS.MaxSkillLevel;
const agiRatio: number = this.agilityEffectiveness * agi / CONSTANTS.MaxSkillLevel;
const chaRatio: number = this.charismaEffectiveness * cha / CONSTANTS.MaxSkillLevel;
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;
}
return reputationGain;
}
isSoftwareJob(): boolean {
return names.SoftwareCompanyPositions.includes(this.name);
}
isITJob(): boolean {
return names.ITCompanyPositions.includes(this.name);
}
isSecurityEngineerJob(): boolean {
return names.SecurityEngineerCompanyPositions.includes(this.name);
}
isNetworkEngineerJob(): boolean {
return names.NetworkEngineerCompanyPositions.includes(this.name);
}
isBusinessJob(): boolean {
return names.BusinessCompanyPositions.includes(this.name);
}
isSecurityJob(): boolean {
return names.SecurityCompanyPositions.includes(this.name);
}
isAgentJob(): boolean {
return names.AgentCompanyPositions.includes(this.name);
}
isSoftwareConsultantJob(): boolean {
return names.SoftwareConsultantCompanyPositions.includes(this.name);
}
isBusinessConsultantJob(): boolean {
return names.BusinessConsultantCompanyPositions.includes(this.name);
}
isPartTimeJob(): boolean {
return names.PartTimeCompanyPositions.includes(this.name);
}
}

@ -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,544 @@
import { IConstructorParams } from "../Company";
import { Locations } from "../../Locations";
import * as posNames from "./CompanyPositionNames";
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: Object.assign({},
CEOOnly,
OperationsManagerOnly,
AllTechnologyPositions,
AllSecurityPositions,
),
expMultiplier: 1.7,
salaryMultiplier: 1.7,
jobStatReqOffset: 199,
},
{
name: Locations.ChongqingSolarisSpaceSystems,
info: "",
companyPositions: Object.assign({},
CEOOnly,
OperationsManagerOnly,
AllTechnologyPositions,
AllSecurityPositions,
),
expMultiplier: 1.7,
salaryMultiplier: 1.7,
jobStatReqOffset: 199,
},
{
name: Locations.Sector12DeltaOne,
info: "",
companyPositions: Object.assign({},
CEOOnly,
OperationsManagerOnly,
AllTechnologyPositions,
AllSecurityPositions,
),
expMultiplier: 1.6,
salaryMultiplier: 1.6,
jobStatReqOffset: 199,
},
{
name: Locations.NewTokyoGlobalPharmaceuticals,
info: "",
companyPositions: Object.assign({},
AllTechnologyPositions,
AllBusinessPositions,
AllSoftwareConsultantPositions,
AllSecurityPositions
),
expMultiplier: 1.8,
salaryMultiplier: 1.8,
jobStatReqOffset: 224,
},
{
name: Locations.IshimaNovaMedical,
info: "",
companyPositions: Object.assign({},
AllTechnologyPositions,
AllBusinessPositions,
AllSoftwareConsultantPositions,
AllSecurityPositions
),
expMultiplier: 1.75,
salaryMultiplier: 1.75,
jobStatReqOffset: 199,
},
{
name: Locations.Sector12CIA,
info: "",
companyPositions: Object.assign({},
SoftwarePositionsUpToHeadOfEngineering,
AllNetworkEngineerPositions,
AllITPositions,
AllSecurityPositions,
AllAgentPositions
),
expMultiplier: 2,
salaryMultiplier: 2,
jobStatReqOffset: 149,
},
{
name: Locations.Sector12NSA,
info: "",
companyPositions: Object.assign({},
SoftwarePositionsUpToHeadOfEngineering,
AllNetworkEngineerPositions,
AllITPositions,
AllSecurityPositions,
AllAgentPositions
),
expMultiplier: 2,
salaryMultiplier: 2,
jobStatReqOffset: 149,
},
{
name: Locations.AevumWatchdogSecurity,
info: "",
companyPositions: Object.assign({},
SoftwarePositionsUpToHeadOfEngineering,
AllNetworkEngineerPositions,
AllITPositions,
AllSecurityPositions,
AllAgentPositions,
AllSoftwareConsultantPositions
),
expMultiplier: 1.5,
salaryMultiplier: 1.5,
jobStatReqOffset: 124,
},
{
name: Locations.VolhavenLexoCorp,
info: "",
companyPositions: Object.assign({},
AllTechnologyPositions,
AllSoftwareConsultantPositions,
AllBusinessPositions,
AllSecurityPositions
),
expMultiplier: 1.4,
salaryMultiplier: 1.4,
jobStatReqOffset: 99,
},
{
name: Locations.AevumRhoConstruction,
info: "",
companyPositions: Object.assign({},
SoftwarePositionsUpToLeadDeveloper,
BusinessPositionsUpToOperationsManager
),
expMultiplier: 1.3,
salaryMultiplier: 1.3,
jobStatReqOffset: 49,
},
{
name: Locations.Sector12AlphaEnterprises,
info: "",
companyPositions: Object.assign({},
SoftwarePositionsUpToLeadDeveloper,
BusinessPositionsUpToOperationsManager,
AllSoftwareConsultantPositions
),
expMultiplier: 1.5,
salaryMultiplier: 1.5,
jobStatReqOffset: 99,
},
{
name: Locations.AevumPolice,
info: "",
companyPositions: Object.assign({},
AllSecurityPositions,
SoftwarePositionsUpToLeadDeveloper
),
expMultiplier: 1.3,
salaryMultiplier: 1.3,
jobStatReqOffset: 99,
},
{
name: Locations.VolhavenSysCoreSecurities,
info: "",
companyPositions: Object.assign({},
AllTechnologyPositions
),
expMultiplier: 1.3,
salaryMultiplier: 1.3,
jobStatReqOffset: 124,
},
{
name: Locations.VolhavenCompuTek,
info: "",
companyPositions: Object.assign({},
AllTechnologyPositions
),
expMultiplier: 1.2,
salaryMultiplier: 1.2,
jobStatReqOffset: 74,
},
{
name: Locations.AevumNetLinkTechnologies,
info: "",
companyPositions: Object.assign({},
AllTechnologyPositions
),
expMultiplier: 1.2,
salaryMultiplier: 1.2,
jobStatReqOffset: 99,
},
{
name: Locations.Sector12CarmichaelSecurity,
info: "",
companyPositions: Object.assign({},
AllTechnologyPositions,
AllAgentPositions,
AllSecurityPositions
),
expMultiplier: 1.2,
salaryMultiplier: 1.2,
jobStatReqOffset: 74,
},
{
name: Locations.Sector12FoodNStuff,
info: "",
companyPositions: Object.assign({},
EmployeeOnly, PartTimeEmployeeOnly
),
expMultiplier: 1,
salaryMultiplier: 1,
jobStatReqOffset: 0,
},
{
name: Locations.Sector12JoesGuns,
info: "",
companyPositions: Object.assign({},
EmployeeOnly, PartTimeEmployeeOnly
),
expMultiplier: 1,
salaryMultiplier: 1,
jobStatReqOffset: 0,
},
{
name: Locations.IshimaOmegaSoftware,
info: "",
companyPositions: Object.assign({},
AllSoftwarePositions,
AllSoftwareConsultantPositions,
AllITPositions
),
expMultiplier: 1.1,
salaryMultiplier: 1.1,
jobStatReqOffset: 49,
},
{
name: Locations.NewTokyoNoodleBar,
info: "",
companyPositions: Object.assign({},
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: 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[1], // 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[1], // Secret Agent
nextPosition: posNames.AgentCompanyPositions[2], // 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[2], // 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[1], // 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,
},
]

@ -0,0 +1,72 @@
// Defs for job titles, stored in arrays and categorized by job "type"
export const SoftwareCompanyPositions: string[] = [
"Software Engineering Intern",
"Junior Software Engineer",
"Senior Software Engineer",
"Lead Software Developer",
"Head of Software",
"Head of Engineering",
"Vice President of Technology",
"Chief Technology Officer"
];
export const ITCompanyPositions: string[] = [
"IT Intern",
"IT Analyst",
"IT Manager",
"Systems Administrator"
];
export const SecurityEngineerCompanyPositions: string[] = [
"Security Engineer"
];
export const NetworkEngineerCompanyPositions: string[] = [
"Network Engineer",
"Network Administrator"
];
export const BusinessCompanyPositions: string[] = [
"Business Intern",
"Business Analyst",
"Business Manager",
"Operations Manager",
"Chief Financial Officer",
"Chief Executive Officer"
];
export const SecurityCompanyPositions: string[] = [
"Police Officer",
"Police Chief",
"Security Guard",
"Security Officer",
"Security Supervisor",
"Head of Security"
];
export const AgentCompanyPositions: string[] = [
"Field Agent",
"Secret Agent",
"Special Operative"
];
export const MiscCompanyPositions: string[] = [
"Waiter",
"Employee"
];
export const SoftwareConsultantCompanyPositions: string[] = [
"Software Consultant",
"Senior Software Consultant"
];
export const BusinessConsultantCompanyPositions: string[] = [
"Business Consultant",
"Senior Business Consultant"
];
export const PartTimeCompanyPositions: string[] = [
"Part-time Waiter",
"Part-time Employee"
];

@ -1,5 +1,7 @@
let CONSTANTS = { import {IMap} from "./types";
Version: "0.41.1",
export let CONSTANTS: IMap<any> = {
Version: "0.41.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
@ -509,8 +511,9 @@ let CONSTANTS = {
* Gang Changes: * Gang Changes:
** UI now displays your chance to win a clash with other gangs ** UI now displays your chance to win a clash with other gangs
** Added getChanceToWinClash() function to the Gang API ** Added getChanceToWinClash() function to the Gang API
* Added the terminal command 'expr', which can be used to evaluate simple mathematical expressions
* Bug Fix: scp() should no longer throw errors when used with 2-arguments and an array of files
` `
} }
export {CONSTANTS};

@ -10,6 +10,7 @@ export const TerminalHelpText: string =
"cls See 'clear' command <br>" + "cls See 'clear' command <br>" +
"connect [ip/hostname] Connects to a remote server<br>" + "connect [ip/hostname] Connects to a remote server<br>" +
"download [script/text file] Downloads scripts or text files to your computer<br>" + "download [script/text file] Downloads scripts or text files to your computer<br>" +
"expr [math expression] Evaluate a mathematical expression<br>" +
"free Check the machine's memory (RAM) usage<br>" + "free Check the machine's memory (RAM) usage<br>" +
"hack Hack the current machine<br>" + "hack Hack the current machine<br>" +
"help [command] Display this help text, or the help text for a command<br>" + "help [command] Display this help text, or the help text for a command<br>" +
@ -96,6 +97,12 @@ export const HelpTexts: IMap<string> = {
"Download all scripts and text files: download *<br>" + "Download all scripts and text files: download *<br>" +
"Download all scripts: download *.script<br>" + "Download all scripts: download *.script<br>" +
"Download all text files: download *.txt<br>", "Download all text files: download *.txt<br>",
expr: "expr [mathematical expression]<br>" +
"Evaluate a simple mathematical expression. Supports native JavaScript operators:<br>" +
"+, -, /, *, **, %<br>" +
"Example:<br>" +
"expr 25 * 2 ** 10<br>" +
"Note that letters (non-digits) are not allowed and will be removed from the input.",
free: "free<br>" + free: "free<br>" +
"Display's the memory usage on the current machine. Print the amount of RAM that is available on the current server as well as " + "Display's the memory usage on the current machine. Print the amount of RAM that is available on the current server as well as " +
"how much of it is being used.", "how much of it is being used.",

@ -1,6 +1,8 @@
import {Bladeburner} from "./Bladeburner"; import {Bladeburner} from "./Bladeburner";
import {CompanyPositions, initCompanies, import {CompanyPositions} from "./Company/CompanyPositions";
Companies, getJobRequirementText} from "./Company"; import {Companies} from "./Company/Companies";
import {getJobRequirementText} from "./Company/GetJobRequirementText";
import * as posNames from "./Company/data/CompanyPositionNames";
import {Corporation} from "./CompanyManagement"; import {Corporation} from "./CompanyManagement";
import {CONSTANTS} from "./Constants"; import {CONSTANTS} from "./Constants";
import {Crimes} from "./Crimes"; import {Crimes} from "./Crimes";
@ -233,7 +235,7 @@ function displayLocationContent() {
//Check if the player is employed at this Location. If he is, display the "Work" button, //Check if the player is employed at this Location. If he is, display the "Work" button,
//update the job title, etc. //update the job title, etc.
if (loc != "" && loc === Player.companyName) { if (loc != "" && loc === Player.companyName) {
var company = Companies[loc]; let company = Companies[loc];
jobTitle.style.display = "block"; jobTitle.style.display = "block";
jobReputation.style.display = "inline"; jobReputation.style.display = "inline";
@ -241,8 +243,8 @@ function displayLocationContent() {
locationTxtDiv1.style.display = "block"; locationTxtDiv1.style.display = "block";
locationTxtDiv2.style.display = "block"; locationTxtDiv2.style.display = "block";
locationTxtDiv3.style.display = "block"; locationTxtDiv3.style.display = "block";
jobTitle.innerHTML = "Job Title: " + Player.companyPosition.positionName; jobTitle.innerHTML = "Job Title: " + Player.companyPosition;
var repGain = company.getFavorGain(); let repGain = company.getFavorGain();
if (repGain.length != 2) {repGain = 0;} if (repGain.length != 2) {repGain = 0;}
repGain = repGain[0]; repGain = repGain[0];
jobReputation.innerHTML = "Company reputation: " + formatNumber(company.playerReputation, 4) + jobReputation.innerHTML = "Company reputation: " + formatNumber(company.playerReputation, 4) +
@ -256,7 +258,10 @@ function displayLocationContent() {
"favor you gain depends on how much reputation you have with the company</span>"; "favor you gain depends on how much reputation you have with the company</span>";
work.style.display = "block"; work.style.display = "block";
var currPos = Player.companyPosition; let currPos = CompanyPositions[Player.companyPosition];
if (currPos == null) {
throw new Error("Player's companyPosition property has an invalid value");
}
work.addEventListener("click", function() { work.addEventListener("click", function() {
if (currPos.isPartTimeJob()) { if (currPos.isPartTimeJob()) {
@ -301,19 +306,19 @@ function displayLocationContent() {
var hospitalTreatmentCost = (Player.max_hp - Player.hp) * CONSTANTS.HospitalCostPerHp; var hospitalTreatmentCost = (Player.max_hp - Player.hp) * CONSTANTS.HospitalCostPerHp;
//Set tooltip for job requirements //Set tooltip for job requirements
setJobRequirementTooltip(loc, CompanyPositions.SoftwareIntern, softwareJob); setJobRequirementTooltip(loc, CompanyPositions[posNames.SoftwareCompanyPositions[0]], softwareJob);
setJobRequirementTooltip(loc, CompanyPositions.SoftwareConsultant, softwareConsultantJob); setJobRequirementTooltip(loc, CompanyPositions[posNames.SoftwareConsultantCompanyPositions[0]], softwareConsultantJob);
setJobRequirementTooltip(loc, CompanyPositions.ITIntern, itJob); setJobRequirementTooltip(loc, CompanyPositions[posNames.ITCompanyPositions[0]], itJob);
setJobRequirementTooltip(loc, CompanyPositions.SecurityEngineer, securityEngineerJob); setJobRequirementTooltip(loc, CompanyPositions[posNames.SecurityEngineerCompanyPositions[0]], securityEngineerJob);
setJobRequirementTooltip(loc, CompanyPositions.NetworkEngineer, networkEngineerJob); setJobRequirementTooltip(loc, CompanyPositions[posNames.NetworkEngineerCompanyPositions[0]], networkEngineerJob);
setJobRequirementTooltip(loc, CompanyPositions.BusinessIntern, businessJob); setJobRequirementTooltip(loc, CompanyPositions[posNames.BusinessCompanyPositions[0]], businessJob);
setJobRequirementTooltip(loc, CompanyPositions.BusinessConsultant, businessConsultantJob); setJobRequirementTooltip(loc, CompanyPositions[posNames.BusinessConsultantCompanyPositions[0]], businessConsultantJob);
setJobRequirementTooltip(loc, CompanyPositions.SecurityGuard, securityJob); setJobRequirementTooltip(loc, CompanyPositions[posNames.SecurityCompanyPositions[0]], securityJob);
setJobRequirementTooltip(loc, CompanyPositions.FieldAgent, agentJob); setJobRequirementTooltip(loc, CompanyPositions[posNames.AgentCompanyPositions[0]], agentJob);
setJobRequirementTooltip(loc, CompanyPositions.Employee, employeeJob); setJobRequirementTooltip(loc, CompanyPositions[posNames.MiscCompanyPositions[1]], employeeJob);
setJobRequirementTooltip(loc, CompanyPositions.PartTimeEmployee, employeePartTimeJob); setJobRequirementTooltip(loc, CompanyPositions[posNames.PartTimeCompanyPositions[1]], employeePartTimeJob);
setJobRequirementTooltip(loc, CompanyPositions.Waiter, waiterJob); setJobRequirementTooltip(loc, CompanyPositions[posNames.MiscCompanyPositions[0]], waiterJob);
setJobRequirementTooltip(loc, CompanyPositions.PartTimeWaiter, waiterPartTimeJob); setJobRequirementTooltip(loc, CompanyPositions[posNames.PartTimeCompanyPositions[0]], waiterPartTimeJob);
switch (loc) { switch (loc) {
case Locations.AevumTravelAgency: case Locations.AevumTravelAgency:
@ -1035,13 +1040,13 @@ function displayLocationContent() {
if (loc == Player.companyName) { if (loc == Player.companyName) {
var currPos = Player.companyPosition; var currPos = Player.companyPosition;
if (currPos.positionName == CompanyPositions.Employee.positionName) { if (currPos == "Employee") {
employeeJob.style.display = "none"; employeeJob.style.display = "none";
} else if (currPos.positionName == CompanyPositions.Waiter.positionName) { } else if (currPos == "Waiter") {
waiterJob.style.display = "none"; waiterJob.style.display = "none";
} else if (currPos.positionName == CompanyPositions.PartTimeEmployee.positionName) { } else if (currPos == "Part-time Employee") {
employeePartTimeJob.style.display = "none"; employeePartTimeJob.style.display = "none";
} else if (currPos.positionName == CompanyPositions.PartTimeWaiter.positionName) { } else if (currPos == "Part-time Waiter") {
waiterPartTimeJob.style.display = "none"; waiterPartTimeJob.style.display = "none";
} }
} }

@ -8,8 +8,10 @@ import {Augmentations, Augmentation,
import {BitNodeMultipliers} from "./BitNodeMultipliers"; import {BitNodeMultipliers} from "./BitNodeMultipliers";
import {determineCrimeSuccess, findCrime} from "./Crimes"; import {determineCrimeSuccess, findCrime} from "./Crimes";
import {Bladeburner} from "./Bladeburner"; import {Bladeburner} from "./Bladeburner";
import {Companies, Company, CompanyPosition, import {Company} from "./Company/Company";
CompanyPositions, companyExists} from "./Company"; import {Companies, companyExists} from "./Company/Companies";
import {CompanyPosition} from "./Company/CompanyPosition";
import {CompanyPositions} from "./Company/CompanyPositions";
import {CONSTANTS} from "./Constants"; import {CONSTANTS} from "./Constants";
import {Programs} from "./CreateProgram"; import {Programs} from "./CreateProgram";
import {DarkWebItems} from "./DarkWeb"; import {DarkWebItems} from "./DarkWeb";
@ -919,7 +921,7 @@ function NetscriptFunctions(workerScript) {
var destServer, currServ; var destServer, currServ;
if (arguments.length === 3) { //scriptname, source, destination if (ip2 != null) { // 3 Argument version: scriptname, source, destination
if (scriptname === undefined || ip1 === undefined || ip2 === undefined) { if (scriptname === undefined || ip1 === undefined || ip2 === undefined) {
throw makeRuntimeRejectMsg(workerScript, "ERROR: scp() call has incorrect number of arguments. Takes 2 or 3 arguments"); throw makeRuntimeRejectMsg(workerScript, "ERROR: scp() call has incorrect number of arguments. Takes 2 or 3 arguments");
} }
@ -932,7 +934,7 @@ function NetscriptFunctions(workerScript) {
if (currServ == null) { if (currServ == null) {
throw makeRuntimeRejectMsg(workerScript, `ERROR: Invalid hostname/ip passed into scp() command: ${ip1}`); throw makeRuntimeRejectMsg(workerScript, `ERROR: Invalid hostname/ip passed into scp() command: ${ip1}`);
} }
} else if (arguments.length === 2) { //scriptname, destination } else if (ip1 != null) { // 2 Argument version: scriptname, destination
if (scriptname === undefined || ip1 === undefined) { if (scriptname === undefined || ip1 === undefined) {
throw makeRuntimeRejectMsg(workerScript, "ERROR: scp() call has incorrect number of arguments. Takes 2 or 3 arguments"); throw makeRuntimeRejectMsg(workerScript, "ERROR: scp() call has incorrect number of arguments. Takes 2 or 3 arguments");
} }
@ -945,6 +947,8 @@ function NetscriptFunctions(workerScript) {
if (currServ == null) { if (currServ == null) {
throw makeRuntimeRejectMsg(workerScript, "Could not find server ip for this script. This is a bug please contact game developer"); throw makeRuntimeRejectMsg(workerScript, "Could not find server ip for this script. This is a bug please contact game developer");
} }
} else {
throw makeRuntimeRejectMsg(workerScript, "ERROR: scp() call has incorrect number of arguments. Takes 2 or 3 arguments");
} }
//Scp for lit files //Scp for lit files
@ -2783,8 +2787,8 @@ function NetscriptFunctions(workerScript) {
} }
var companyPositionTitle = ""; var companyPositionTitle = "";
if (Player.companyPosition instanceof CompanyPosition) { if (CompanyPositions[Player.companyPosition] instanceof CompanyPosition) {
companyPositionTitle = Player.companyPosition.positionName; companyPositionTitle = Player.companyPosition;
} }
return { return {
bitnode: Player.bitNodeN, bitnode: Player.bitNodeN,
@ -2925,7 +2929,8 @@ function NetscriptFunctions(workerScript) {
return; 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"); workerScript.scriptRef.log("ERROR: workForCompany() failed because you do not have a job");
return false; return false;
} }
@ -2937,13 +2942,13 @@ function NetscriptFunctions(workerScript) {
} }
} }
if (Player.companyPosition.isPartTimeJob()) { if (companyPosition.isPartTimeJob()) {
Player.startWorkPartTime(); Player.startWorkPartTime();
} else { } else {
Player.startWork(); Player.startWork();
} }
if (workerScript.disableLogs.ALL == null && workerScript.disableLogs.workForCompany == null) { 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; return true;
}, },
@ -3019,11 +3024,11 @@ function NetscriptFunctions(workerScript) {
} }
if (res) { if (res) {
if (workerScript.disableLogs.ALL == null && workerScript.disableLogs.applyToCompany == null) { 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 { } else {
if (workerScript.disableLogs.ALL == null && workerScript.disableLogs.applyToCompany == null) { 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; return res;

@ -3,9 +3,12 @@ import {Augmentations, applyAugmentation,
PlayerOwnedAugmentation} from "./Augmentations"; PlayerOwnedAugmentation} from "./Augmentations";
import {BitNodeMultipliers} from "./BitNodeMultipliers"; import {BitNodeMultipliers} from "./BitNodeMultipliers";
import {CodingContractRewardType} from "./CodingContracts"; import {CodingContractRewardType} from "./CodingContracts";
import {Company, Companies, getNextCompanyPosition, import {Company} from "./Company/Company";
getJobRequirementText, CompanyPosition, import {Companies} from "./Company/Companies";
CompanyPositions} from "./Company"; import {getNextCompanyPosition} from "./Company/GetNextCompanyPosition";
import {getJobRequirementText} from "./Company/GetJobRequirementText";
import {CompanyPositions} from "./Company/CompanyPositions";
import * as posNames from "./Company/data/CompanyPositionNames";
import {CONSTANTS} from "./Constants"; import {CONSTANTS} from "./Constants";
import {Corporation} from "./CompanyManagement"; import {Corporation} from "./CompanyManagement";
import {Programs} from "./CreateProgram"; import {Programs} from "./CreateProgram";
@ -94,8 +97,8 @@ function PlayerObject() {
this.location = ""; this.location = "";
//Company Information //Company Information
this.companyName = ""; //Name of Company, equivalent to an object from Locations this.companyName = ""; // Name of Company. Must match a key value in Companies map
this.companyPosition = ""; //CompanyPosition object this.companyPosition = ""; // Name of Company Position. Must match a key value in CompanyPositions map
//Servers //Servers
this.currentServer = ""; //IP address of Server currently being accessed through terminal this.currentServer = ""; //IP address of Server currently being accessed through terminal
@ -709,13 +712,13 @@ PlayerObject.prototype.work = function(numCycles) {
var comp = Companies[this.companyName], companyRep = "0"; var comp = Companies[this.companyName], companyRep = "0";
if (comp == null || !(comp instanceof Company)) { if (comp == null || !(comp instanceof Company)) {
console.log("ERROR: Could not find Company: " + this.companyName); console.error(`Could not find Company: ${this.companyName}`);
} else { } else {
companyRep = comp.playerReputation; companyRep = comp.playerReputation;
} }
var txt = document.getElementById("work-in-progress-text"); 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: " + " at " + this.companyName + " (Current Company Reputation: " +
numeralWrapper.format(companyRep, '0,0') + ")<br><br>" + numeralWrapper.format(companyRep, '0,0') + ")<br><br>" +
"You have been working for " + convertTimeMsToTimeElapsedString(this.timeWorked) + "<br><br>" + "You have been working for " + convertTimeMsToTimeElapsedString(this.timeWorked) + "<br><br>" +
@ -837,7 +840,7 @@ PlayerObject.prototype.workPartTime = function(numCycles) {
} }
var txt = document.getElementById("work-in-progress-text"); 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: " + " at " + Player.companyName + " (Current Company Reputation: " +
numeralWrapper.format(companyRep, '0,0') + ")<br><br>" + numeralWrapper.format(companyRep, '0,0') + ")<br><br>" +
"You have been working for " + convertTimeMsToTimeElapsedString(this.timeWorked) + "<br><br>" + "You have been working for " + convertTimeMsToTimeElapsedString(this.timeWorked) + "<br><br>" +
@ -1069,61 +1072,117 @@ PlayerObject.prototype.finishFactionWork = function(cancelled, sing=false) {
//Money gained per game cycle //Money gained per game cycle
PlayerObject.prototype.getWorkMoneyGain = function() { PlayerObject.prototype.getWorkMoneyGain = function() {
var bn11Mult = 1; // If player has SF-11, calculate salary multiplier from favor
var company = Companies[this.companyName]; let bn11Mult = 1;
if (hasBn11SF) { const company = Companies[this.companyName];
bn11Mult = 1 + (company.favor / 100); 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 //Hack exp gained per game cycle
PlayerObject.prototype.getWorkHackExpGain = function() { PlayerObject.prototype.getWorkHackExpGain = function() {
var company = Companies[this.companyName]; const company = Companies[this.companyName];
return this.companyPosition.hackingExpGain * company.expMultiplier * const companyPosition = CompanyPositions[this.companyPosition];
this.hacking_exp_mult * BitNodeMultipliers.CompanyWorkExpGain; 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 //Str exp gained per game cycle
PlayerObject.prototype.getWorkStrExpGain = function() { PlayerObject.prototype.getWorkStrExpGain = function() {
var company = Companies[this.companyName]; const company = Companies[this.companyName];
return this.companyPosition.strengthExpGain * company.expMultiplier * const companyPosition = CompanyPositions[this.companyPosition];
this.strength_exp_mult * BitNodeMultipliers.CompanyWorkExpGain; 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 companyPosition.strengthExpGain * company.expMultiplier * this.strength_exp_mult * BitNodeMultipliers.CompanyWorkExpGain;
} }
//Def exp gained per game cycle //Def exp gained per game cycle
PlayerObject.prototype.getWorkDefExpGain = function() { PlayerObject.prototype.getWorkDefExpGain = function() {
var company = Companies[this.companyName]; const company = Companies[this.companyName];
return this.companyPosition.defenseExpGain * company.expMultiplier * const companyPosition = CompanyPositions[this.companyPosition];
this.defense_exp_mult * BitNodeMultipliers.CompanyWorkExpGain; 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 companyPosition.defenseExpGain * company.expMultiplier * this.defense_exp_mult * BitNodeMultipliers.CompanyWorkExpGain;
} }
//Dex exp gained per game cycle //Dex exp gained per game cycle
PlayerObject.prototype.getWorkDexExpGain = function() { PlayerObject.prototype.getWorkDexExpGain = function() {
var company = Companies[this.companyName]; const company = Companies[this.companyName];
return this.companyPosition.dexterityExpGain * company.expMultiplier * const companyPosition = CompanyPositions[this.companyPosition];
this.dexterity_exp_mult * BitNodeMultipliers.CompanyWorkExpGain; 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 companyPosition.dexterityExpGain * company.expMultiplier * this.dexterity_exp_mult * BitNodeMultipliers.CompanyWorkExpGain;
} }
//Agi exp gained per game cycle //Agi exp gained per game cycle
PlayerObject.prototype.getWorkAgiExpGain = function() { PlayerObject.prototype.getWorkAgiExpGain = function() {
var company = Companies[this.companyName]; const company = Companies[this.companyName];
return this.companyPosition.agilityExpGain * company.expMultiplier * const companyPosition = CompanyPositions[this.companyPosition];
this.agility_exp_mult * BitNodeMultipliers.CompanyWorkExpGain; 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 companyPosition.agilityExpGain * company.expMultiplier * this.agility_exp_mult * BitNodeMultipliers.CompanyWorkExpGain;
} }
//Charisma exp gained per game cycle //Charisma exp gained per game cycle
PlayerObject.prototype.getWorkChaExpGain = function() { PlayerObject.prototype.getWorkChaExpGain = function() {
var company = Companies[this.companyName]; const company = Companies[this.companyName];
return this.companyPosition.charismaExpGain * company.expMultiplier * const companyPosition = CompanyPositions[this.companyPosition];
this.charisma_exp_mult * BitNodeMultipliers.CompanyWorkExpGain; 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 companyPosition.charismaExpGain * company.expMultiplier * this.charisma_exp_mult * BitNodeMultipliers.CompanyWorkExpGain;
} }
//Reputation gained per game cycle //Reputation gained per game cycle
PlayerObject.prototype.getWorkRepGain = function() { PlayerObject.prototype.getWorkRepGain = function() {
var company = Companies[this.companyName]; const company = Companies[this.companyName];
var jobPerformance = this.companyPosition.calculateJobPerformance(this.hacking_skill, this.strength, 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 = companyPosition.calculateJobPerformance(this.hacking_skill, this.strength,
this.defense, this.dexterity, this.defense, this.dexterity,
this.agility, this.charisma); this.agility, this.charisma);
@ -1611,20 +1670,25 @@ PlayerObject.prototype.hospitalize = function() {
//The 'sing' argument designates whether or not this is being called from //The 'sing' argument designates whether or not this is being called from
//the applyToCompany() Netscript Singularity function //the applyToCompany() Netscript Singularity function
PlayerObject.prototype.applyForJob = function(entryPosType, sing=false) { PlayerObject.prototype.applyForJob = function(entryPosType, sing=false) {
var currCompany = ""; // Get current company and job
if (this.companyName != "") { let currCompany = null;
if (this.companyName !== "") {
currCompany = Companies[this.companyName]; currCompany = Companies[this.companyName];
} }
var currPositionName = ""; const currPositionName = this.companyPosition;
if (this.companyPosition != "") {
currPositionName = this.companyPosition.positionName; // Get company that's being applied to
} const company = Companies[this.location]; //Company being applied to
var company = Companies[this.location]; //Company being applied to if (!(company instanceof Company)) {
if (sing && !(company instanceof Company)) { if (sing) {
return "ERROR: Invalid company name: " + this.location + ". applyToCompany() failed"; 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)) { if (!this.isQualified(company, pos)) {
var reqText = getJobRequirementText(company, pos); var reqText = getJobRequirementText(company, pos);
@ -1634,8 +1698,7 @@ PlayerObject.prototype.applyForJob = function(entryPosType, sing=false) {
} }
while (true) { while (true) {
if (Engine.Debug) {console.log("Determining qualification for next Company Position");} let newPos = getNextCompanyPosition(pos);
var newPos = getNextCompanyPosition(pos);
if (newPos == null) {break;} if (newPos == null) {break;}
//Check if this company has this position //Check if this company has this position
@ -1651,9 +1714,8 @@ PlayerObject.prototype.applyForJob = function(entryPosType, sing=false) {
} }
//Check if the determined job is the same as the player's current job //Check if the determined job is the same as the player's current job
if (currCompany != "") { if (currCompany != null) {
if (currCompany.companyName == company.companyName && if (currCompany.name == company.name && pos.name == currPositionName) {
pos.positionName == currPositionName) {
var nextPos = getNextCompanyPosition(pos); var nextPos = getNextCompanyPosition(pos);
if (nextPos == null) { if (nextPos == null) {
if (sing) {return false;} if (sing) {return false;}
@ -1672,31 +1734,30 @@ PlayerObject.prototype.applyForJob = function(entryPosType, sing=false) {
//Lose reputation from a Company if you are leaving it for another job //Lose reputation from a Company if you are leaving it for another job
var leaveCompany = false; let leaveCompany = false;
var oldCompanyName = ""; let oldCompanyName = "";
if (currCompany != "") { if (currCompany != null) {
if (currCompany.companyName != company.companyName) { if (currCompany.name != company.name) {
leaveCompany = true; leaveCompany = true;
oldCompanyName = currCompany.companyName; oldCompanyName = currCompany.name;
company.playerReputation -= 1000; currCompany.playerReputation -= 1000;
if (company.playerReputation < 0) {company.playerReputation = 0;} if (currCompany.playerReputation < 0) { currCompany.playerReputation = 0; }
} }
} }
this.companyName = company.companyName; this.companyName = company.name;
this.companyPosition = pos; this.companyPosition = pos.name;
document.getElementById("world-menu-header").click(); document.getElementById("world-menu-header").click();
document.getElementById("world-menu-header").click(); document.getElementById("world-menu-header").click();
if (leaveCompany) { if (leaveCompany) {
if (sing) { return true; } if (sing) { return true; }
dialogBoxCreate("Congratulations! You were offered a new job at " + this.companyName + " as a " + dialogBoxCreate([`Congratulations! You were offered a new job at ${this.companyName} as a ${pos.name}!`,
pos.positionName + "!<br>" + `You lost 1000 reputation at your old company ${oldCompanyName} because you left.`].join("<br>"));
"You lost 1000 reputation at your old company " + oldCompanyName + " because you left.");
} else { } else {
if (sing) { return true; } if (sing) { return true; }
dialogBoxCreate("Congratulations! You were offered a new job at " + this.companyName + " as a " + pos.positionName + "!"); dialogBoxCreate("Congratulations! You were offered a new job at " + this.companyName + " as a " + pos.name + "!");
} }
Engine.loadLocationContent(); Engine.loadLocationContent();
@ -1705,51 +1766,51 @@ PlayerObject.prototype.applyForJob = function(entryPosType, sing=false) {
//Returns your next position at a company given the field (software, business, etc.) //Returns your next position at a company given the field (software, business, etc.)
PlayerObject.prototype.getNextCompanyPosition = function(company, entryPosType) { PlayerObject.prototype.getNextCompanyPosition = function(company, entryPosType) {
var currCompany = null; var currCompany = null;
if (this.companyName != "") { if (this.companyName !== "") {
currCompany = Companies[this.companyName]; currCompany = Companies[this.companyName];
} }
//Not employed at this company, so return the entry position //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; return entryPosType;
} }
//If the entry pos type and the player's current position have the same type, //If the entry pos type and the player's current position have the same type,
//return the player's "nextCompanyPosition". Otherwise return the entryposType //return the player's "nextCompanyPosition". Otherwise return the entryposType
//Employed at this company, so just return the next position if it exists. //Employed at this company, so just return the next position if it exists.
if ((this.companyPosition.isSoftwareJob() && entryPosType.isSoftwareJob()) || const currentPosition = CompanyPositions[this.companyPosition];
(this.companyPosition.isITJob() && entryPosType.isITJob()) || if ((currentPosition.isSoftwareJob() && entryPosType.isSoftwareJob()) ||
(this.companyPosition.isBusinessJob() && entryPosType.isBusinessJob()) || (currentPosition.isITJob() && entryPosType.isITJob()) ||
(this.companyPosition.isSecurityEngineerJob() && entryPosType.isSecurityEngineerJob()) || (currentPosition.isBusinessJob() && entryPosType.isBusinessJob()) ||
(this.companyPosition.isNetworkEngineerJob() && entryPosType.isNetworkEngineerJob()) || (currentPosition.isSecurityEngineerJob() && entryPosType.isSecurityEngineerJob()) ||
(this.companyPosition.isSecurityJob() && entryPosType.isSecurityJob()) || (currentPosition.isNetworkEngineerJob() && entryPosType.isNetworkEngineerJob()) ||
(this.companyPosition.isAgentJob() && entryPosType.isAgentJob()) || (currentPosition.isSecurityJob() && entryPosType.isSecurityJob()) ||
(this.companyPosition.isSoftwareConsultantJob() && entryPosType.isSoftwareConsultantJob()) || (currentPosition.isAgentJob() && entryPosType.isAgentJob()) ||
(this.companyPosition.isBusinessConsultantJob() && entryPosType.isBusinessConsultantJob()) || (currentPosition.isSoftwareConsultantJob() && entryPosType.isSoftwareConsultantJob()) ||
(this.companyPosition.isPartTimeJob() && entryPosType.isPartTimeJob())) { (currentPosition.isBusinessConsultantJob() && entryPosType.isBusinessConsultantJob()) ||
return getNextCompanyPosition(this.companyPosition); (currentPosition.isPartTimeJob() && entryPosType.isPartTimeJob())) {
return getNextCompanyPosition(currentPosition);
} }
return entryPosType; return entryPosType;
} }
PlayerObject.prototype.applyForSoftwareJob = function(sing=false) { PlayerObject.prototype.applyForSoftwareJob = function(sing=false) {
return this.applyForJob(CompanyPositions.SoftwareIntern, sing); return this.applyForJob(CompanyPositions[posNames.SoftwareCompanyPositions[0]], sing);
} }
PlayerObject.prototype.applyForSoftwareConsultantJob = function(sing=false) { PlayerObject.prototype.applyForSoftwareConsultantJob = function(sing=false) {
return this.applyForJob(CompanyPositions.SoftwareConsultant, sing); return this.applyForJob(CompanyPositions[posNames.SoftwareConsultantCompanyPositions[0]], sing);
} }
PlayerObject.prototype.applyForItJob = function(sing=false) { PlayerObject.prototype.applyForItJob = function(sing=false) {
return this.applyForJob(CompanyPositions.ITIntern, sing); return this.applyForJob(CompanyPositions[posNames.ITCompanyPositions[0]], sing);
} }
PlayerObject.prototype.applyForSecurityEngineerJob = function(sing=false) { PlayerObject.prototype.applyForSecurityEngineerJob = function(sing=false) {
var company = Companies[this.location]; //Company being applied to var company = Companies[this.location]; //Company being applied to
if (this.isQualified(company, CompanyPositions.SecurityEngineer)) { if (this.isQualified(company, CompanyPositions[posNames.SecurityEngineerCompanyPositions[0]])) {
return this.applyForJob(CompanyPositions.SecurityEngineer, sing); return this.applyForJob(CompanyPositions[posNames.SecurityEngineerCompanyPositions[0]], sing);
} else { } else {
if (sing) {return false;} if (sing) {return false;}
dialogBoxCreate("Unforunately, you do not qualify for this position"); dialogBoxCreate("Unforunately, you do not qualify for this position");
@ -1758,8 +1819,8 @@ PlayerObject.prototype.applyForSecurityEngineerJob = function(sing=false) {
PlayerObject.prototype.applyForNetworkEngineerJob = function(sing=false) { PlayerObject.prototype.applyForNetworkEngineerJob = function(sing=false) {
var company = Companies[this.location]; //Company being applied to var company = Companies[this.location]; //Company being applied to
if (this.isQualified(company, CompanyPositions.NetworkEngineer)) { if (this.isQualified(company, CompanyPositions[posNames.NetworkEngineerCompanyPositions[0]])) {
return this.applyForJob(CompanyPositions.NetworkEngineer, sing); return this.applyForJob(CompanyPositions[posNames.NetworkEngineerCompanyPositions[0]], sing);
} else { } else {
if (sing) {return false;} if (sing) {return false;}
dialogBoxCreate("Unforunately, you do not qualify for this position"); dialogBoxCreate("Unforunately, you do not qualify for this position");
@ -1767,22 +1828,23 @@ PlayerObject.prototype.applyForNetworkEngineerJob = function(sing=false) {
} }
PlayerObject.prototype.applyForBusinessJob = function(sing=false) { PlayerObject.prototype.applyForBusinessJob = function(sing=false) {
return this.applyForJob(CompanyPositions.BusinessIntern, sing); return this.applyForJob(CompanyPositions[posNames.BusinessCompanyPositions[0]], sing);
} }
PlayerObject.prototype.applyForBusinessConsultantJob = function(sing=false) { PlayerObject.prototype.applyForBusinessConsultantJob = function(sing=false) {
return this.applyForJob(CompanyPositions.BusinessConsultant, sing); return this.applyForJob(CompanyPositions[posNames.BusinessConsultantCompanyPositions[0]], sing);
} }
PlayerObject.prototype.applyForSecurityJob = function(sing=false) { PlayerObject.prototype.applyForSecurityJob = function(sing=false) {
//TODO If case for POlice departments // TODO Police Jobs
return this.applyForJob(CompanyPositions.SecurityGuard, sing); // Indexing starts at 2 because 0 is for police officer
return this.applyForJob(CompanyPositions[posNames.SecurityCompanyPositions[2]], sing);
} }
PlayerObject.prototype.applyForAgentJob = function(sing=false) { PlayerObject.prototype.applyForAgentJob = function(sing=false) {
var company = Companies[this.location]; //Company being applied to var company = Companies[this.location]; //Company being applied to
if (this.isQualified(company, CompanyPositions.FieldAgent)) { if (this.isQualified(company, CompanyPositions[posNames.AgentCompanyPositions[0]])) {
return this.applyForJob(CompanyPositions.FieldAgent, sing); return this.applyForJob(CompanyPositions[posNames.AgentCompanyPositions[0]], sing);
} else { } else {
if (sing) {return false;} if (sing) {return false;}
dialogBoxCreate("Unforunately, you do not qualify for this position"); dialogBoxCreate("Unforunately, you do not qualify for this position");
@ -1791,9 +1853,9 @@ PlayerObject.prototype.applyForAgentJob = function(sing=false) {
PlayerObject.prototype.applyForEmployeeJob = function(sing=false) { PlayerObject.prototype.applyForEmployeeJob = function(sing=false) {
var company = Companies[this.location]; //Company being applied to var company = Companies[this.location]; //Company being applied to
if (this.isQualified(company, CompanyPositions.Employee)) { if (this.isQualified(company, CompanyPositions[posNames.MiscCompanyPositions[1]])) {
this.companyName = company.companyName; this.companyName = company.name;
this.companyPosition = CompanyPositions.Employee; this.companyPosition = posNames.MiscCompanyPositions[1];
document.getElementById("world-menu-header").click(); document.getElementById("world-menu-header").click();
document.getElementById("world-menu-header").click(); document.getElementById("world-menu-header").click();
if (sing) {return true;} if (sing) {return true;}
@ -1807,9 +1869,9 @@ PlayerObject.prototype.applyForEmployeeJob = function(sing=false) {
PlayerObject.prototype.applyForPartTimeEmployeeJob = function(sing=false) { PlayerObject.prototype.applyForPartTimeEmployeeJob = function(sing=false) {
var company = Companies[this.location]; //Company being applied to var company = Companies[this.location]; //Company being applied to
if (this.isQualified(company, CompanyPositions.PartTimeEmployee)) { if (this.isQualified(company, CompanyPositions[posNames.PartTimeCompanyPositions[1]])) {
this.companyName = company.companyName; this.companyName = company.name;
this.companyPosition = CompanyPositions.PartTimeEmployee; this.companyPosition = posNames.PartTimeCompanyPositions[1];
document.getElementById("world-menu-header").click(); document.getElementById("world-menu-header").click();
document.getElementById("world-menu-header").click(); document.getElementById("world-menu-header").click();
if (sing) {return true;} if (sing) {return true;}
@ -1823,9 +1885,9 @@ PlayerObject.prototype.applyForPartTimeEmployeeJob = function(sing=false) {
PlayerObject.prototype.applyForWaiterJob = function(sing=false) { PlayerObject.prototype.applyForWaiterJob = function(sing=false) {
var company = Companies[this.location]; //Company being applied to var company = Companies[this.location]; //Company being applied to
if (this.isQualified(company, CompanyPositions.Waiter)) { if (this.isQualified(company, CompanyPositions[posNames.MiscCompanyPositions[0]])) {
this.companyName = company.companyName; this.companyName = company.name;
this.companyPosition = CompanyPositions.Waiter; this.companyPosition = posNames.MiscCompanyPositions[0];
document.getElementById("world-menu-header").click(); document.getElementById("world-menu-header").click();
document.getElementById("world-menu-header").click(); document.getElementById("world-menu-header").click();
if (sing) {return true;} if (sing) {return true;}
@ -1839,9 +1901,9 @@ PlayerObject.prototype.applyForWaiterJob = function(sing=false) {
PlayerObject.prototype.applyForPartTimeWaiterJob = function(sing=false) { PlayerObject.prototype.applyForPartTimeWaiterJob = function(sing=false) {
var company = Companies[this.location]; //Company being applied to var company = Companies[this.location]; //Company being applied to
if (this.isQualified(company, CompanyPositions.PartTimeWaiter)) { if (this.isQualified(company, CompanyPositions[posNames.PartTimeCompanyPositions[0]])) {
this.companyName = company.companyName; this.companyName = company.name;
this.companyPosition = CompanyPositions.PartTimeWaiter; this.companyPosition = posNames.PartTimeCompanyPositions[0];
document.getElementById("world-menu-header").click(); document.getElementById("world-menu-header").click();
document.getElementById("world-menu-header").click(); document.getElementById("world-menu-header").click();
if (sing) {return true;} if (sing) {return true;}
@ -2156,10 +2218,12 @@ PlayerObject.prototype.checkForFactionInvitations = function() {
//Silhouette //Silhouette
var silhouetteFac = Factions["Silhouette"]; var silhouetteFac = Factions["Silhouette"];
const companyPosition = CompanyPositions[this.companyPosition];
if (!silhouetteFac.isBanned && !silhouetteFac.isMember && !silhouetteFac.alreadyInvited && if (!silhouetteFac.isBanned && !silhouetteFac.isMember && !silhouetteFac.alreadyInvited &&
(this.companyPosition.positionName == CompanyPositions.CTO.positionName || companyPosition != null &&
this.companyPosition.positionName == CompanyPositions.CFO.positionName || (companyPosition.name == "Chief Technology Officer" ||
this.companyPosition.positionName == CompanyPositions.CEO.positionName) && companyPosition.name == "Chief Financial Officer" ||
companyPosition.name == "Chief Executive Officer") &&
this.money.gte(15000000) && this.karma <= -22) { this.money.gte(15000000) && this.karma <= -22) {
invitedFactions.push(silhouetteFac); invitedFactions.push(silhouetteFac);
} }

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

@ -1,7 +1,7 @@
import {loadAliases, loadGlobalAliases, import {loadAliases, loadGlobalAliases,
Aliases, GlobalAliases} from "./Alias"; Aliases, GlobalAliases} from "./Alias";
import {loadCompanies, Companies, import {Companies, loadCompanies} from "./Company/Companies";
CompanyPositions} from "./Company"; import {CompanyPosition} from "./Company/CompanyPosition";
import {CONSTANTS} from "./Constants"; import {CONSTANTS} from "./Constants";
import {Engine} from "./engine"; import {Engine} from "./engine";
import {loadFactions, Factions, import {loadFactions, Factions,
@ -110,6 +110,41 @@ BitburnerSaveObject.prototype.saveGame = function(db) {
createStatusText("Game saved!"); createStatusText("Game saved!");
} }
// Makes necessary changes to the loaded/imported data to ensure
// the game stills works with new versions
function evaluateVersionCompatibility(ver) {
// This version refactored the Company/job-related code
if (ver <= "0.41.2") {
// Player's company position is now a string
if (Player.companyPosition != null && typeof Player.companyPosition !== "string") {
console.log("Changed Player.companyPosition value to be compatible with v0.41.2");
Player.companyPosition = Player.companyPosition.data.positionName;
if (Player.companyPosition == null) {
Player.companyPosition = "";
}
}
// 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 (company.companyPositions instanceof Array) {
console.log("Changed company companyPositions property to be compatible with v0.41.2");
const pos = {};
for (let i = 0; i < company.companyPositions.length; ++i) {
pos[company.companyPositions[i]] = true;
}
company.companyPositions = pos;
}
}
}
}
function loadGame(saveString) { function loadGame(saveString) {
if (saveString === "" || saveString == null || saveString === undefined) { if (saveString === "" || saveString == null || saveString === undefined) {
if (!window.localStorage.getItem("bitburnerSave")) { if (!window.localStorage.getItem("bitburnerSave")) {
@ -187,28 +222,8 @@ function loadGame(saveString) {
if (saveObj.hasOwnProperty("VersionSave")) { if (saveObj.hasOwnProperty("VersionSave")) {
try { try {
var ver = JSON.parse(saveObj.VersionSave, Reviver); var ver = JSON.parse(saveObj.VersionSave, Reviver);
if (Player.bitNodeN == null || Player.bitNodeN === 0) { evaluateVersionCompatibility(ver);
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.firstTimeTraveled = true;
Player.firstProgramAvailable = true;
} else {
if (Player.factions.length > 0 || Player.factionInvitations.length > 0) {
Player.firstFacInvRecvd = true;
}
if (Player.hacking_skill >= 25) {
Player.firstScriptAvailable = true;
}
}
}
if (window.location.href.toLowerCase().includes("bitburner-beta")) { if (window.location.href.toLowerCase().includes("bitburner-beta")) {
//Beta branch, always show changes //Beta branch, always show changes
createBetaUpdateText(); createBetaUpdateText();
@ -306,23 +321,11 @@ function loadImportedGame(saveObj, saveString) {
if (tempSaveObj.hasOwnProperty("VersionSave")) { if (tempSaveObj.hasOwnProperty("VersionSave")) {
try { try {
var ver = JSON.parse(tempSaveObj.VersionSave, Reviver); var ver = JSON.parse(tempSaveObj.VersionSave, Reviver);
if (ver.startsWith("0.27.") || ver.startsWith("0.28.")) { evaluateVersionCompatibility(ver);
if (tempPlayer.bitNodeN == null || tempPlayer.bitNodeN == 0) {
tempPlayer.bitNodeN = 1;
}
if (tempPlayer.sourceFiles == null) {
tempPlayer.sourceFiles = [];
}
}
if (ver != CONSTANTS.Version) {
//createNewUpdateText();
}
} catch(e) { } catch(e) {
console.log("Parsing Version save failed: " + e); console.error("Parsing Version save failed: " + e);
//createNewUpdateText();
} }
} else { } else {
//createNewUpdateText();
} }
if (tempPlayer.bitNodeN == 2 && tempPlayer.inGang() && tempSaveObj.hasOwnProperty("AllGangsSave")) { if (tempPlayer.bitNodeN == 2 && tempPlayer.inGang() && tempSaveObj.hasOwnProperty("AllGangsSave")) {
try { try {
@ -401,29 +404,8 @@ function loadImportedGame(saveObj, saveString) {
if (saveObj.hasOwnProperty("VersionSave")) { if (saveObj.hasOwnProperty("VersionSave")) {
try { try {
var ver = JSON.parse(saveObj.VersionSave, Reviver); var ver = JSON.parse(saveObj.VersionSave, Reviver);
if (Player.bitNodeN == null || Player.bitNodeN == 0) { evaluateVersionCompatibility(ver);
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.firstTimeTraveled = true;
Player.firstProgramAvailable = true;
} else {
if (Player.factions.length > 0 || Player.factionInvitations.length > 0) {
Player.firstFacInvRecvd = true;
}
if (Player.hacking_skill >= 25) {
Player.firstScriptAvailable = true;
}
}
}
if (ver != CONSTANTS.Version) { if (ver != CONSTANTS.Version) {
createNewUpdateText(); createNewUpdateText();
} }
@ -459,7 +441,6 @@ function loadImportedGame(saveObj, saveString) {
console.log("Importing game"); console.log("Importing game");
Engine.setDisplayElements(); //Sets variables for important DOM elements Engine.setDisplayElements(); //Sets variables for important DOM elements
Engine.init(); //Initialize buttons, work, etc. Engine.init(); //Initialize buttons, work, etc.
CompanyPositions.init();
//Calculate the number of cycles have elapsed while offline //Calculate the number of cycles have elapsed while offline
Engine._lastUpdate = new Date().getTime(); Engine._lastUpdate = new Date().getTime();

@ -1090,6 +1090,24 @@ let Terminal = {
} }
} }
post("Error: " + fn + " does not exist"); post("Error: " + fn + " does not exist");
break;
case "expr":
if (commandArray.length <= 1) {
post("Incorrect usage of expr command. Usage: expr [math expression]");
return;
}
const expr = commandArray.slice(1).join("");
// Sanitize the math expression
const sanitizedExpr = expr.replace(/s+/g, '').replace(/[^-()\d/*+.]/g, '');
let result;
try {
result = eval(sanitizedExpr);
} catch(e) {
post(`Could not evaluate expression: ${sanitizedExpr}`);
return;
}
post(result);
break; break;
case "free": case "free":
Terminal.executeFreeCommand(commandArray); Terminal.executeFreeCommand(commandArray);

@ -25,7 +25,8 @@ import {Bladeburner} from "./Bladeburner";
import {CharacterOverview} from "./CharacterOverview"; import {CharacterOverview} from "./CharacterOverview";
import {cinematicTextFlag} from "./CinematicText"; import {cinematicTextFlag} from "./CinematicText";
import {generateRandomContract} from "./CodingContractGenerator"; import {generateRandomContract} from "./CodingContractGenerator";
import {CompanyPositions, initCompanies} from "./Company"; import {CompanyPositions} from "./Company/CompanyPositions";
import {initCompanies} from "./Company/Companies";
import {Corporation} from "./CompanyManagement"; import {Corporation} from "./CompanyManagement";
import {CONSTANTS} from "./Constants"; import {CONSTANTS} from "./Constants";
import {displayCreateProgramContent, import {displayCreateProgramContent,
@ -338,7 +339,13 @@ const Engine = {
loadLocationContent: function() { loadLocationContent: function() {
Engine.hideAllContent(); Engine.hideAllContent();
Engine.Display.locationContent.style.display = "block"; Engine.Display.locationContent.style.display = "block";
try {
displayLocationContent(); displayLocationContent();
} catch(e) {
exceptionAlert(e);
console.error(e);
}
routing.navigateTo(Page.Location); routing.navigateTo(Page.Location);
}, },
@ -539,8 +546,8 @@ const Engine = {
removeChildrenFromElement(Engine.Display.characterInfo); removeChildrenFromElement(Engine.Display.characterInfo);
var companyPosition = ""; var companyPosition = "";
if (Player.companyPosition != "") { if (Player.companyPosition !== "") {
companyPosition = Player.companyPosition.positionName; companyPosition = Player.companyPosition;
} }
var intText = ""; var intText = "";
@ -1204,7 +1211,6 @@ const Engine = {
initSourceFiles(); initSourceFiles();
Engine.setDisplayElements(); //Sets variables for important DOM elements Engine.setDisplayElements(); //Sets variables for important DOM elements
Engine.init(); //Initialize buttons, work, etc. Engine.init(); //Initialize buttons, work, etc.
CompanyPositions.init();
initAugmentations(); //Also calls Player.reapplyAllAugmentations() initAugmentations(); //Also calls Player.reapplyAllAugmentations()
Player.reapplyAllSourceFiles(); Player.reapplyAllSourceFiles();
initStockSymbols(); initStockSymbols();
@ -1312,7 +1318,6 @@ const Engine = {
initForeignServers(); initForeignServers();
initCompanies(); initCompanies();
initFactions(); initFactions();
CompanyPositions.init();
initAugmentations(); initAugmentations();
initMessages(); initMessages();
initStockSymbols(); initStockSymbols();

@ -1,5 +1,6 @@
{ {
"compilerOptions": { "compilerOptions": {
"baseUrl" : ".",
"lib" : ["es2016", "dom"], "lib" : ["es2016", "dom"],
"module": "commonjs", "module": "commonjs",
"target": "es6", "target": "es6",