mirror of
https://github.com/bitburner-official/bitburner-src.git
synced 2024-12-19 20:55:44 +01:00
commit
c1c0297c92
@ -39,6 +39,19 @@
|
||||
padding: 16px;
|
||||
}
|
||||
|
||||
.mainmenu.compact > li a,
|
||||
.mainmenu.compact > li button {
|
||||
display: block;
|
||||
color: #e6e6e6;
|
||||
background-color: #555;
|
||||
|
||||
text-decoration: none;
|
||||
cursor: pointer;
|
||||
width: 100%;
|
||||
text-align: left;
|
||||
padding: 4px;
|
||||
}
|
||||
|
||||
/* Hovering makes them lighter */
|
||||
.mainmenu > li a:hover,
|
||||
.mainmenu > li a:hover:not(.active),
|
||||
@ -73,7 +86,8 @@
|
||||
}
|
||||
|
||||
/* Accordion Outline */
|
||||
.mainmenu-accordion-header {
|
||||
.mainmenu-accordion-header,
|
||||
.mainmenu-accordion-header-compact {
|
||||
outline: 2px solid #fff !important;
|
||||
}
|
||||
|
||||
@ -83,7 +97,8 @@
|
||||
}
|
||||
|
||||
/* Plus and minus signs */
|
||||
.mainmenu-accordion-header:after {
|
||||
.mainmenu-accordion-header:after,
|
||||
.mainmenu-accordion-header-compact:after {
|
||||
content: '\02795';
|
||||
float: right;
|
||||
font-size: $defaultFontSize * 0.8125;
|
||||
@ -103,8 +118,9 @@
|
||||
}
|
||||
|
||||
.mainmenu-accordion-header.opened,
|
||||
.mainmenu-accordion-header-classic.opened {
|
||||
background-color: #222;
|
||||
.mainmenu-accordion-header-classic.opened,
|
||||
.mainmenu-accordion-header-compact.opened {
|
||||
background-color: #222 !important;
|
||||
|
||||
&:after {
|
||||
content: "\2796";
|
||||
|
2
dist/engine.bundle.js
vendored
2
dist/engine.bundle.js
vendored
File diff suppressed because one or more lines are too long
25
dist/engine.css
vendored
25
dist/engine.css
vendored
@ -521,6 +521,17 @@ button {
|
||||
.mainmenu.classic > li button {
|
||||
padding: 16px; }
|
||||
|
||||
.mainmenu.compact > li a,
|
||||
.mainmenu.compact > li button {
|
||||
display: block;
|
||||
color: #e6e6e6;
|
||||
background-color: #555;
|
||||
text-decoration: none;
|
||||
cursor: pointer;
|
||||
width: 100%;
|
||||
text-align: left;
|
||||
padding: 4px; }
|
||||
|
||||
/* Hovering makes them lighter */
|
||||
.mainmenu > li a:hover,
|
||||
.mainmenu > li a:hover:not(.active),
|
||||
@ -550,7 +561,8 @@ button {
|
||||
position: relative; }
|
||||
|
||||
/* Accordion Outline */
|
||||
.mainmenu-accordion-header {
|
||||
.mainmenu-accordion-header,
|
||||
.mainmenu-accordion-header-compact {
|
||||
outline: 2px solid #fff !important; }
|
||||
|
||||
.mainmenu-accordion-header-classic {
|
||||
@ -558,7 +570,8 @@ button {
|
||||
padding: 16px !important; }
|
||||
|
||||
/* Plus and minus signs */
|
||||
.mainmenu-accordion-header:after {
|
||||
.mainmenu-accordion-header:after,
|
||||
.mainmenu-accordion-header-compact:after {
|
||||
content: '\2795';
|
||||
float: right;
|
||||
font-size: 13px;
|
||||
@ -576,10 +589,12 @@ button {
|
||||
margin-left: 5px; }
|
||||
|
||||
.mainmenu-accordion-header.opened,
|
||||
.mainmenu-accordion-header-classic.opened {
|
||||
background-color: #222; }
|
||||
.mainmenu-accordion-header-classic.opened,
|
||||
.mainmenu-accordion-header-compact.opened {
|
||||
background-color: #222 !important; }
|
||||
.mainmenu-accordion-header.opened:after,
|
||||
.mainmenu-accordion-header-classic.opened:after {
|
||||
.mainmenu-accordion-header-classic.opened:after,
|
||||
.mainmenu-accordion-header-compact.opened:after {
|
||||
content: "\2796"; }
|
||||
|
||||
/* Slide down transition */
|
||||
|
116
dist/vendor.bundle.js
vendored
116
dist/vendor.bundle.js
vendored
File diff suppressed because one or more lines are too long
@ -3,6 +3,33 @@
|
||||
Changelog
|
||||
=========
|
||||
|
||||
v0.41.2 - 11/23/2018
|
||||
--------------------
|
||||
* IMPORTANT - Netscript Changes:
|
||||
* rm() now takes an optional parameter that lets you specify on which server to delete the file
|
||||
* Added growthAnalyze() Netscript function
|
||||
|
||||
* Gang Changes:
|
||||
* UI now displays your chance to win a clash with other gangs
|
||||
* Added getChanceToWinClash() function to the Gang API
|
||||
* Added getEquipmentType() function to the Gang API
|
||||
* Added several new hacking-based equipment and Augmentations
|
||||
* Rebalanced several equipment/upgrades to give less defense
|
||||
* Wanted level gain rate is now be slightly higher for all tasks
|
||||
* Rebalanced parameters for "hacking" tasks
|
||||
|
||||
* Added new Main Menu configuration in .fconf: "compact"
|
||||
* Added the terminal command 'expr', which can be used to evaluate simple mathematical expressions
|
||||
* Bug Fix: Can no longer purchase duplicate equipment/Augmentations through gang.purchaseEquipment()
|
||||
* Bug Fix: scp() should no longer throw errors when used with 2-arguments and an array of files
|
||||
* Bug Fix: Coding Contracts no longer give money in BitNode-8
|
||||
* Bug Fix: In Bladeburner, you can no longer start a BlackOp through the Netscript API if it has already been completed
|
||||
* Bug Fix: In Bladeburner, fixed a bug which caused the configured 'automate' actions to occasionally be switched to other actions
|
||||
* Bug Fix: 'Return to World' button at locations no longer accumulates event listeners
|
||||
* Bug Fix: Working & taking classes now continuously add/subtract money during the action, instead of doing it at completion
|
||||
* Bug Fix: Top-right overview panel now displays negative money using '-' instead of '()'
|
||||
* Bug Fix: Stock Market UI should no longer show 'NaN' profit immediately after buying a stock
|
||||
|
||||
v0.41.1 - 11/5/2018
|
||||
-------------------
|
||||
* IMPORTANT - Netscript Changes:
|
||||
|
@ -56,7 +56,7 @@ weaken
|
||||
|
||||
.. js:function:: weaken(hostname/ip)
|
||||
|
||||
:param string hostname.ip: IP or hostname of the target server to weaken
|
||||
:param string hostname/ip: IP or hostname of the target server to weaken
|
||||
:returns: The amount by which the target server's security level was decreased. This is equivalent to 0.05 multiplied
|
||||
by the number of script threads
|
||||
:RAM cost: 0.15 GB
|
||||
@ -72,6 +72,31 @@ weaken
|
||||
|
||||
weaken("foodnstuff");
|
||||
|
||||
growthAnalyze
|
||||
^^^^^^^^^^^^^
|
||||
|
||||
.. js:function:: growthAnalyze(hostname/ip, growthAmount)
|
||||
|
||||
:param string hostname/ip: IP or hostname of server to analyze
|
||||
:param number growthAmount: Multiplicative factor by which the server is grown. Decimal form.
|
||||
:returns: The amount of grow() calls needed to grow the specified server by the specified amount
|
||||
:RAM cost: 1 GB
|
||||
|
||||
This function returns the number of "growths" needed in order to increase the amount
|
||||
of money available on the specified server by the specified amount.
|
||||
|
||||
The specified amount is multiplicative and is in decimal form, not percentage.
|
||||
|
||||
For example, if you want to determine how many `grow()` calls you need
|
||||
to double the amount of money on `foodnstuff`, you would use::
|
||||
|
||||
growthAnalyze("foodnstuff", 2);
|
||||
|
||||
If this returns 100, then this means you need to call `grow()` 100 times
|
||||
in order to double the money (or once with 100 threads).
|
||||
|
||||
**Warning**: The value returned by this function isn't necessarily a whole number.
|
||||
|
||||
sleep
|
||||
^^^^^
|
||||
|
||||
@ -951,9 +976,10 @@ getPortHandle
|
||||
rm
|
||||
^^
|
||||
|
||||
.. js:function:: rm(fn)
|
||||
.. js:function:: rm(fn[, hostname/ip=current server])
|
||||
|
||||
:param string fn: Filename of file to remove. Must include the extension
|
||||
:param string hostname/ip: Hostname or IP Address of the server on which to delete the file. Optional. Defaults to current server
|
||||
:returns: True if it successfully deletes the file, and false otherwise
|
||||
:RAM cost: 1 GB
|
||||
|
||||
@ -1011,7 +1037,7 @@ getScriptRam
|
||||
.. js:function:: getScriptRam(scriptname[, hostname/ip])
|
||||
|
||||
:param string scriptname: Filename of script. This is case-sensitive.
|
||||
:param string hostname/ip: Hostname or IP of target server the script is located on. This is optional, If it is not specified then the function will se the current server as the target server.
|
||||
:param string hostname/ip: Hostname or IP of target server the script is located on. This is optional, If it is not specified then the function will set the current server as the target server.
|
||||
:RAM cost: 0.1 GB
|
||||
|
||||
Returns the amount of RAM required to run the specified script on the target server. Returns
|
||||
|
@ -187,6 +187,23 @@ getEquipmentCost
|
||||
:returns: Cost to purchase the specified Equipment/Augmentation (number). Infinity
|
||||
for invalid arguments
|
||||
|
||||
getEquipmentType
|
||||
----------------
|
||||
|
||||
.. js:function:: getEquipmentType(equipName)
|
||||
|
||||
:param string equipName: Name of equipment
|
||||
|
||||
Get the specified equipment type, which can be one of the following:
|
||||
|
||||
* Weapon
|
||||
* Armor
|
||||
* Vehicle
|
||||
* Rootkit
|
||||
* Augmentation
|
||||
|
||||
:returns: A string stating the type of the equipment
|
||||
|
||||
purchaseEquipment
|
||||
-----------------
|
||||
|
||||
@ -234,6 +251,17 @@ setTerritoryWarfare
|
||||
|
||||
Set whether or not the gang should engage in territory warfare
|
||||
|
||||
getChanceToWinClash
|
||||
-------------------
|
||||
|
||||
.. js:function:: getChanceToWinClash(gangName)
|
||||
|
||||
:param string gangName: Target gang
|
||||
|
||||
Returns the chance you have to win a clash with the specified gang. The chance
|
||||
is returned in decimal form, not percentage
|
||||
|
||||
|
||||
getBonusTime
|
||||
------------
|
||||
|
||||
|
@ -59,7 +59,8 @@ var TextHighlightRules = acequire("./text_highlight_rules").TextHighlightRules;
|
||||
var identifierRe = "[a-zA-Z\\$_\u00a1-\uffff][a-zA-Z\\d\\$_\u00a1-\uffff]*";
|
||||
|
||||
let NetscriptFunctions =
|
||||
"hack|sleep|grow|weaken|print|tprint|scan|nuke|brutessh|ftpcrack|" + //Netscript functions
|
||||
"hack|sleep|grow|weaken|growthAnalyze|print|tprint|scan|nuke|brutessh|" +
|
||||
"ftpcrack|" +
|
||||
"clearLog|disableLog|enableLog|isLogEnabled|getScriptLogs|" +
|
||||
"relaysmtp|httpworm|sqlinject|run|exec|spawn|kill|killall|exit|" +
|
||||
"scp|ls|ps|hasRootAccess|" +
|
||||
@ -106,8 +107,9 @@ let NetscriptFunctions =
|
||||
"gang|" +
|
||||
"getMemberNames|getGangInformation|getMemberInformation|canRecruitMember|" +
|
||||
"recruitMember|getTaskNames|setMemberTask|getEquipmentNames|" +
|
||||
"getEquipmentCost|purchaseEquipment|ascendMember|setTerritoryWarfare|" +
|
||||
"getBonusTime|" +
|
||||
"getEquipmentCost|getEquipmentType|purchaseEquipment|ascendMember|" +
|
||||
"setTerritoryWarfare|" +
|
||||
"getChanceToWinClash|getBonusTime|" +
|
||||
|
||||
// Bladeburner API
|
||||
"bladeburner|getContractNames|getOperationNames|getBlackOpNames|" +
|
||||
|
@ -304,6 +304,7 @@ function initBitNodeMultipliers() {
|
||||
BitNodeMultipliers.InfiltrationMoney = 0;
|
||||
BitNodeMultipliers.RepToDonateToFaction = 0;
|
||||
BitNodeMultipliers.CorporationValuation = 0;
|
||||
BitNodeMultipliers.CodingContractMoney = 0;
|
||||
break;
|
||||
case 11: //The Big Crash
|
||||
BitNodeMultipliers.ServerMaxMoney = 0.1;
|
||||
|
@ -29,6 +29,11 @@ interface IBitNodeMultipliers {
|
||||
*/
|
||||
ClassGymExpGain: number;
|
||||
|
||||
/**
|
||||
* Influences the amount of money gained from completing Coding Contracts
|
||||
**/
|
||||
CodingContractMoney: number;
|
||||
|
||||
/**
|
||||
* Influences the experience gained for each ability when the player completes working their job.
|
||||
*/
|
||||
@ -154,6 +159,7 @@ export const BitNodeMultipliers: IBitNodeMultipliers = {
|
||||
HacknetNodeMoney: 1,
|
||||
ManualHackMoney: 1,
|
||||
ScriptHackMoney: 1,
|
||||
CodingContractMoney: 1,
|
||||
|
||||
ClassGymExpGain: 1,
|
||||
CompanyWorkExpGain: 1,
|
||||
|
@ -918,14 +918,15 @@ Bladeburner.prototype.process = function() {
|
||||
|
||||
//Automation
|
||||
if (this.automateEnabled) {
|
||||
// Note: Do NOT set this.action = this.automateActionHigh/Low since it creates a reference
|
||||
if (this.stamina <= this.automateThreshLow) {
|
||||
if (this.action.name !== this.automateActionLow.name || this.action.type !== this.automateActionLow.type) {
|
||||
this.action = this.automateActionLow;
|
||||
this.action = new ActionIdentifier({type: this.automateActionLow.type, name: this.automateActionLow.name});
|
||||
this.startAction(this.action);
|
||||
}
|
||||
} else if (this.stamina >= this.automateThreshHigh) {
|
||||
if (this.action.name !== this.automateActionHigh.name || this.action.type !== this.automateActionHigh.type) {
|
||||
this.action = this.automateActionHigh;
|
||||
this.action = new ActionIdentifier({type: this.automateActionHigh.type, name: this.automateActionHigh.name});
|
||||
this.startAction(this.action);
|
||||
}
|
||||
}
|
||||
@ -1119,6 +1120,13 @@ Bladeburner.prototype.startAction = function(actionId) {
|
||||
case ActionTypes["BlackOp"]:
|
||||
case ActionTypes["BlackOperation"]:
|
||||
try {
|
||||
// Safety measure - don't repeat BlackOps that are already done
|
||||
if (this.blackops[actionId.name] != null) {
|
||||
this.resetAction();
|
||||
this.log("Error: Tried to start a Black Operation that had already been completed");
|
||||
break;
|
||||
}
|
||||
|
||||
var action = this.getActionObject(actionId);
|
||||
if (action == null) {
|
||||
throw new Error("Failed to get BlackOperation object for: " + actionId.name);
|
||||
@ -2096,6 +2104,8 @@ Bladeburner.prototype.createBlackOpsContent = function() {
|
||||
"Black Operations (Black Ops) are special, one-time covert operations. " +
|
||||
"Each Black Op must be unlocked successively by completing " +
|
||||
"the one before it.<br><br>" +
|
||||
"<b>Your ultimate goal to climb through the ranks of Bladeburners is to complete " +
|
||||
"all of the Black Ops.</b><br><br>" +
|
||||
"Like normal operations, you may use a team for Black Ops. Failing " +
|
||||
"a black op will incur heavy HP and rank losses.";
|
||||
|
||||
@ -3373,6 +3383,12 @@ Bladeburner.prototype.startActionNetscriptFn = function(type, name, workerScript
|
||||
return false;
|
||||
}
|
||||
|
||||
// Can't start a BlackOp if its already been done
|
||||
if (this.blackops[actionId.name] != null) {
|
||||
workerScript.log(`Failed to start Black Op ${actionId.name} because its already been completed`);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Can't start a BlackOp if you haven't done the one before it
|
||||
var blackops = [];
|
||||
for (const nm in BlackOperations) {
|
||||
|
@ -34,7 +34,7 @@ CharacterOverview.prototype.update = function() {
|
||||
|
||||
let changed = false;
|
||||
changed = replaceAndChanged(this.hp, Player.hp + " / " + Player.max_hp) || changed;
|
||||
changed = replaceAndChanged(this.money, numeralWrapper.format(Player.money.toNumber(), '($0.000a)')) || changed;
|
||||
changed = replaceAndChanged(this.money, numeralWrapper.format(Player.money.toNumber(), '$0.000a')) || changed;
|
||||
changed = replaceAndChanged(this.hack, (Player.hacking_skill).toLocaleString()) || changed;
|
||||
changed = replaceAndChanged(this.str, (Player.strength).toLocaleString()) || changed;
|
||||
changed = replaceAndChanged(this.def, (Player.defense).toLocaleString()) || changed;
|
||||
|
1149
src/Company.js
1149
src/Company.js
File diff suppressed because it is too large
Load Diff
50
src/Company/Companies.ts
Normal file
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
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;
|
182
src/Company/CompanyPosition.ts
Normal file
182
src/Company/CompanyPosition.ts
Normal file
@ -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);
|
||||
}
|
||||
}
|
17
src/Company/CompanyPositions.ts
Normal file
17
src/Company/CompanyPositions.ts
Normal file
@ -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);
|
||||
});
|
40
src/Company/GetJobRequirementText.ts
Normal file
40
src/Company/GetJobRequirementText.ts
Normal file
@ -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;
|
||||
}
|
13
src/Company/GetNextCompanyPosition.ts
Normal file
13
src/Company/GetNextCompanyPosition.ts
Normal file
@ -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
1
src/Company/README.md
Normal file
@ -0,0 +1 @@
|
||||
Implementation of Company and Job related mechanics
|
544
src/Company/data/CompaniesMetadata.ts
Normal file
544
src/Company/data/CompaniesMetadata.ts
Normal file
@ -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,
|
||||
},
|
||||
]
|
602
src/Company/data/CompanyPositionsMetadata.ts
Normal file
602
src/Company/data/CompanyPositionsMetadata.ts
Normal file
@ -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,
|
||||
},
|
||||
]
|
72
src/Company/data/companypositionnames.ts
Normal file
72
src/Company/data/companypositionnames.ts
Normal file
@ -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 = {
|
||||
Version: "0.41.1",
|
||||
import {IMap} from "./types";
|
||||
|
||||
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
|
||||
//and the skill level formula in Player.js. Note that all this means it that when experience hits MAX_INT, then
|
||||
@ -54,6 +56,7 @@ let CONSTANTS = {
|
||||
ScriptIfRamCost: 0,
|
||||
ScriptHackRamCost: 0.1,
|
||||
ScriptGrowRamCost: 0.15,
|
||||
ScriptGrowthAnalyzeRamCost: 1,
|
||||
ScriptWeakenRamCost: 0.15,
|
||||
ScriptScanRamCost: 0.2,
|
||||
ScriptPortProgramRamCost: 0.05,
|
||||
@ -502,33 +505,31 @@ let CONSTANTS = {
|
||||
|
||||
LatestUpdate:
|
||||
`
|
||||
v0.41.1
|
||||
v0.41.2
|
||||
* IMPORTANT - Netscript Changes:
|
||||
** purchaseTor() now returns true if you already have a TOR router (it used to return false)
|
||||
** getPurchasedServerCost() now returns Infinity if the specified RAM is an invalid amount or is greater than the max amount of RAM (2 ^ 20 GB)
|
||||
** Added purchase4SMarketData() and purchase4SMarketDataTixApi() functions
|
||||
** getScriptLogs() now takes in optional arguments that let you get the logs of another script
|
||||
** rm() now takes an optional parameter that lets you specify on which server to delete the file
|
||||
** Added growthAnalyze() Netscript function
|
||||
|
||||
* Stock Market changes:
|
||||
** Stocks now have "maximum prices". These are hidden from the player
|
||||
** If a stock reaches its "maximum price", it will most likely drop in value (although it might still rise)
|
||||
** Each stock has its own, unique maximum price
|
||||
** Maximum price for each stock are randomly generated and change during each 'reset'
|
||||
** Stock Market cycles are now accumulated/stored, much like it is for Gangs and Bladeburners
|
||||
** Accumulated/stored cycles cause stock prices to update up to 50% faster (from every 6 seconds to 4 seconds)
|
||||
*** This means that after coming back from being offline, stock prices will update faster to make up for offline time
|
||||
* Gang Changes:
|
||||
** UI now displays your chance to win a clash with other gangs
|
||||
** Added getChanceToWinClash() function to the Gang API
|
||||
** Added getEquipmentType() function to the Gang API
|
||||
** Added several new hacking-based equipment and Augmentations
|
||||
** Rebalanced several equipment/upgrades to give less defense
|
||||
** Wanted level gain rate is now be slightly higher for all tasks
|
||||
** Rebalanced parameters for "hacking" tasks
|
||||
|
||||
* Decreased the Hacking Level multiplier for BitNodes 6 and 7 to 0.4 (from 0.5)
|
||||
* Bladeburner console history is now saved and persists when switching screens or closing/reopening the game
|
||||
* In Bladeburner, if your stamina reaches 0 your current action will be cancelled
|
||||
* b1t_flum3.exe is no longer removed from your home computer upon reset
|
||||
* Added main menu link for the Stock Market (once you've purchased an account)
|
||||
* Job main menu link only appears if you actually have a job
|
||||
* Bug Fix: Netscript Gang API functions purchaseEquipment() and ascendMember() should now work properly
|
||||
* Bug Fix: After installing Augs, the "Portfolio Mode" button on the Stock Market page should be properly reset
|
||||
* Bug Fix: bladeburner.getActionCountRemaining()'s return value is now rounded down (by Kline-)
|
||||
* Added new Main Menu configuration in .fconf: "compact"
|
||||
* Added the terminal command 'expr', which can be used to evaluate simple mathematical expressions
|
||||
* Bug Fix: Can no longer purchase duplicate equipment/Augmentations through gang.purchaseEquipment()
|
||||
* Bug Fix: scp() should no longer throw errors when used with 2-arguments and an array of files
|
||||
* Bug Fix: Coding Contracts no longer give money in BitNode-8
|
||||
* Bug Fix: In Bladeburner, you can no longer start a BlackOp through the Netscript API if it has already been completed
|
||||
* Bug Fix: In Bladeburner, fixed a bug which caused the configured 'automate' actions to occasionally be switched to other actions
|
||||
* Bug Fix: 'Return to World' button at locations no longer accumulates event listeners
|
||||
* Bug Fix: Working & taking classes now continuously add/subtract money during the action, instead of doing it at completion
|
||||
* Bug Fix: Top-right overview panel now displays negative money using '-' instead of '()'
|
||||
* Bug Fix: Stock Market UI should no longer show 'NaN' profit immediately after buying a stock
|
||||
`
|
||||
|
||||
}
|
||||
|
||||
export {CONSTANTS};
|
@ -345,6 +345,26 @@ export function createDevMenu() {
|
||||
innerText: "Gain Bladeburner Rank",
|
||||
});
|
||||
|
||||
const bladeburnerStoredCyclesInput = createElement("input", {
|
||||
class: "text-input",
|
||||
margin: "5px",
|
||||
placeholder: "# Cycles to Add",
|
||||
type: "number",
|
||||
});
|
||||
|
||||
const bladeburnerStoredCyclesButton = createElement("button", {
|
||||
class: "std-button",
|
||||
clickListener: () => {
|
||||
try {
|
||||
const cycles = parseInt(bladeburnerStoredCyclesInput.value);
|
||||
Player.bladeburner.storedCycles += cycles;
|
||||
} catch(e) {
|
||||
exceptionAlert(`Failed to add cycles to Bladeburner in dev menu: ${e}`);
|
||||
}
|
||||
},
|
||||
innerText: "Add Cycles to Bladeburner mechanic",
|
||||
});
|
||||
|
||||
// Gang
|
||||
const gangHeader = createElement("h2", {innerText: "Gang"});
|
||||
|
||||
@ -501,6 +521,9 @@ export function createDevMenu() {
|
||||
devMenuContainer.appendChild(bladeburnerGainRankInput);
|
||||
devMenuContainer.appendChild(bladeburnerGainRankButton);
|
||||
devMenuContainer.appendChild(createElement("br"));
|
||||
devMenuContainer.appendChild(bladeburnerStoredCyclesInput);
|
||||
devMenuContainer.appendChild(bladeburnerStoredCyclesButton);
|
||||
devMenuContainer.appendChild(createElement("br"));
|
||||
devMenuContainer.appendChild(gangHeader);
|
||||
devMenuContainer.appendChild(gangStoredCyclesInput);
|
||||
devMenuContainer.appendChild(gangAddStoredCycles);
|
||||
|
@ -385,14 +385,17 @@ function displayFactionContent(factionName) {
|
||||
gangDiv.appendChild(gangDivWrapper);
|
||||
gangDivWrapper.appendChild(createElement("a", {
|
||||
class:"a-link-button", innerText:"Manage Gang",
|
||||
clickListener:()=>{
|
||||
clickListener: () => {
|
||||
if (!Player.inGang()) {
|
||||
// Determine whether this is a hacking gang
|
||||
let hacking = false;
|
||||
if (factionName === "NiteSec" || factionName === "The Black Hand") { hacking = true; }
|
||||
|
||||
// Configure Yes/No buttons for the pop-up
|
||||
var yesBtn = yesNoBoxGetYesButton(), noBtn = yesNoBoxGetNoButton();
|
||||
yesBtn.innerHTML = "Create Gang";
|
||||
noBtn.innerHTML = "Cancel";
|
||||
yesBtn.addEventListener("click", () => {
|
||||
var hacking = false;
|
||||
if (factionName === "NiteSec" || factionName === "The Black Hand") {hacking = true;}
|
||||
Player.startGang(factionName, hacking);
|
||||
document.getElementById("world-menu-header").click();
|
||||
document.getElementById("world-menu-header").click();
|
||||
@ -402,10 +405,24 @@ function displayFactionContent(factionName) {
|
||||
noBtn.addEventListener("click", () => {
|
||||
yesNoBoxClose();
|
||||
});
|
||||
yesNoBoxCreate("Would you like to create a new Gang with " + factionName + "?<br><br>" +
|
||||
|
||||
// Pop-up text
|
||||
let gangTypeText = "";
|
||||
if (hacking) {
|
||||
gangTypeText = "This is a HACKING gang. Members in this gang will have different tasks than COMBAT gangs. " +
|
||||
"Compared to combat gangs, progression with hacking gangs is more straightforward as territory warfare " +
|
||||
"is not as important.<br><br>";
|
||||
} else {
|
||||
gangTypeText = "This is a COMBAT gang. Members in this gang will have different tasks than HACKING gangs. " +
|
||||
"Compared to hacking gangs, progression with combat gangs can be more difficult as territory management " +
|
||||
"is more important. However, well-managed combat gangs can progress faster than hacking ones.<br><br>";
|
||||
}
|
||||
yesNoBoxCreate(`Would you like to create a new Gang with ${factionName}?<br><br>` +
|
||||
"Note that this will prevent you from creating a Gang with any other Faction until " +
|
||||
"this BitNode is destroyed. There are NO differences between the Factions you can " +
|
||||
"create a Gang with and each of these Factions have all Augmentations available");
|
||||
"this BitNode is destroyed.<br><br>" +
|
||||
gangTypeText +
|
||||
"Other than hacking vs combat, there are NO differences between the Factions you can " +
|
||||
"create a Gang with, and each of these Factions have all Augmentations available.");
|
||||
} else {
|
||||
Engine.loadGangContent();
|
||||
}
|
||||
|
12
src/Fconf.js
12
src/Fconf.js
@ -23,7 +23,7 @@ var FconfComments = {
|
||||
ENABLE_TIMESTAMPS: "Terminal commands and log entries will be timestamped. The timestamp\n" +
|
||||
"will have the format: M/D h:m",
|
||||
MAIN_MENU_STYLE: "Customize the main navigation menu on the left-hand side. Current options:\n\n" +
|
||||
"default, classic",
|
||||
"default, classic, compact",
|
||||
THEME_BACKGROUND_COLOR: "Sets the background color for not only the Terminal, but also for\n" +
|
||||
"most of the game's UI.\n\n" +
|
||||
"The color must be specified as a pound sign (#) followed by a \n" +
|
||||
@ -46,7 +46,7 @@ var FconfComments = {
|
||||
"before its effect takes place.",
|
||||
}
|
||||
|
||||
const MainMenuStyleOptions = ["default", "classic"];
|
||||
const MainMenuStyleOptions = ["default", "classic", "compact"];
|
||||
|
||||
//Parse Fconf settings from the config text
|
||||
//Throws an exception if parsing fails
|
||||
@ -231,12 +231,18 @@ function setMainMenuStyle() {
|
||||
if (FconfSettings["MAIN_MENU_STYLE"] === "default") {
|
||||
removeAllAccordionHeaderClasses();
|
||||
mainMenu.classList.remove("classic");
|
||||
mainMenu.classList.remove("compact");
|
||||
addClassToAllAccordionHeaders("mainmenu-accordion-header");
|
||||
|
||||
} else if (FconfSettings["MAIN_MENU_STYLE"] === "classic") {
|
||||
removeAllAccordionHeaderClasses();
|
||||
mainMenu.classList.remove("compact");
|
||||
mainMenu.classList.add("classic");
|
||||
addClassToAllAccordionHeaders("mainmenu-accordion-header-classic");
|
||||
} else if (FconfSettings["MAIN_MENU_STYLE"] === "compact") {
|
||||
removeAllAccordionHeaderClasses();
|
||||
mainMenu.classList.remove("classic");
|
||||
mainMenu.classList.add("compact");
|
||||
addClassToAllAccordionHeaders("mainmenu-accordion-header-compact");
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
72
src/Gang.js
72
src/Gang.js
@ -272,11 +272,11 @@ Gang.prototype.processTerritoryAndPowerGains = function(numCycles=1) {
|
||||
if (gainRoll < 0.5) {
|
||||
// Multiplicative gain (50% chance)
|
||||
// This is capped per cycle, to prevent it from getting out of control
|
||||
const multiplicativeGain = AllGangs[name].power * 0.008;
|
||||
AllGangs[name].power += Math.min(0.9, multiplicativeGain);
|
||||
const multiplicativeGain = AllGangs[name].power * 0.005;
|
||||
AllGangs[name].power += Math.min(0.85, multiplicativeGain);
|
||||
} else {
|
||||
// Additive gain (50% chance)
|
||||
const additiveGain = 0.5 * gainRoll * AllGangs[name].territory;
|
||||
const additiveGain = 0.75 * gainRoll * AllGangs[name].territory;
|
||||
AllGangs[name].power += (additiveGain);
|
||||
}
|
||||
}
|
||||
@ -533,6 +533,27 @@ Gang.prototype.getUpgradeCost = function(upgName) {
|
||||
return GangMemberUpgrades[upgName].getCost(this);
|
||||
}
|
||||
|
||||
// Returns a player-friendly string stating the type of the specified upgrade
|
||||
Gang.prototype.getUpgradeType = function(upgName) {
|
||||
const upg = GangMemberUpgrades[upgName];
|
||||
if (upg == null) { return ""; }
|
||||
|
||||
switch (upg.type) {
|
||||
case "w":
|
||||
return "Weapon";
|
||||
case "a":
|
||||
return "Armor";
|
||||
case "v":
|
||||
return "Vehicle";
|
||||
case "r":
|
||||
return "Rootkit";
|
||||
case "g":
|
||||
return "Augmentation";
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
Gang.prototype.toJSON = function() {
|
||||
return Generic_toJSON("Gang", this);
|
||||
}
|
||||
@ -660,7 +681,7 @@ GangMember.prototype.calculateWantedLevelGain = function(gang) {
|
||||
if (task.baseWanted < 0) {
|
||||
return 0.5 * task.baseWanted * statWeight * territoryMult;
|
||||
} else {
|
||||
return 7 * task.baseWanted / (3 * statWeight * territoryMult);
|
||||
return 7 * task.baseWanted / (Math.pow(3 * statWeight * territoryMult, 0.8));
|
||||
}
|
||||
}
|
||||
|
||||
@ -788,6 +809,11 @@ GangMember.prototype.buyUpgrade = function(upg, player, gang) {
|
||||
if (!(upg instanceof GangMemberUpgrade)) {
|
||||
return false;
|
||||
}
|
||||
// Prevent purchasing of already-owned upgrades
|
||||
if (this.augmentations.includes(upg.name) || this.upgrades.includes(upg.name)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (player.money.lt(upg.getCost(gang))) { return false; }
|
||||
player.loseMoney(upg.getCost(gang));
|
||||
if (upg.type === "g") {
|
||||
@ -1521,9 +1547,10 @@ Gang.prototype.updateGangContent = function() {
|
||||
|
||||
// Update territory information
|
||||
UIElems.gangTerritoryInfoText.innerHTML = "";
|
||||
for (var gangname in AllGangs) {
|
||||
const playerPower = AllGangs[this.facName].power;
|
||||
for (const gangname in AllGangs) {
|
||||
if (AllGangs.hasOwnProperty(gangname)) {
|
||||
var gangTerritoryInfo = AllGangs[gangname];
|
||||
const gangTerritoryInfo = AllGangs[gangname];
|
||||
let territory = gangTerritoryInfo.territory * 100;
|
||||
|
||||
//Fix some rounding issues graphically
|
||||
@ -1536,12 +1563,16 @@ Gang.prototype.updateGangContent = function() {
|
||||
displayNumber = formatNumber(territory, 2);
|
||||
}
|
||||
|
||||
if (gangname == this.facName) {
|
||||
UIElems.gangTerritoryInfoText.innerHTML += ("<b>" + gangname + "</b><br>(Power: " + formatNumber(gangTerritoryInfo.power, 6) + "): " +
|
||||
displayNumber + "%<br><br>");
|
||||
if (gangname === this.facName) {
|
||||
let newHTML = `<b><u>${gangname}</u></b><br>Power: ${formatNumber(gangTerritoryInfo.power, 6)}<br>`;
|
||||
newHTML += `Territory: ${displayNumber}%<br><br>`;
|
||||
UIElems.gangTerritoryInfoText.innerHTML += newHTML;
|
||||
} else {
|
||||
UIElems.gangTerritoryInfoText.innerHTML += (gangname + "<br>(Power: " + formatNumber(gangTerritoryInfo.power, 6) + "): " +
|
||||
displayNumber + "%<br><br>");
|
||||
const clashVictoryChance = playerPower / (gangTerritoryInfo.power + playerPower);
|
||||
let newHTML = `<u>${gangname}</u><br>Power: ${formatNumber(gangTerritoryInfo.power, 6)}<br>`;
|
||||
newHTML += `Territory: ${displayNumber}%<br>`;
|
||||
newHTML += `Chance to win clash with this gang: ${numeralWrapper.format(clashVictoryChance, "0.000%")}<br><br>`;
|
||||
UIElems.gangTerritoryInfoText.innerHTML += newHTML;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1853,6 +1884,25 @@ Gang.prototype.updateGangMemberDisplayElement = function(memberObj) {
|
||||
`Wanted Level: ${formatNumber(5*memberObj.calculateWantedLevelGain(this), 6)} / sec`,
|
||||
`Total Respect Earned: ${formatNumber(memberObj.earnedRespect, 6)}`].join("<br>");
|
||||
}
|
||||
|
||||
// Update selector to have the correct task
|
||||
const taskSelector = document.getElementById(name + "gang-member-task-selector");
|
||||
if (taskSelector) {
|
||||
let tasks = this.getAllTaskNames();
|
||||
tasks.unshift("---");
|
||||
|
||||
if (GangMemberTasks.hasOwnProperty(memberObj.task)) {
|
||||
const taskName = memberObj.task;
|
||||
let taskIndex = 0;
|
||||
for (let i = 0; i < tasks.length; ++i) {
|
||||
if (taskName === tasks[i]) {
|
||||
taskIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
taskSelector.selectedIndex = taskIndex;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Gang.prototype.setGangMemberTaskDescription = function(memberObj, taskName) {
|
||||
|
@ -10,6 +10,7 @@ export const TerminalHelpText: string =
|
||||
"cls See 'clear' command <br>" +
|
||||
"connect [ip/hostname] Connects to a remote server<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>" +
|
||||
"hack Hack the current machine<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: download *.script<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>" +
|
||||
"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.",
|
||||
|
@ -1,6 +1,8 @@
|
||||
import {Bladeburner} from "./Bladeburner";
|
||||
import {CompanyPositions, initCompanies,
|
||||
Companies, getJobRequirementText} from "./Company";
|
||||
import {CompanyPositions} from "./Company/CompanyPositions";
|
||||
import {Companies} from "./Company/Companies";
|
||||
import {getJobRequirementText} from "./Company/GetJobRequirementText";
|
||||
import * as posNames from "./Company/data/CompanyPositionNames";
|
||||
import {Corporation} from "./CompanyManagement";
|
||||
import {CONSTANTS} from "./Constants";
|
||||
import {Crimes} from "./Crimes";
|
||||
@ -28,7 +30,7 @@ import {yesNoBoxCreate, yesNoTxtInpBoxCreate,
|
||||
yesNoTxtInpBoxClose} from "../utils/YesNoBox";
|
||||
|
||||
function displayLocationContent() {
|
||||
var returnToWorld = document.getElementById("location-return-to-world-button");
|
||||
var returnToWorld = clearEventListeners("location-return-to-world-button");
|
||||
|
||||
var locationName = document.getElementById("location-name");
|
||||
|
||||
@ -111,7 +113,7 @@ function displayLocationContent() {
|
||||
|
||||
var cityHallCreateCorporation = document.getElementById("location-cityhall-create-corporation");
|
||||
|
||||
var nsaBladeburner = document.getElementById("location-nsa-bladeburner");
|
||||
var nsaBladeburner = clearEventListeners("location-nsa-bladeburner");
|
||||
|
||||
var loc = Player.location;
|
||||
|
||||
@ -233,7 +235,7 @@ function displayLocationContent() {
|
||||
//Check if the player is employed at this Location. If he is, display the "Work" button,
|
||||
//update the job title, etc.
|
||||
if (loc != "" && loc === Player.companyName) {
|
||||
var company = Companies[loc];
|
||||
let company = Companies[loc];
|
||||
|
||||
jobTitle.style.display = "block";
|
||||
jobReputation.style.display = "inline";
|
||||
@ -241,8 +243,8 @@ function displayLocationContent() {
|
||||
locationTxtDiv1.style.display = "block";
|
||||
locationTxtDiv2.style.display = "block";
|
||||
locationTxtDiv3.style.display = "block";
|
||||
jobTitle.innerHTML = "Job Title: " + Player.companyPosition.positionName;
|
||||
var repGain = company.getFavorGain();
|
||||
jobTitle.innerHTML = "Job Title: " + Player.companyPosition;
|
||||
let repGain = company.getFavorGain();
|
||||
if (repGain.length != 2) {repGain = 0;}
|
||||
repGain = repGain[0];
|
||||
jobReputation.innerHTML = "Company reputation: " + formatNumber(company.playerReputation, 4) +
|
||||
@ -256,10 +258,13 @@ function displayLocationContent() {
|
||||
"favor you gain depends on how much reputation you have with the company</span>";
|
||||
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() {
|
||||
if (currPos.isPartTimeJob()) {
|
||||
if (currPos.isPartTimeJob() || currPos.isSoftwareConsultantJob() || currPos.isBusinessConsultantJob()) {
|
||||
Player.startWorkPartTime();
|
||||
} else {
|
||||
Player.startWork();
|
||||
@ -301,19 +306,19 @@ function displayLocationContent() {
|
||||
var hospitalTreatmentCost = (Player.max_hp - Player.hp) * CONSTANTS.HospitalCostPerHp;
|
||||
|
||||
//Set tooltip for job requirements
|
||||
setJobRequirementTooltip(loc, CompanyPositions.SoftwareIntern, softwareJob);
|
||||
setJobRequirementTooltip(loc, CompanyPositions.SoftwareConsultant, softwareConsultantJob);
|
||||
setJobRequirementTooltip(loc, CompanyPositions.ITIntern, itJob);
|
||||
setJobRequirementTooltip(loc, CompanyPositions.SecurityEngineer, securityEngineerJob);
|
||||
setJobRequirementTooltip(loc, CompanyPositions.NetworkEngineer, networkEngineerJob);
|
||||
setJobRequirementTooltip(loc, CompanyPositions.BusinessIntern, businessJob);
|
||||
setJobRequirementTooltip(loc, CompanyPositions.BusinessConsultant, businessConsultantJob);
|
||||
setJobRequirementTooltip(loc, CompanyPositions.SecurityGuard, securityJob);
|
||||
setJobRequirementTooltip(loc, CompanyPositions.FieldAgent, agentJob);
|
||||
setJobRequirementTooltip(loc, CompanyPositions.Employee, employeeJob);
|
||||
setJobRequirementTooltip(loc, CompanyPositions.PartTimeEmployee, employeePartTimeJob);
|
||||
setJobRequirementTooltip(loc, CompanyPositions.Waiter, waiterJob);
|
||||
setJobRequirementTooltip(loc, CompanyPositions.PartTimeWaiter, waiterPartTimeJob);
|
||||
setJobRequirementTooltip(loc, CompanyPositions[posNames.SoftwareCompanyPositions[0]], softwareJob);
|
||||
setJobRequirementTooltip(loc, CompanyPositions[posNames.SoftwareConsultantCompanyPositions[0]], softwareConsultantJob);
|
||||
setJobRequirementTooltip(loc, CompanyPositions[posNames.ITCompanyPositions[0]], itJob);
|
||||
setJobRequirementTooltip(loc, CompanyPositions[posNames.SecurityEngineerCompanyPositions[0]], securityEngineerJob);
|
||||
setJobRequirementTooltip(loc, CompanyPositions[posNames.NetworkEngineerCompanyPositions[0]], networkEngineerJob);
|
||||
setJobRequirementTooltip(loc, CompanyPositions[posNames.BusinessCompanyPositions[0]], businessJob);
|
||||
setJobRequirementTooltip(loc, CompanyPositions[posNames.BusinessConsultantCompanyPositions[0]], businessConsultantJob);
|
||||
setJobRequirementTooltip(loc, CompanyPositions[posNames.SecurityCompanyPositions[0]], securityJob);
|
||||
setJobRequirementTooltip(loc, CompanyPositions[posNames.AgentCompanyPositions[0]], agentJob);
|
||||
setJobRequirementTooltip(loc, CompanyPositions[posNames.MiscCompanyPositions[1]], employeeJob);
|
||||
setJobRequirementTooltip(loc, CompanyPositions[posNames.PartTimeCompanyPositions[1]], employeePartTimeJob);
|
||||
setJobRequirementTooltip(loc, CompanyPositions[posNames.MiscCompanyPositions[0]], waiterJob);
|
||||
setJobRequirementTooltip(loc, CompanyPositions[posNames.PartTimeCompanyPositions[0]], waiterPartTimeJob);
|
||||
|
||||
switch (loc) {
|
||||
case Locations.AevumTravelAgency:
|
||||
@ -1030,18 +1035,18 @@ function displayLocationContent() {
|
||||
console.log("ERROR: INVALID LOCATION");
|
||||
}
|
||||
|
||||
//Make the "Apply to be Employee and Waiter" texts disappear if you already hold the job
|
||||
//Includes part-time stuff
|
||||
// Make the "Apply to be Employee and Waiter" texts disappear if you already hold the job
|
||||
// Includes part-time stuff
|
||||
if (loc == Player.companyName) {
|
||||
var currPos = Player.companyPosition;
|
||||
|
||||
if (currPos.positionName == CompanyPositions.Employee.positionName) {
|
||||
if (currPos == "Employee") {
|
||||
employeeJob.style.display = "none";
|
||||
} else if (currPos.positionName == CompanyPositions.Waiter.positionName) {
|
||||
} else if (currPos == "Waiter") {
|
||||
waiterJob.style.display = "none";
|
||||
} else if (currPos.positionName == CompanyPositions.PartTimeEmployee.positionName) {
|
||||
} else if (currPos == "Part-time Employee") {
|
||||
employeePartTimeJob.style.display = "none";
|
||||
} else if (currPos.positionName == CompanyPositions.PartTimeWaiter.positionName) {
|
||||
} else if (currPos == "Part-time Waiter") {
|
||||
waiterPartTimeJob.style.display = "none";
|
||||
}
|
||||
}
|
||||
@ -2173,8 +2178,8 @@ function setJobRequirementTooltip(loc, entryPosType, btn) {
|
||||
var company = Companies[loc];
|
||||
if (company == null) {return;}
|
||||
var pos = Player.getNextCompanyPosition(company, entryPosType);
|
||||
if (pos == null) {return};
|
||||
if (!company.hasPosition(pos)) {return;}
|
||||
if (pos == null) { return };
|
||||
if (!company.hasPosition(pos)) { return; }
|
||||
var reqText = getJobRequirementText(company, pos, true);
|
||||
btn.innerHTML += "<span class='tooltiptext'>" + reqText + "</span>";
|
||||
}
|
||||
|
@ -8,8 +8,10 @@ import {Augmentations, Augmentation,
|
||||
import {BitNodeMultipliers} from "./BitNodeMultipliers";
|
||||
import {determineCrimeSuccess, findCrime} from "./Crimes";
|
||||
import {Bladeburner} from "./Bladeburner";
|
||||
import {Companies, Company, CompanyPosition,
|
||||
CompanyPositions, companyExists} from "./Company";
|
||||
import {Company} from "./Company/Company";
|
||||
import {Companies, companyExists} from "./Company/Companies";
|
||||
import {CompanyPosition} from "./Company/CompanyPosition";
|
||||
import {CompanyPositions} from "./Company/CompanyPositions";
|
||||
import {CONSTANTS} from "./Constants";
|
||||
import {Programs} from "./CreateProgram";
|
||||
import {DarkWebItems} from "./DarkWeb";
|
||||
@ -31,7 +33,7 @@ import {Script, findRunningScript, RunningScript,
|
||||
isScriptFilename} from "./Script";
|
||||
import {Server, getServer, AddToAllServers,
|
||||
AllServers, processSingleServerGrowth,
|
||||
GetServerByHostname} from "./Server";
|
||||
GetServerByHostname, numCycleForGrowth} from "./Server";
|
||||
import {Settings} from "./Settings";
|
||||
import {SpecialServerIps} from "./SpecialServerIps";
|
||||
import {Stock} from "./Stock";
|
||||
@ -461,7 +463,21 @@ function NetscriptFunctions(workerScript) {
|
||||
return Promise.resolve(moneyAfter/moneyBefore);
|
||||
});
|
||||
},
|
||||
weaken : function(ip){
|
||||
growthAnalyze : function(ip, growth) {
|
||||
if (workerScript.checkingRam) {
|
||||
return updateStaticRam("growthAnalyze", CONSTANTS.ScriptGrowthAnalyzeRamCost);
|
||||
}
|
||||
updateDynamicRam("growthAnalyze", CONSTANTS.ScriptGrowthAnalyzeRamCost);
|
||||
|
||||
// Check argument validity
|
||||
const server = safeGetServer(ip, 'growthAnalyze');
|
||||
if (isNaN(growth)) {
|
||||
throw makeRuntimeRejectMsg(workerScript, `Invalid growth argument passed into growthAnalyze: ${growth}. Must be numeric`);
|
||||
}
|
||||
|
||||
return numCycleForGrowth(server, Number(growth));
|
||||
},
|
||||
weaken : function(ip) {
|
||||
if (workerScript.checkingRam) {
|
||||
return updateStaticRam("weaken", CONSTANTS.ScriptWeakenRamCost);
|
||||
}
|
||||
@ -919,7 +935,7 @@ function NetscriptFunctions(workerScript) {
|
||||
|
||||
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) {
|
||||
throw makeRuntimeRejectMsg(workerScript, "ERROR: scp() call has incorrect number of arguments. Takes 2 or 3 arguments");
|
||||
}
|
||||
@ -932,7 +948,7 @@ function NetscriptFunctions(workerScript) {
|
||||
if (currServ == null) {
|
||||
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) {
|
||||
throw makeRuntimeRejectMsg(workerScript, "ERROR: scp() call has incorrect number of arguments. Takes 2 or 3 arguments");
|
||||
}
|
||||
@ -945,6 +961,8 @@ function NetscriptFunctions(workerScript) {
|
||||
if (currServ == null) {
|
||||
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
|
||||
@ -2138,14 +2156,18 @@ function NetscriptFunctions(workerScript) {
|
||||
}
|
||||
return port;
|
||||
},
|
||||
rm : function(fn) {
|
||||
rm : function(fn, ip) {
|
||||
if (workerScript.checkingRam) {
|
||||
return updateStaticRam("rm", CONSTANTS.ScriptReadWriteRamCost);
|
||||
}
|
||||
updateDynamicRam("rm", CONSTANTS.ScriptReadWriteRamCost);
|
||||
var s = getServer(workerScript.serverIp);
|
||||
|
||||
if (ip == null || ip === "") {
|
||||
ip = workerScript.serverIp;
|
||||
}
|
||||
var s = getServer(ip);
|
||||
if (s == null) {
|
||||
throw makeRuntimeRejectMsg(workerScript, "Error getting Server for this script in clear(). This is a bug please contact game dev");
|
||||
throw makeRuntimeRejectMsg(workerScript, `Invalid server specified for rm(): ${ip}`);
|
||||
}
|
||||
|
||||
if (fn.includes(".exe")) {
|
||||
@ -2779,8 +2801,8 @@ function NetscriptFunctions(workerScript) {
|
||||
}
|
||||
|
||||
var companyPositionTitle = "";
|
||||
if (Player.companyPosition instanceof CompanyPosition) {
|
||||
companyPositionTitle = Player.companyPosition.positionName;
|
||||
if (CompanyPositions[Player.companyPosition] instanceof CompanyPosition) {
|
||||
companyPositionTitle = Player.companyPosition;
|
||||
}
|
||||
return {
|
||||
bitnode: Player.bitNodeN,
|
||||
@ -2921,7 +2943,8 @@ function NetscriptFunctions(workerScript) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (Player.companyPosition == "" || !(Player.companyPosition instanceof CompanyPosition)) {
|
||||
const companyPosition = CompanyPositions[Player.companyPosition];
|
||||
if (Player.companyPosition === "" || !(companyPosition instanceof CompanyPosition)) {
|
||||
workerScript.scriptRef.log("ERROR: workForCompany() failed because you do not have a job");
|
||||
return false;
|
||||
}
|
||||
@ -2933,13 +2956,13 @@ function NetscriptFunctions(workerScript) {
|
||||
}
|
||||
}
|
||||
|
||||
if (Player.companyPosition.isPartTimeJob()) {
|
||||
if (companyPosition.isPartTimeJob()) {
|
||||
Player.startWorkPartTime();
|
||||
} else {
|
||||
Player.startWork();
|
||||
}
|
||||
if (workerScript.disableLogs.ALL == null && workerScript.disableLogs.workForCompany == null) {
|
||||
workerScript.scriptRef.log("Began working at " + Player.companyName + " as a " + Player.companyPosition.positionName);
|
||||
workerScript.log(`Began working at ${Player.companyName} as a ${Player.companyPosition}`);
|
||||
}
|
||||
return true;
|
||||
},
|
||||
@ -3015,11 +3038,11 @@ function NetscriptFunctions(workerScript) {
|
||||
}
|
||||
if (res) {
|
||||
if (workerScript.disableLogs.ALL == null && workerScript.disableLogs.applyToCompany == null) {
|
||||
workerScript.scriptRef.log("You were offered a new job at " + companyName + " as a " + Player.companyPosition.positionName);
|
||||
workerScript.log(`You were offered a new job at ${companyName} as a ${Player.companyPosition}`);
|
||||
}
|
||||
} else {
|
||||
if (workerScript.disableLogs.ALL == null && workerScript.disableLogs.applyToCompany == null) {
|
||||
workerScript.scriptRef.log("You failed to get a new job/promotion at " + companyName + " in the " + field + " field.");
|
||||
workerScript.log(`You failed to get a new job/promotion at ${companyName} in the ${field} field.`);
|
||||
}
|
||||
}
|
||||
return res;
|
||||
@ -3860,6 +3883,19 @@ function NetscriptFunctions(workerScript) {
|
||||
throw makeRuntimeRejectMsg(workerScript, nsGang.unknownGangApiExceptionMessage("getEquipmentCost", e));
|
||||
}
|
||||
},
|
||||
getEquipmentType : function(equipName) {
|
||||
if (workerScript.checkingRam) {
|
||||
return updateStaticRam("getEquipmentType", CONSTANTS.ScriptGangApiBaseRamCost / 2);
|
||||
}
|
||||
updateDynamicRam("getEquipmentType", CONSTANTS.ScriptGangApiBaseRamCost / 2);
|
||||
nsGang.checkGangApiAccess(workerScript, "getEquipmentType");
|
||||
|
||||
try {
|
||||
return Player.gang.getUpgradeType(equipName);
|
||||
} catch(e) {
|
||||
throw makeRuntimeRejectMsg(workerScript, nsGang.unknownGangApiExceptionMessage("getEquipmentType", e));
|
||||
}
|
||||
},
|
||||
purchaseEquipment : function(memberName, equipName) {
|
||||
if (workerScript.checkingRam) {
|
||||
return updateStaticRam("purchaseEquipment", CONSTANTS.ScriptGangApiBaseRamCost);
|
||||
@ -3932,6 +3968,27 @@ function NetscriptFunctions(workerScript) {
|
||||
throw makeRuntimeRejectMsg(workerScript, nsGang.unknownGangApiExceptionMessage("setTerritoryWarfare", e));
|
||||
}
|
||||
},
|
||||
getChanceToWinClash : function(otherGang) {
|
||||
if (workerScript.checkingRam) {
|
||||
return updateStaticRam("getChanceToWinClash", CONSTANTS.ScriptGangApiBaseRamCost);
|
||||
}
|
||||
updateDynamicRam("getChanceToWinClash", CONSTANTS.ScriptGangApiBaseRamCost);
|
||||
nsGang.checkGangApiAccess(workerScript, "getChanceToWinClash");
|
||||
|
||||
try {
|
||||
if (AllGangs[otherGang] == null) {
|
||||
workerScript.log(`Invalid gang specified in gang.getChanceToWinClash() : ${otherGang}`);
|
||||
return 0;
|
||||
}
|
||||
|
||||
const playerPower = AllGangs[Player.gang.facName].power;
|
||||
const otherPower = AllGangs[otherGang].power;
|
||||
|
||||
return playerPower / (otherPower + playerPower);
|
||||
} catch(e) {
|
||||
throw makeRuntimeRejectMsg(workerScript, nsGang.unknownGangApiExceptionMessage("getChanceToWinClash", e));
|
||||
}
|
||||
},
|
||||
getBonusTime : function() {
|
||||
if (workerScript.checkingRam) { return 0; }
|
||||
nsGang.checkGangApiAccess(workerScript, "getBonusTime");
|
||||
|
305
src/Player.js
305
src/Player.js
@ -3,9 +3,12 @@ import {Augmentations, applyAugmentation,
|
||||
PlayerOwnedAugmentation} from "./Augmentations";
|
||||
import {BitNodeMultipliers} from "./BitNodeMultipliers";
|
||||
import {CodingContractRewardType} from "./CodingContracts";
|
||||
import {Company, Companies, getNextCompanyPosition,
|
||||
getJobRequirementText, CompanyPosition,
|
||||
CompanyPositions} from "./Company";
|
||||
import {Company} from "./Company/Company";
|
||||
import {Companies} from "./Company/Companies";
|
||||
import {getNextCompanyPosition} from "./Company/GetNextCompanyPosition";
|
||||
import {getJobRequirementText} from "./Company/GetJobRequirementText";
|
||||
import {CompanyPositions} from "./Company/CompanyPositions";
|
||||
import * as posNames from "./Company/data/CompanyPositionNames";
|
||||
import {CONSTANTS} from "./Constants";
|
||||
import {Corporation} from "./CompanyManagement";
|
||||
import {Programs} from "./CreateProgram";
|
||||
@ -94,8 +97,8 @@ function PlayerObject() {
|
||||
this.location = "";
|
||||
|
||||
//Company Information
|
||||
this.companyName = ""; //Name of Company, equivalent to an object from Locations
|
||||
this.companyPosition = ""; //CompanyPosition object
|
||||
this.companyName = ""; // Name of Company. Must match a key value in Companies map
|
||||
this.companyPosition = ""; // Name of Company Position. Must match a key value in CompanyPositions map
|
||||
|
||||
//Servers
|
||||
this.currentServer = ""; //IP address of Server currently being accessed through terminal
|
||||
@ -636,12 +639,13 @@ PlayerObject.prototype.resetWorkStatus = function() {
|
||||
}
|
||||
|
||||
PlayerObject.prototype.processWorkEarnings = function(numCycles=1) {
|
||||
var hackExpGain = this.workHackExpGainRate * numCycles;
|
||||
var strExpGain = this.workStrExpGainRate * numCycles;
|
||||
var defExpGain = this.workDefExpGainRate * numCycles;
|
||||
var dexExpGain = this.workDexExpGainRate * numCycles;
|
||||
var agiExpGain = this.workAgiExpGainRate * numCycles;
|
||||
var chaExpGain = this.workChaExpGainRate * numCycles;
|
||||
const hackExpGain = this.workHackExpGainRate * numCycles;
|
||||
const strExpGain = this.workStrExpGainRate * numCycles;
|
||||
const defExpGain = this.workDefExpGainRate * numCycles;
|
||||
const dexExpGain = this.workDexExpGainRate * numCycles;
|
||||
const agiExpGain = this.workAgiExpGainRate * numCycles;
|
||||
const chaExpGain = this.workChaExpGainRate * numCycles;
|
||||
const moneyGain = (this.workMoneyGainRate - this.workMoneyLossRate) * numCycles;
|
||||
|
||||
this.gainHackingExp(hackExpGain);
|
||||
this.gainStrengthExp(strExpGain);
|
||||
@ -649,6 +653,7 @@ PlayerObject.prototype.processWorkEarnings = function(numCycles=1) {
|
||||
this.gainDexterityExp(dexExpGain);
|
||||
this.gainAgilityExp(agiExpGain);
|
||||
this.gainCharismaExp(chaExpGain);
|
||||
this.gainMoney(moneyGain);
|
||||
this.workHackExpGained += hackExpGain;
|
||||
this.workStrExpGained += strExpGain;
|
||||
this.workDefExpGained += defExpGain;
|
||||
@ -709,13 +714,13 @@ PlayerObject.prototype.work = function(numCycles) {
|
||||
|
||||
var comp = Companies[this.companyName], companyRep = "0";
|
||||
if (comp == null || !(comp instanceof Company)) {
|
||||
console.log("ERROR: Could not find Company: " + this.companyName);
|
||||
console.error(`Could not find Company: ${this.companyName}`);
|
||||
} else {
|
||||
companyRep = comp.playerReputation;
|
||||
}
|
||||
|
||||
var txt = document.getElementById("work-in-progress-text");
|
||||
txt.innerHTML = "You are currently working as a " + this.companyPosition.positionName +
|
||||
txt.innerHTML = "You are currently working as a " + this.companyPosition +
|
||||
" at " + this.companyName + " (Current Company Reputation: " +
|
||||
numeralWrapper.format(companyRep, '0,0') + ")<br><br>" +
|
||||
"You have been working for " + convertTimeMsToTimeElapsedString(this.timeWorked) + "<br><br>" +
|
||||
@ -741,8 +746,6 @@ PlayerObject.prototype.finishWork = function(cancelled, sing=false) {
|
||||
var company = Companies[this.companyName];
|
||||
company.playerReputation += (this.workRepGained);
|
||||
|
||||
this.gainMoney(this.workMoneyGained);
|
||||
|
||||
this.updateSkillLevels();
|
||||
|
||||
var txt = "You earned a total of: <br>" +
|
||||
@ -837,7 +840,7 @@ PlayerObject.prototype.workPartTime = function(numCycles) {
|
||||
}
|
||||
|
||||
var txt = document.getElementById("work-in-progress-text");
|
||||
txt.innerHTML = "You are currently working as a " + this.companyPosition.positionName +
|
||||
txt.innerHTML = "You are currently working as a " + this.companyPosition +
|
||||
" at " + Player.companyName + " (Current Company Reputation: " +
|
||||
numeralWrapper.format(companyRep, '0,0') + ")<br><br>" +
|
||||
"You have been working for " + convertTimeMsToTimeElapsedString(this.timeWorked) + "<br><br>" +
|
||||
@ -859,8 +862,6 @@ PlayerObject.prototype.finishWorkPartTime = function(sing=false) {
|
||||
var company = Companies[this.companyName];
|
||||
company.playerReputation += (this.workRepGained);
|
||||
|
||||
this.gainMoney(this.workMoneyGained);
|
||||
|
||||
this.updateSkillLevels();
|
||||
|
||||
var txt = "You earned a total of: <br>" +
|
||||
@ -1028,8 +1029,6 @@ PlayerObject.prototype.finishFactionWork = function(cancelled, sing=false) {
|
||||
var faction = Factions[this.currentWorkFactionName];
|
||||
faction.playerReputation += (this.workRepGained);
|
||||
|
||||
this.gainMoney(this.workMoneyGained);
|
||||
|
||||
this.updateSkillLevels();
|
||||
|
||||
var txt = "You worked for your faction " + faction.name + " for a total of " + convertTimeMsToTimeElapsedString(this.timeWorked) + " <br><br> " +
|
||||
@ -1069,70 +1068,126 @@ PlayerObject.prototype.finishFactionWork = function(cancelled, sing=false) {
|
||||
|
||||
//Money gained per game cycle
|
||||
PlayerObject.prototype.getWorkMoneyGain = function() {
|
||||
var bn11Mult = 1;
|
||||
var company = Companies[this.companyName];
|
||||
if (hasBn11SF) {
|
||||
bn11Mult = 1 + (company.favor / 100);
|
||||
// If player has SF-11, calculate salary multiplier from favor
|
||||
let bn11Mult = 1;
|
||||
const company = Companies[this.companyName];
|
||||
if (hasBn11SF) { bn11Mult = 1 + (company.favor / 100); }
|
||||
|
||||
// Get base salary
|
||||
const companyPosition = CompanyPositions[this.companyPosition];
|
||||
if (companyPosition == null) {
|
||||
console.error(`Could not find CompanyPosition object for ${this.companyPosition}. Work salary will be 0`);
|
||||
return 0;
|
||||
}
|
||||
return this.companyPosition.baseSalary * company.salaryMultiplier *
|
||||
this.work_money_mult * BitNodeMultipliers.CompanyWorkMoney * bn11Mult;
|
||||
|
||||
return companyPosition.baseSalary * company.salaryMultiplier * this.work_money_mult * BitNodeMultipliers.CompanyWorkMoney * bn11Mult;
|
||||
}
|
||||
|
||||
//Hack exp gained per game cycle
|
||||
PlayerObject.prototype.getWorkHackExpGain = function() {
|
||||
var company = Companies[this.companyName];
|
||||
return this.companyPosition.hackingExpGain * company.expMultiplier *
|
||||
this.hacking_exp_mult * BitNodeMultipliers.CompanyWorkExpGain;
|
||||
const company = Companies[this.companyName];
|
||||
const companyPosition = CompanyPositions[this.companyPosition];
|
||||
if (company == null || companyPosition == null) {
|
||||
console.error([`Could not find Company object for ${this.companyName}`,
|
||||
`or CompanyPosition object for ${this.companyPosition}.`,
|
||||
`Work hack exp gain will be 0`].join(" "));
|
||||
return 0;
|
||||
}
|
||||
|
||||
return companyPosition.hackingExpGain * company.expMultiplier * this.hacking_exp_mult * BitNodeMultipliers.CompanyWorkExpGain;
|
||||
}
|
||||
|
||||
//Str exp gained per game cycle
|
||||
PlayerObject.prototype.getWorkStrExpGain = function() {
|
||||
var company = Companies[this.companyName];
|
||||
return this.companyPosition.strengthExpGain * company.expMultiplier *
|
||||
this.strength_exp_mult * BitNodeMultipliers.CompanyWorkExpGain;
|
||||
const company = Companies[this.companyName];
|
||||
const companyPosition = CompanyPositions[this.companyPosition];
|
||||
if (company == null || companyPosition == null) {
|
||||
console.error([`Could not find Company object for ${this.companyName}`,
|
||||
`or CompanyPosition object for ${this.companyPosition}.`,
|
||||
`Work str exp gain will be 0`].join(" "));
|
||||
return 0;
|
||||
}
|
||||
|
||||
return companyPosition.strengthExpGain * company.expMultiplier * this.strength_exp_mult * BitNodeMultipliers.CompanyWorkExpGain;
|
||||
}
|
||||
|
||||
//Def exp gained per game cycle
|
||||
PlayerObject.prototype.getWorkDefExpGain = function() {
|
||||
var company = Companies[this.companyName];
|
||||
return this.companyPosition.defenseExpGain * company.expMultiplier *
|
||||
this.defense_exp_mult * BitNodeMultipliers.CompanyWorkExpGain;
|
||||
const company = Companies[this.companyName];
|
||||
const companyPosition = CompanyPositions[this.companyPosition];
|
||||
if (company == null || companyPosition == null) {
|
||||
console.error([`Could not find Company object for ${this.companyName}`,
|
||||
`or CompanyPosition object for ${this.companyPosition}.`,
|
||||
`Work def exp gain will be 0`].join(" "));
|
||||
return 0;
|
||||
}
|
||||
|
||||
return companyPosition.defenseExpGain * company.expMultiplier * this.defense_exp_mult * BitNodeMultipliers.CompanyWorkExpGain;
|
||||
}
|
||||
|
||||
//Dex exp gained per game cycle
|
||||
PlayerObject.prototype.getWorkDexExpGain = function() {
|
||||
var company = Companies[this.companyName];
|
||||
return this.companyPosition.dexterityExpGain * company.expMultiplier *
|
||||
this.dexterity_exp_mult * BitNodeMultipliers.CompanyWorkExpGain;
|
||||
const company = Companies[this.companyName];
|
||||
const companyPosition = CompanyPositions[this.companyPosition];
|
||||
if (company == null || companyPosition == null) {
|
||||
console.error([`Could not find Company object for ${this.companyName}`,
|
||||
`or CompanyPosition object for ${this.companyPosition}.`,
|
||||
`Work dex exp gain will be 0`].join(" "));
|
||||
return 0;
|
||||
}
|
||||
|
||||
return companyPosition.dexterityExpGain * company.expMultiplier * this.dexterity_exp_mult * BitNodeMultipliers.CompanyWorkExpGain;
|
||||
}
|
||||
|
||||
//Agi exp gained per game cycle
|
||||
PlayerObject.prototype.getWorkAgiExpGain = function() {
|
||||
var company = Companies[this.companyName];
|
||||
return this.companyPosition.agilityExpGain * company.expMultiplier *
|
||||
this.agility_exp_mult * BitNodeMultipliers.CompanyWorkExpGain;
|
||||
const company = Companies[this.companyName];
|
||||
const companyPosition = CompanyPositions[this.companyPosition];
|
||||
if (company == null || companyPosition == null) {
|
||||
console.error([`Could not find Company object for ${this.companyName}`,
|
||||
`or CompanyPosition object for ${this.companyPosition}.`,
|
||||
`Work agi exp gain will be 0`].join(" "));
|
||||
return 0;
|
||||
}
|
||||
|
||||
return companyPosition.agilityExpGain * company.expMultiplier * this.agility_exp_mult * BitNodeMultipliers.CompanyWorkExpGain;
|
||||
}
|
||||
|
||||
//Charisma exp gained per game cycle
|
||||
PlayerObject.prototype.getWorkChaExpGain = function() {
|
||||
var company = Companies[this.companyName];
|
||||
return this.companyPosition.charismaExpGain * company.expMultiplier *
|
||||
this.charisma_exp_mult * BitNodeMultipliers.CompanyWorkExpGain;
|
||||
const company = Companies[this.companyName];
|
||||
const companyPosition = CompanyPositions[this.companyPosition];
|
||||
if (company == null || companyPosition == null) {
|
||||
console.error([`Could not find Company object for ${this.companyName}`,
|
||||
`or CompanyPosition object for ${this.companyPosition}.`,
|
||||
`Work cha exp gain will be 0`].join(" "));
|
||||
return 0;
|
||||
}
|
||||
|
||||
return companyPosition.charismaExpGain * company.expMultiplier * this.charisma_exp_mult * BitNodeMultipliers.CompanyWorkExpGain;
|
||||
}
|
||||
|
||||
//Reputation gained per game cycle
|
||||
PlayerObject.prototype.getWorkRepGain = function() {
|
||||
var company = Companies[this.companyName];
|
||||
var jobPerformance = this.companyPosition.calculateJobPerformance(this.hacking_skill, this.strength,
|
||||
this.defense, this.dexterity,
|
||||
this.agility, this.charisma);
|
||||
const company = Companies[this.companyName];
|
||||
const companyPosition = CompanyPositions[this.companyPosition];
|
||||
if (company == null || companyPosition == null) {
|
||||
console.error([`Could not find Company object for ${this.companyName}`,
|
||||
`or CompanyPosition object for ${this.companyPosition}.`,
|
||||
`Work rep gain will be 0`].join(" "));
|
||||
return 0;
|
||||
}
|
||||
|
||||
var jobPerformance = companyPosition.calculateJobPerformance(this.hacking_skill, this.strength,
|
||||
this.defense, this.dexterity,
|
||||
this.agility, this.charisma);
|
||||
|
||||
//Intelligence provides a flat bonus to job performance
|
||||
jobPerformance += (this.intelligence / CONSTANTS.MaxSkillLevel);
|
||||
|
||||
//Update reputation gain rate to account for company favor
|
||||
var favorMult = 1 + (company.favor / 100);
|
||||
if (isNaN(favorMult)) {favorMult = 1;}
|
||||
if (isNaN(favorMult)) { favorMult = 1; }
|
||||
return jobPerformance * this.company_rep_mult * favorMult;
|
||||
}
|
||||
|
||||
@ -1365,7 +1420,6 @@ PlayerObject.prototype.finishClass = function(sing=false) {
|
||||
if (this.workMoneyGained > 0) {
|
||||
throw new Error("ERR: Somehow gained money while taking class");
|
||||
}
|
||||
this.loseMoney(this.workMoneyGained * -1);
|
||||
|
||||
this.updateSkillLevels();
|
||||
var txt = "After " + this.className + " for " + convertTimeMsToTimeElapsedString(this.timeWorked) + ", <br>" +
|
||||
@ -1611,20 +1665,25 @@ PlayerObject.prototype.hospitalize = function() {
|
||||
//The 'sing' argument designates whether or not this is being called from
|
||||
//the applyToCompany() Netscript Singularity function
|
||||
PlayerObject.prototype.applyForJob = function(entryPosType, sing=false) {
|
||||
var currCompany = "";
|
||||
if (this.companyName != "") {
|
||||
// Get current company and job
|
||||
let currCompany = null;
|
||||
if (this.companyName !== "") {
|
||||
currCompany = Companies[this.companyName];
|
||||
}
|
||||
var currPositionName = "";
|
||||
if (this.companyPosition != "") {
|
||||
currPositionName = this.companyPosition.positionName;
|
||||
}
|
||||
var company = Companies[this.location]; //Company being applied to
|
||||
if (sing && !(company instanceof Company)) {
|
||||
return "ERROR: Invalid company name: " + this.location + ". applyToCompany() failed";
|
||||
const currPositionName = this.companyPosition;
|
||||
|
||||
// Get company that's being applied to
|
||||
const company = Companies[this.location]; //Company being applied to
|
||||
if (!(company instanceof Company)) {
|
||||
if (sing) {
|
||||
return "ERROR: Invalid company name: " + this.location + ". applyToCompany() failed";
|
||||
} else {
|
||||
console.error(`Could not find company that matches the location: ${this.location}. Player.applyToCompany() failed`);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
var pos = entryPosType;
|
||||
let pos = entryPosType;
|
||||
|
||||
if (!this.isQualified(company, pos)) {
|
||||
var reqText = getJobRequirementText(company, pos);
|
||||
@ -1634,8 +1693,7 @@ PlayerObject.prototype.applyForJob = function(entryPosType, sing=false) {
|
||||
}
|
||||
|
||||
while (true) {
|
||||
if (Engine.Debug) {console.log("Determining qualification for next Company Position");}
|
||||
var newPos = getNextCompanyPosition(pos);
|
||||
let newPos = getNextCompanyPosition(pos);
|
||||
if (newPos == null) {break;}
|
||||
|
||||
//Check if this company has this position
|
||||
@ -1651,9 +1709,8 @@ PlayerObject.prototype.applyForJob = function(entryPosType, sing=false) {
|
||||
}
|
||||
|
||||
//Check if the determined job is the same as the player's current job
|
||||
if (currCompany != "") {
|
||||
if (currCompany.companyName == company.companyName &&
|
||||
pos.positionName == currPositionName) {
|
||||
if (currCompany != null) {
|
||||
if (currCompany.name == company.name && pos.name == currPositionName) {
|
||||
var nextPos = getNextCompanyPosition(pos);
|
||||
if (nextPos == null) {
|
||||
if (sing) {return false;}
|
||||
@ -1672,31 +1729,30 @@ PlayerObject.prototype.applyForJob = function(entryPosType, sing=false) {
|
||||
|
||||
|
||||
//Lose reputation from a Company if you are leaving it for another job
|
||||
var leaveCompany = false;
|
||||
var oldCompanyName = "";
|
||||
if (currCompany != "") {
|
||||
if (currCompany.companyName != company.companyName) {
|
||||
let leaveCompany = false;
|
||||
let oldCompanyName = "";
|
||||
if (currCompany != null) {
|
||||
if (currCompany.name != company.name) {
|
||||
leaveCompany = true;
|
||||
oldCompanyName = currCompany.companyName;
|
||||
company.playerReputation -= 1000;
|
||||
if (company.playerReputation < 0) {company.playerReputation = 0;}
|
||||
oldCompanyName = currCompany.name;
|
||||
currCompany.playerReputation -= 1000;
|
||||
if (currCompany.playerReputation < 0) { currCompany.playerReputation = 0; }
|
||||
}
|
||||
}
|
||||
|
||||
this.companyName = company.companyName;
|
||||
this.companyPosition = pos;
|
||||
this.companyName = company.name;
|
||||
this.companyPosition = pos.name;
|
||||
|
||||
document.getElementById("world-menu-header").click();
|
||||
document.getElementById("world-menu-header").click();
|
||||
|
||||
if (leaveCompany) {
|
||||
if (sing) {return true;}
|
||||
dialogBoxCreate("Congratulations! You were offered a new job at " + this.companyName + " as a " +
|
||||
pos.positionName + "!<br>" +
|
||||
"You lost 1000 reputation at your old company " + oldCompanyName + " because you left.");
|
||||
if (sing) { return true; }
|
||||
dialogBoxCreate([`Congratulations! You were offered a new job at ${this.companyName} as a ${pos.name}!`,
|
||||
`You lost 1000 reputation at your old company ${oldCompanyName} because you left.`].join("<br>"));
|
||||
} else {
|
||||
if (sing) {return true;}
|
||||
dialogBoxCreate("Congratulations! You were offered a new job at " + this.companyName + " as a " + pos.positionName + "!");
|
||||
if (sing) { return true; }
|
||||
dialogBoxCreate("Congratulations! You were offered a new job at " + this.companyName + " as a " + pos.name + "!");
|
||||
}
|
||||
|
||||
Engine.loadLocationContent();
|
||||
@ -1705,51 +1761,51 @@ PlayerObject.prototype.applyForJob = function(entryPosType, sing=false) {
|
||||
//Returns your next position at a company given the field (software, business, etc.)
|
||||
PlayerObject.prototype.getNextCompanyPosition = function(company, entryPosType) {
|
||||
var currCompany = null;
|
||||
if (this.companyName != "") {
|
||||
if (this.companyName !== "") {
|
||||
currCompany = Companies[this.companyName];
|
||||
}
|
||||
|
||||
//Not employed at this company, so return the entry position
|
||||
if (currCompany == null || (currCompany.companyName != company.companyName)) {
|
||||
if (currCompany == null || (currCompany.name != company.name)) {
|
||||
return entryPosType;
|
||||
}
|
||||
|
||||
//If the entry pos type and the player's current position have the same type,
|
||||
//return the player's "nextCompanyPosition". Otherwise return the entryposType
|
||||
//Employed at this company, so just return the next position if it exists.
|
||||
if ((this.companyPosition.isSoftwareJob() && entryPosType.isSoftwareJob()) ||
|
||||
(this.companyPosition.isITJob() && entryPosType.isITJob()) ||
|
||||
(this.companyPosition.isBusinessJob() && entryPosType.isBusinessJob()) ||
|
||||
(this.companyPosition.isSecurityEngineerJob() && entryPosType.isSecurityEngineerJob()) ||
|
||||
(this.companyPosition.isNetworkEngineerJob() && entryPosType.isNetworkEngineerJob()) ||
|
||||
(this.companyPosition.isSecurityJob() && entryPosType.isSecurityJob()) ||
|
||||
(this.companyPosition.isAgentJob() && entryPosType.isAgentJob()) ||
|
||||
(this.companyPosition.isSoftwareConsultantJob() && entryPosType.isSoftwareConsultantJob()) ||
|
||||
(this.companyPosition.isBusinessConsultantJob() && entryPosType.isBusinessConsultantJob()) ||
|
||||
(this.companyPosition.isPartTimeJob() && entryPosType.isPartTimeJob())) {
|
||||
return getNextCompanyPosition(this.companyPosition);
|
||||
const currentPosition = CompanyPositions[this.companyPosition];
|
||||
if ((currentPosition.isSoftwareJob() && entryPosType.isSoftwareJob()) ||
|
||||
(currentPosition.isITJob() && entryPosType.isITJob()) ||
|
||||
(currentPosition.isBusinessJob() && entryPosType.isBusinessJob()) ||
|
||||
(currentPosition.isSecurityEngineerJob() && entryPosType.isSecurityEngineerJob()) ||
|
||||
(currentPosition.isNetworkEngineerJob() && entryPosType.isNetworkEngineerJob()) ||
|
||||
(currentPosition.isSecurityJob() && entryPosType.isSecurityJob()) ||
|
||||
(currentPosition.isAgentJob() && entryPosType.isAgentJob()) ||
|
||||
(currentPosition.isSoftwareConsultantJob() && entryPosType.isSoftwareConsultantJob()) ||
|
||||
(currentPosition.isBusinessConsultantJob() && entryPosType.isBusinessConsultantJob()) ||
|
||||
(currentPosition.isPartTimeJob() && entryPosType.isPartTimeJob())) {
|
||||
return getNextCompanyPosition(currentPosition);
|
||||
}
|
||||
|
||||
|
||||
return entryPosType;
|
||||
}
|
||||
|
||||
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) {
|
||||
return this.applyForJob(CompanyPositions.SoftwareConsultant, sing);
|
||||
return this.applyForJob(CompanyPositions[posNames.SoftwareConsultantCompanyPositions[0]], sing);
|
||||
}
|
||||
|
||||
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) {
|
||||
var company = Companies[this.location]; //Company being applied to
|
||||
if (this.isQualified(company, CompanyPositions.SecurityEngineer)) {
|
||||
return this.applyForJob(CompanyPositions.SecurityEngineer, sing);
|
||||
if (this.isQualified(company, CompanyPositions[posNames.SecurityEngineerCompanyPositions[0]])) {
|
||||
return this.applyForJob(CompanyPositions[posNames.SecurityEngineerCompanyPositions[0]], sing);
|
||||
} else {
|
||||
if (sing) {return false;}
|
||||
dialogBoxCreate("Unforunately, you do not qualify for this position");
|
||||
@ -1758,8 +1814,8 @@ PlayerObject.prototype.applyForSecurityEngineerJob = function(sing=false) {
|
||||
|
||||
PlayerObject.prototype.applyForNetworkEngineerJob = function(sing=false) {
|
||||
var company = Companies[this.location]; //Company being applied to
|
||||
if (this.isQualified(company, CompanyPositions.NetworkEngineer)) {
|
||||
return this.applyForJob(CompanyPositions.NetworkEngineer, sing);
|
||||
if (this.isQualified(company, CompanyPositions[posNames.NetworkEngineerCompanyPositions[0]])) {
|
||||
return this.applyForJob(CompanyPositions[posNames.NetworkEngineerCompanyPositions[0]], sing);
|
||||
} else {
|
||||
if (sing) {return false;}
|
||||
dialogBoxCreate("Unforunately, you do not qualify for this position");
|
||||
@ -1767,22 +1823,23 @@ PlayerObject.prototype.applyForNetworkEngineerJob = 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) {
|
||||
return this.applyForJob(CompanyPositions.BusinessConsultant, sing);
|
||||
return this.applyForJob(CompanyPositions[posNames.BusinessConsultantCompanyPositions[0]], sing);
|
||||
}
|
||||
|
||||
PlayerObject.prototype.applyForSecurityJob = function(sing=false) {
|
||||
//TODO If case for POlice departments
|
||||
return this.applyForJob(CompanyPositions.SecurityGuard, sing);
|
||||
// TODO Police Jobs
|
||||
// Indexing starts at 2 because 0 is for police officer
|
||||
return this.applyForJob(CompanyPositions[posNames.SecurityCompanyPositions[2]], sing);
|
||||
}
|
||||
|
||||
PlayerObject.prototype.applyForAgentJob = function(sing=false) {
|
||||
var company = Companies[this.location]; //Company being applied to
|
||||
if (this.isQualified(company, CompanyPositions.FieldAgent)) {
|
||||
return this.applyForJob(CompanyPositions.FieldAgent, sing);
|
||||
if (this.isQualified(company, CompanyPositions[posNames.AgentCompanyPositions[0]])) {
|
||||
return this.applyForJob(CompanyPositions[posNames.AgentCompanyPositions[0]], sing);
|
||||
} else {
|
||||
if (sing) {return false;}
|
||||
dialogBoxCreate("Unforunately, you do not qualify for this position");
|
||||
@ -1791,9 +1848,9 @@ PlayerObject.prototype.applyForAgentJob = function(sing=false) {
|
||||
|
||||
PlayerObject.prototype.applyForEmployeeJob = function(sing=false) {
|
||||
var company = Companies[this.location]; //Company being applied to
|
||||
if (this.isQualified(company, CompanyPositions.Employee)) {
|
||||
this.companyName = company.companyName;
|
||||
this.companyPosition = CompanyPositions.Employee;
|
||||
if (this.isQualified(company, CompanyPositions[posNames.MiscCompanyPositions[1]])) {
|
||||
this.companyName = company.name;
|
||||
this.companyPosition = posNames.MiscCompanyPositions[1];
|
||||
document.getElementById("world-menu-header").click();
|
||||
document.getElementById("world-menu-header").click();
|
||||
if (sing) {return true;}
|
||||
@ -1807,9 +1864,9 @@ PlayerObject.prototype.applyForEmployeeJob = function(sing=false) {
|
||||
|
||||
PlayerObject.prototype.applyForPartTimeEmployeeJob = function(sing=false) {
|
||||
var company = Companies[this.location]; //Company being applied to
|
||||
if (this.isQualified(company, CompanyPositions.PartTimeEmployee)) {
|
||||
this.companyName = company.companyName;
|
||||
this.companyPosition = CompanyPositions.PartTimeEmployee;
|
||||
if (this.isQualified(company, CompanyPositions[posNames.PartTimeCompanyPositions[1]])) {
|
||||
this.companyName = company.name;
|
||||
this.companyPosition = posNames.PartTimeCompanyPositions[1];
|
||||
document.getElementById("world-menu-header").click();
|
||||
document.getElementById("world-menu-header").click();
|
||||
if (sing) {return true;}
|
||||
@ -1823,9 +1880,9 @@ PlayerObject.prototype.applyForPartTimeEmployeeJob = function(sing=false) {
|
||||
|
||||
PlayerObject.prototype.applyForWaiterJob = function(sing=false) {
|
||||
var company = Companies[this.location]; //Company being applied to
|
||||
if (this.isQualified(company, CompanyPositions.Waiter)) {
|
||||
this.companyName = company.companyName;
|
||||
this.companyPosition = CompanyPositions.Waiter;
|
||||
if (this.isQualified(company, CompanyPositions[posNames.MiscCompanyPositions[0]])) {
|
||||
this.companyName = company.name;
|
||||
this.companyPosition = posNames.MiscCompanyPositions[0];
|
||||
document.getElementById("world-menu-header").click();
|
||||
document.getElementById("world-menu-header").click();
|
||||
if (sing) {return true;}
|
||||
@ -1839,9 +1896,9 @@ PlayerObject.prototype.applyForWaiterJob = function(sing=false) {
|
||||
|
||||
PlayerObject.prototype.applyForPartTimeWaiterJob = function(sing=false) {
|
||||
var company = Companies[this.location]; //Company being applied to
|
||||
if (this.isQualified(company, CompanyPositions.PartTimeWaiter)) {
|
||||
this.companyName = company.companyName;
|
||||
this.companyPosition = CompanyPositions.PartTimeWaiter;
|
||||
if (this.isQualified(company, CompanyPositions[posNames.PartTimeCompanyPositions[0]])) {
|
||||
this.companyName = company.name;
|
||||
this.companyPosition = posNames.PartTimeCompanyPositions[0];
|
||||
document.getElementById("world-menu-header").click();
|
||||
document.getElementById("world-menu-header").click();
|
||||
if (sing) {return true;}
|
||||
@ -2156,10 +2213,12 @@ PlayerObject.prototype.checkForFactionInvitations = function() {
|
||||
|
||||
//Silhouette
|
||||
var silhouetteFac = Factions["Silhouette"];
|
||||
const companyPosition = CompanyPositions[this.companyPosition];
|
||||
if (!silhouetteFac.isBanned && !silhouetteFac.isMember && !silhouetteFac.alreadyInvited &&
|
||||
(this.companyPosition.positionName == CompanyPositions.CTO.positionName ||
|
||||
this.companyPosition.positionName == CompanyPositions.CFO.positionName ||
|
||||
this.companyPosition.positionName == CompanyPositions.CEO.positionName) &&
|
||||
companyPosition != null &&
|
||||
(companyPosition.name == "Chief Technology Officer" ||
|
||||
companyPosition.name == "Chief Financial Officer" ||
|
||||
companyPosition.name == "Chief Executive Officer") &&
|
||||
this.money.gte(15000000) && this.karma <= -22) {
|
||||
invitedFactions.push(silhouetteFac);
|
||||
}
|
||||
@ -2307,7 +2366,7 @@ PlayerObject.prototype.gainCodingContractReward = function(reward, difficulty=1)
|
||||
break;
|
||||
case CodingContractRewardType.Money:
|
||||
default:
|
||||
var moneyGain = CONSTANTS.CodingContractBaseMoneyGain * difficulty;
|
||||
var moneyGain = CONSTANTS.CodingContractBaseMoneyGain * difficulty * BitNodeMultipliers.CodingContractMoney;
|
||||
this.gainMoney(moneyGain);
|
||||
return `Gained ${numeralWrapper.format(moneyGain, '$0.000a')}`;
|
||||
break;
|
||||
|
@ -4,7 +4,7 @@ import {Augmentations, augmentationExists,
|
||||
import {initBitNodeMultipliers} from "./BitNode";
|
||||
import {Bladeburner} from "./Bladeburner";
|
||||
import {writeCinematicText} from "./CinematicText";
|
||||
import {Companies, Company, initCompanies} from "./Company";
|
||||
import {Companies, initCompanies} from "./Company/Companies";
|
||||
import {Programs} from "./CreateProgram";
|
||||
import {Engine} from "./engine";
|
||||
import {Factions, Faction, initFactions,
|
||||
|
@ -1,7 +1,7 @@
|
||||
import {loadAliases, loadGlobalAliases,
|
||||
Aliases, GlobalAliases} from "./Alias";
|
||||
import {loadCompanies, Companies,
|
||||
CompanyPositions} from "./Company";
|
||||
import {Companies, loadCompanies} from "./Company/Companies";
|
||||
import {CompanyPosition} from "./Company/CompanyPosition";
|
||||
import {CONSTANTS} from "./Constants";
|
||||
import {Engine} from "./engine";
|
||||
import {loadFactions, Factions,
|
||||
@ -110,6 +110,41 @@ BitburnerSaveObject.prototype.saveGame = function(db) {
|
||||
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.name === 0 || company.name === "") && 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) {
|
||||
if (saveString === "" || saveString == null || saveString === undefined) {
|
||||
if (!window.localStorage.getItem("bitburnerSave")) {
|
||||
@ -187,28 +222,8 @@ function loadGame(saveString) {
|
||||
if (saveObj.hasOwnProperty("VersionSave")) {
|
||||
try {
|
||||
var ver = JSON.parse(saveObj.VersionSave, Reviver);
|
||||
if (Player.bitNodeN == null || Player.bitNodeN === 0) {
|
||||
Player.setBitNodeNumber(1);
|
||||
}
|
||||
if (ver.startsWith("0.27.") || ver.startsWith("0.28.")) {
|
||||
console.log("Evaluating changes needed for version compatibility");
|
||||
if (Player.augmentations.length > 0 || Player.queuedAugmentations.length > 0 ||
|
||||
Player.sourceFiles.length > 0) {
|
||||
//If you have already purchased an Aug...you are far enough in the game
|
||||
//that everything should be available
|
||||
Player.firstFacInvRecvd = true;
|
||||
Player.firstAugPurchased = true;
|
||||
Player.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;
|
||||
}
|
||||
}
|
||||
}
|
||||
evaluateVersionCompatibility(ver);
|
||||
|
||||
if (window.location.href.toLowerCase().includes("bitburner-beta")) {
|
||||
//Beta branch, always show changes
|
||||
createBetaUpdateText();
|
||||
@ -306,23 +321,11 @@ function loadImportedGame(saveObj, saveString) {
|
||||
if (tempSaveObj.hasOwnProperty("VersionSave")) {
|
||||
try {
|
||||
var ver = JSON.parse(tempSaveObj.VersionSave, Reviver);
|
||||
if (ver.startsWith("0.27.") || ver.startsWith("0.28.")) {
|
||||
if (tempPlayer.bitNodeN == null || tempPlayer.bitNodeN == 0) {
|
||||
tempPlayer.bitNodeN = 1;
|
||||
}
|
||||
if (tempPlayer.sourceFiles == null) {
|
||||
tempPlayer.sourceFiles = [];
|
||||
}
|
||||
}
|
||||
if (ver != CONSTANTS.Version) {
|
||||
//createNewUpdateText();
|
||||
}
|
||||
evaluateVersionCompatibility(ver);
|
||||
} catch(e) {
|
||||
console.log("Parsing Version save failed: " + e);
|
||||
//createNewUpdateText();
|
||||
console.error("Parsing Version save failed: " + e);
|
||||
}
|
||||
} else {
|
||||
//createNewUpdateText();
|
||||
}
|
||||
if (tempPlayer.bitNodeN == 2 && tempPlayer.inGang() && tempSaveObj.hasOwnProperty("AllGangsSave")) {
|
||||
try {
|
||||
@ -401,29 +404,8 @@ function loadImportedGame(saveObj, saveString) {
|
||||
if (saveObj.hasOwnProperty("VersionSave")) {
|
||||
try {
|
||||
var ver = JSON.parse(saveObj.VersionSave, Reviver);
|
||||
if (Player.bitNodeN == null || Player.bitNodeN == 0) {
|
||||
Player.setBitNodeNumber(1);
|
||||
evaluateVersionCompatibility(ver);
|
||||
|
||||
}
|
||||
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) {
|
||||
createNewUpdateText();
|
||||
}
|
||||
@ -459,7 +441,6 @@ function loadImportedGame(saveObj, saveString) {
|
||||
console.log("Importing game");
|
||||
Engine.setDisplayElements(); //Sets variables for important DOM elements
|
||||
Engine.init(); //Initialize buttons, work, etc.
|
||||
CompanyPositions.init();
|
||||
|
||||
//Calculate the number of cycles have elapsed while offline
|
||||
Engine._lastUpdate = new Date().getTime();
|
||||
|
@ -466,7 +466,7 @@ async function parseOnlyRamCalculate(server, code, workerScript) {
|
||||
const nextModule = parseQueue.shift();
|
||||
|
||||
let code;
|
||||
if (nextModule.startsWith("https://")) {
|
||||
if (nextModule.startsWith("https://") || nextModule.startsWith("http://")) {
|
||||
try {
|
||||
const module = await eval('import(nextModule)');
|
||||
code = "";
|
||||
|
@ -206,7 +206,7 @@ Server.fromJSON = function(value) {
|
||||
|
||||
Reviver.constructors.Server = Server;
|
||||
|
||||
function initForeignServers() {
|
||||
export function initForeignServers() {
|
||||
/* Create a randomized network for all the foreign servers */
|
||||
//Groupings for creating a randomized network
|
||||
const networkLayers = [];
|
||||
@ -287,7 +287,9 @@ function initForeignServers() {
|
||||
}
|
||||
}
|
||||
|
||||
function numCycleForGrowth(server, growth) {
|
||||
// Returns the number of cycles needed to grow the specified server by the
|
||||
// specified amount. 'growth' parameter is in decimal form, not percentage
|
||||
export function numCycleForGrowth(server, growth) {
|
||||
let ajdGrowthRate = 1 + (CONSTANTS.ServerBaseGrowthRate - 1) / server.hackDifficulty;
|
||||
if(ajdGrowthRate > CONSTANTS.ServerMaxGrowthRate) {
|
||||
ajdGrowthRate = CONSTANTS.ServerMaxGrowthRate;
|
||||
@ -300,7 +302,7 @@ function numCycleForGrowth(server, growth) {
|
||||
}
|
||||
|
||||
//Applied server growth for a single server. Returns the percentage growth
|
||||
function processSingleServerGrowth(server, numCycles) {
|
||||
export function processSingleServerGrowth(server, numCycles) {
|
||||
//Server growth processed once every 450 game cycles
|
||||
const numServerGrowthCycles = Math.max(Math.floor(numCycles / 450), 0);
|
||||
|
||||
@ -334,7 +336,7 @@ function processSingleServerGrowth(server, numCycles) {
|
||||
}
|
||||
|
||||
// if there was any growth at all, increase security
|
||||
if(oldMoneyAvailable !== server.moneyAvailable) {
|
||||
if (oldMoneyAvailable !== server.moneyAvailable) {
|
||||
//Growing increases server security twice as much as hacking
|
||||
let usedCycles = numCycleForGrowth(server, server.moneyAvailable / oldMoneyAvailable);
|
||||
usedCycles = Math.max(0, usedCycles);
|
||||
@ -343,7 +345,7 @@ function processSingleServerGrowth(server, numCycles) {
|
||||
return server.moneyAvailable / oldMoneyAvailable;
|
||||
}
|
||||
|
||||
function prestigeHomeComputer(homeComp) {
|
||||
export function prestigeHomeComputer(homeComp) {
|
||||
const hasBitflume = homeComp.programs.includes(Programs.BitFlume.name);
|
||||
|
||||
homeComp.programs.length = 0; //Remove programs
|
||||
@ -366,14 +368,14 @@ function prestigeHomeComputer(homeComp) {
|
||||
//List of all servers that exist in the game, indexed by their ip
|
||||
let AllServers = {};
|
||||
|
||||
function prestigeAllServers() {
|
||||
export function prestigeAllServers() {
|
||||
for (var member in AllServers) {
|
||||
delete AllServers[member];
|
||||
}
|
||||
AllServers = {};
|
||||
}
|
||||
|
||||
function loadAllServers(saveString) {
|
||||
export function loadAllServers(saveString) {
|
||||
AllServers = JSON.parse(saveString, Reviver);
|
||||
}
|
||||
|
||||
@ -386,7 +388,7 @@ function SizeOfAllServers() {
|
||||
}
|
||||
|
||||
//Add a server onto the map of all servers in the game
|
||||
function AddToAllServers(server) {
|
||||
export function AddToAllServers(server) {
|
||||
var serverIp = server.ip;
|
||||
if (ipExists(serverIp)) {
|
||||
console.log("IP of server that's being added: " + serverIp);
|
||||
@ -400,7 +402,7 @@ function AddToAllServers(server) {
|
||||
|
||||
//Returns server object with corresponding hostname
|
||||
// Relatively slow, would rather not use this a lot
|
||||
function GetServerByHostname(hostname) {
|
||||
export function GetServerByHostname(hostname) {
|
||||
for (var ip in AllServers) {
|
||||
if (AllServers.hasOwnProperty(ip)) {
|
||||
if (AllServers[ip].hostname == hostname) {
|
||||
@ -412,7 +414,7 @@ function GetServerByHostname(hostname) {
|
||||
}
|
||||
|
||||
//Get server by IP or hostname. Returns null if invalid
|
||||
function getServer(s) {
|
||||
export function getServer(s) {
|
||||
if (!isValidIPAddress(s)) {
|
||||
return GetServerByHostname(s);
|
||||
}
|
||||
@ -459,6 +461,4 @@ Directory.prototype.getPath = function(name) {
|
||||
return res.join("");
|
||||
}
|
||||
|
||||
export {Server, AllServers, getServer, GetServerByHostname, loadAllServers,
|
||||
AddToAllServers, processSingleServerGrowth, initForeignServers,
|
||||
prestigeAllServers, prestigeHomeComputer};
|
||||
export {Server, AllServers};
|
||||
|
@ -403,12 +403,13 @@ function stockMarketCycle() {
|
||||
|
||||
//Returns true if successful, false otherwise
|
||||
function buyStock(stock, shares) {
|
||||
if (stock == null || shares < 0 || isNaN(shares)) {
|
||||
// Validate arguments
|
||||
shares = Math.round(shares);
|
||||
if (shares == 0 || shares < 0) { return false; }
|
||||
if (stock == null || isNaN(shares)) {
|
||||
dialogBoxCreate("Failed to buy stock. This may be a bug, contact developer");
|
||||
return false;
|
||||
}
|
||||
shares = Math.round(shares);
|
||||
if (shares == 0) {return false;}
|
||||
|
||||
var totalPrice = stock.price * shares;
|
||||
if (Player.money.lt(totalPrice + CONSTANTS.StockMarketCommission)) {
|
||||
@ -420,7 +421,7 @@ function buyStock(stock, shares) {
|
||||
var origTotal = stock.playerShares * stock.playerAvgPx;
|
||||
Player.loseMoney(totalPrice + CONSTANTS.StockMarketCommission);
|
||||
var newTotal = origTotal + totalPrice;
|
||||
stock.playerShares += shares;
|
||||
stock.playerShares = Math.round(stock.playerShares + shares);
|
||||
stock.playerAvgPx = newTotal / stock.playerShares;
|
||||
updateStockPlayerPosition(stock);
|
||||
dialogBoxCreate("Bought " + numeralWrapper.format(shares, '0,0') + " shares of " + stock.symbol + " at " +
|
||||
@ -441,7 +442,7 @@ function sellStock(stock, shares) {
|
||||
if (shares === 0) {return false;}
|
||||
var gains = stock.price * shares - CONSTANTS.StockMarketCommission;
|
||||
Player.gainMoney(gains);
|
||||
stock.playerShares -= shares;
|
||||
stock.playerShares = Math.round(stock.playerShares - shares);
|
||||
if (stock.playerShares == 0) {
|
||||
stock.playerAvgPx = 0;
|
||||
}
|
||||
@ -455,7 +456,11 @@ function sellStock(stock, shares) {
|
||||
//Returns true if successful and false otherwise
|
||||
function shortStock(stock, shares, workerScript=null) {
|
||||
var tixApi = (workerScript instanceof WorkerScript);
|
||||
if (stock == null || isNaN(shares) || shares < 0) {
|
||||
|
||||
// Validate arguments
|
||||
shares = Math.round(shares);
|
||||
if (shares === 0 || shares < 0) { return false; }
|
||||
if (stock == null || isNaN(shares)) {
|
||||
if (tixApi) {
|
||||
workerScript.scriptRef.log("ERROR: shortStock() failed because of invalid arguments.");
|
||||
} else {
|
||||
@ -464,8 +469,6 @@ function shortStock(stock, shares, workerScript=null) {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
shares = Math.round(shares);
|
||||
if (shares === 0) {return false;}
|
||||
|
||||
var totalPrice = stock.price * shares;
|
||||
if (Player.money.lt(totalPrice + CONSTANTS.StockMarketCommission)) {
|
||||
@ -484,7 +487,7 @@ function shortStock(stock, shares, workerScript=null) {
|
||||
var origTotal = stock.playerShortShares * stock.playerAvgShortPx;
|
||||
Player.loseMoney(totalPrice + CONSTANTS.StockMarketCommission);
|
||||
var newTotal = origTotal + totalPrice;
|
||||
stock.playerShortShares += shares;
|
||||
stock.playerShortShares = Math.round(stock.playerShortShares + shares);
|
||||
stock.playerAvgShortPx = newTotal / stock.playerShortShares;
|
||||
updateStockPlayerPosition(stock);
|
||||
if (tixApi) {
|
||||
@ -526,7 +529,7 @@ function sellShort(stock, shares, workerScript=null) {
|
||||
Player.scriptProdSinceLastAug += profit;
|
||||
}
|
||||
|
||||
stock.playerShortShares -= shares;
|
||||
stock.playerShortShares = Math.round(stock.playerShortShares - shares);
|
||||
if (stock.playerShortShares === 0) {
|
||||
stock.playerAvgShortPx = 0;
|
||||
}
|
||||
@ -1370,15 +1373,15 @@ function updateStockPlayerPosition(stock) {
|
||||
}
|
||||
|
||||
//Calculate returns
|
||||
var totalCost = stock.playerShares * stock.playerAvgPx,
|
||||
gains = (stock.price - stock.playerAvgPx) * stock.playerShares,
|
||||
percentageGains = gains / totalCost;
|
||||
if (isNaN(percentageGains)) {percentageGains = 0;}
|
||||
const totalCost = stock.playerShares * stock.playerAvgPx;
|
||||
let gains = (stock.price - stock.playerAvgPx) * stock.playerShares;
|
||||
let percentageGains = gains / totalCost;
|
||||
if (isNaN(percentageGains)) { percentageGains = 0; }
|
||||
|
||||
var shortTotalCost = stock.playerShortShares * stock.playerAvgShortPx,
|
||||
shortGains = (stock.playerAvgShortPx - stock.price) * stock.playerShortShares,
|
||||
shortPercentageGains = shortGains/ shortTotalCost;
|
||||
if (isNaN(shortPercentageGains)) {shortPercentageGains = 0;}
|
||||
const shortTotalCost = stock.playerShortShares * stock.playerAvgShortPx;
|
||||
let shortGains = (stock.playerAvgShortPx - stock.price) * stock.playerShortShares;
|
||||
let shortPercentageGains = shortGains/ shortTotalCost;
|
||||
if (isNaN(shortPercentageGains)) { shortPercentageGains = 0; }
|
||||
|
||||
stock.posTxtEl.innerHTML =
|
||||
"<h1 class='tooltip stock-market-position-text'>Long Position: " +
|
||||
|
@ -1090,6 +1090,24 @@ let Terminal = {
|
||||
}
|
||||
}
|
||||
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;
|
||||
case "free":
|
||||
Terminal.executeFreeCommand(commandArray);
|
||||
|
@ -49,56 +49,56 @@ export const gangMemberTasksMetadata: IGangMemberTaskMetadata[] = [
|
||||
isCombat: false,
|
||||
isHacking: true,
|
||||
name: "Ransomware",
|
||||
params: {baseRespect: 0.00005, baseWanted: 0.00001, baseMoney: 1, hackWeight: 100, difficulty: 1},
|
||||
params: {baseRespect: 0.00005, baseWanted: 0.0001, baseMoney: 1, hackWeight: 100, difficulty: 1},
|
||||
},
|
||||
{
|
||||
desc: "Assign this gang member to attempt phishing scams and attacks<br><br>Earns money - Slightly increases respect - Slightly increases wanted level",
|
||||
isCombat: false,
|
||||
isHacking: true,
|
||||
name: "Phishing",
|
||||
params: {baseRespect: 0.00008, baseWanted: 0.001, baseMoney: 2.5, hackWeight: 85, chaWeight: 15, difficulty: 3.5},
|
||||
params: {baseRespect: 0.00008, baseWanted: 0.003, baseMoney: 2.5, hackWeight: 85, chaWeight: 15, difficulty: 3.5},
|
||||
},
|
||||
{
|
||||
desc: "Assign this gang member to attempt identity theft<br><br>Earns money - Increases respect - Increases wanted level",
|
||||
isCombat: false,
|
||||
isHacking: true,
|
||||
name: "Identity Theft",
|
||||
params: {baseRespect: 0.0001, baseWanted: 0.01, baseMoney: 6, hackWeight: 80, chaWeight: 20, difficulty: 5},
|
||||
params: {baseRespect: 0.0001, baseWanted: 0.075, baseMoney: 6, hackWeight: 80, chaWeight: 20, difficulty: 5},
|
||||
},
|
||||
{
|
||||
desc: "Assign this gang member to carry out DDoS attacks<br><br>Increases respect - Increases wanted level",
|
||||
isCombat: false,
|
||||
isHacking: true,
|
||||
name: "DDoS Attacks",
|
||||
params: {baseRespect: 0.0004, baseWanted: 0.05, hackWeight: 100, difficulty: 8},
|
||||
params: {baseRespect: 0.0004, baseWanted: 0.2, hackWeight: 100, difficulty: 8},
|
||||
},
|
||||
{
|
||||
desc: "Assign this gang member to create and distribute malicious viruses<br><br>Increases respect - Increases wanted level",
|
||||
isCombat: false,
|
||||
isHacking: true,
|
||||
name: "Plant Virus",
|
||||
params: {baseRespect: 0.0006, baseWanted: 0.05, hackWeight: 100, difficulty: 12},
|
||||
params: {baseRespect: 0.0006, baseWanted: 0.4, hackWeight: 100, difficulty: 12},
|
||||
},
|
||||
{
|
||||
desc: "Assign this gang member to commit financial fraud and digital counterfeiting<br><br>Earns money - Slightly increases respect - Slightly increases wanted level",
|
||||
isCombat: false,
|
||||
isHacking: true,
|
||||
name: "Fraud & Counterfeiting",
|
||||
params: {baseRespect: 0.0005, baseWanted: 0.1, baseMoney: 15, hackWeight: 80, chaWeight: 20, difficulty: 20},
|
||||
params: {baseRespect: 0.0004, baseWanted: 0.3, baseMoney: 15, hackWeight: 80, chaWeight: 20, difficulty: 20},
|
||||
},
|
||||
{
|
||||
desc: "Assign this gang member to launder money<br><br>Earns money - Increases respect - Increases wanted level",
|
||||
isCombat: false,
|
||||
isHacking: true,
|
||||
name: "Money Laundering",
|
||||
params: {baseRespect: 0.0006, baseWanted: 0.2, baseMoney: 40, hackWeight: 75, chaWeight: 25, difficulty: 25},
|
||||
params: {baseRespect: 0.001, baseWanted: 1.25, baseMoney: 120, hackWeight: 75, chaWeight: 25, difficulty: 25},
|
||||
},
|
||||
{
|
||||
desc: "Assign this gang member to commit acts of cyberterrorism<br><br>Greatly increases respect - Greatly increases wanted level",
|
||||
isCombat: false,
|
||||
isHacking: true,
|
||||
name: "Cyberterrorism",
|
||||
params: {baseRespect: 0.001, baseWanted: 0.5, hackWeight: 80, chaWeight: 20, difficulty: 36},
|
||||
params: {baseRespect: 0.01, baseWanted: 6, hackWeight: 80, chaWeight: 20, difficulty: 36},
|
||||
},
|
||||
{
|
||||
desc: "Assign this gang member to be an ethical hacker for corporations<br><br>Earns money - Lowers wanted level",
|
||||
@ -140,7 +140,7 @@ export const gangMemberTasksMetadata: IGangMemberTaskMetadata[] = [
|
||||
isHacking: false,
|
||||
name: "Strongarm Civilians",
|
||||
params: {
|
||||
baseRespect: 0.00004, baseWanted: 0.0035, baseMoney: 2.5,
|
||||
baseRespect: 0.00004, baseWanted: 0.02, baseMoney: 2.5,
|
||||
hackWeight: 10, strWeight: 25, defWeight: 25, dexWeight: 20, agiWeight: 10, chaWeight: 10,
|
||||
difficulty: 5,
|
||||
territory: {
|
||||
@ -156,7 +156,7 @@ export const gangMemberTasksMetadata: IGangMemberTaskMetadata[] = [
|
||||
isHacking: false,
|
||||
name: "Run a Con",
|
||||
params: {
|
||||
baseRespect: 0.00012, baseWanted: 0.04, baseMoney: 15,
|
||||
baseRespect: 0.00012, baseWanted: 0.05, baseMoney: 15,
|
||||
strWeight: 5, defWeight: 5, agiWeight: 25, dexWeight: 25, chaWeight: 40,
|
||||
difficulty: 14,
|
||||
},
|
||||
@ -167,7 +167,7 @@ export const gangMemberTasksMetadata: IGangMemberTaskMetadata[] = [
|
||||
isHacking: false,
|
||||
name: "Armed Robbery",
|
||||
params: {
|
||||
baseRespect: 0.00014, baseWanted: 0.08, baseMoney: 38,
|
||||
baseRespect: 0.00014, baseWanted: 0.1, baseMoney: 38,
|
||||
hackWeight: 20, strWeight: 15, defWeight: 15, agiWeight: 10, dexWeight: 20, chaWeight: 20,
|
||||
difficulty: 20,
|
||||
},
|
||||
@ -178,7 +178,7 @@ export const gangMemberTasksMetadata: IGangMemberTaskMetadata[] = [
|
||||
isHacking: false,
|
||||
name: "Traffick Illegal Arms",
|
||||
params: {
|
||||
baseRespect: 0.0002, baseWanted: 0.18, baseMoney: 58,
|
||||
baseRespect: 0.0002, baseWanted: 0.24, baseMoney: 58,
|
||||
hackWeight: 15, strWeight: 20, defWeight: 20, dexWeight: 20, chaWeight: 25,
|
||||
difficulty: 32,
|
||||
territory: {
|
||||
@ -194,7 +194,7 @@ export const gangMemberTasksMetadata: IGangMemberTaskMetadata[] = [
|
||||
isHacking: false,
|
||||
name: "Threaten & Blackmail",
|
||||
params: {
|
||||
baseRespect: 0.0002, baseWanted: 0.1, baseMoney: 24,
|
||||
baseRespect: 0.0002, baseWanted: 0.125, baseMoney: 24,
|
||||
hackWeight: 25, strWeight: 25, dexWeight: 25, chaWeight: 25,
|
||||
difficulty: 28,
|
||||
},
|
||||
@ -205,7 +205,7 @@ export const gangMemberTasksMetadata: IGangMemberTaskMetadata[] = [
|
||||
isHacking: false,
|
||||
name: "Human Trafficking",
|
||||
params: {
|
||||
baseRespect: 0.004, baseWanted: 1, baseMoney: 120,
|
||||
baseRespect: 0.004, baseWanted: 1.25, baseMoney: 120,
|
||||
hackWeight: 30, strWeight: 5, defWeight: 5, dexWeight: 30, chaWeight: 30,
|
||||
difficulty: 36,
|
||||
territory: {
|
||||
@ -221,7 +221,7 @@ export const gangMemberTasksMetadata: IGangMemberTaskMetadata[] = [
|
||||
isHacking: false,
|
||||
name: "Terrorism",
|
||||
params: {
|
||||
baseRespect: 0.01, baseWanted: 5,
|
||||
baseRespect: 0.01, baseWanted: 6,
|
||||
hackWeight: 20, strWeight: 20, defWeight: 20, dexWeight: 20, chaWeight: 20,
|
||||
difficulty: 36,
|
||||
territory: {
|
||||
|
@ -34,31 +34,31 @@ export const gangMemberUpgradesMetadata: IGangMemberUpgradeMetadata[] = [
|
||||
},
|
||||
{
|
||||
cost: 50e6,
|
||||
mults: {str: 1.12, def: 1.12, agi: 1.1},
|
||||
mults: {str: 1.12, def: 1.1, agi: 1.1},
|
||||
name: "P90C",
|
||||
upgType: "w",
|
||||
},
|
||||
{
|
||||
cost: 60e6,
|
||||
mults: {str: 1.2, def: 1.2},
|
||||
mults: {str: 1.2, def: 1.15},
|
||||
name: "Steyr AUG",
|
||||
upgType: "w",
|
||||
},
|
||||
{
|
||||
cost: 100e6,
|
||||
mults: {str: 1.25, def: 1.25},
|
||||
mults: {str: 1.25, def: 1.2},
|
||||
name: "AK-47",
|
||||
upgType: "w",
|
||||
},
|
||||
{
|
||||
cost: 150e6,
|
||||
mults: {str: 1.3, def: 1.3},
|
||||
mults: {str: 1.3, def: 1.25},
|
||||
name: "M15A10 Assault Rifle",
|
||||
upgType: "w",
|
||||
},
|
||||
{
|
||||
cost: 225e6,
|
||||
mults: {str: 1.3, dex: 1.3, agi: 1.3},
|
||||
mults: {str: 1.3, dex: 1.25, agi: 1.3},
|
||||
name: "AWM Sniper Rifle",
|
||||
upgType: "w",
|
||||
},
|
||||
@ -117,17 +117,29 @@ export const gangMemberUpgradesMetadata: IGangMemberUpgradeMetadata[] = [
|
||||
upgType: "r",
|
||||
},
|
||||
{
|
||||
cost: 15e6,
|
||||
cost: 25e6,
|
||||
mults: {hack: 1.1},
|
||||
name: "Soulstealer Rootkit",
|
||||
upgType: "r",
|
||||
},
|
||||
{
|
||||
cost: 50e6,
|
||||
cost: 75e6,
|
||||
mults: {hack: 1.15},
|
||||
name: "Demon Rootkit",
|
||||
upgType: "r",
|
||||
},
|
||||
{
|
||||
cost: 40e6,
|
||||
mults: {hack: 1.12},
|
||||
name: "Hmap Node",
|
||||
upgType: "r",
|
||||
},
|
||||
{
|
||||
cost: 75e6,
|
||||
mults: {hack: 1.15},
|
||||
name: "Jack the Ripper",
|
||||
upgType: "r",
|
||||
},
|
||||
{
|
||||
cost: 10e9,
|
||||
mults: {str: 1.3, dex: 1.3},
|
||||
@ -182,6 +194,12 @@ export const gangMemberUpgradesMetadata: IGangMemberUpgradeMetadata[] = [
|
||||
name: "Neuralstimulator",
|
||||
upgType: "g",
|
||||
},
|
||||
{
|
||||
cost: 7.5e9,
|
||||
mults: {hack: 1.1},
|
||||
name: "DataJack",
|
||||
upgType: "g",
|
||||
},
|
||||
{
|
||||
cost: 50e9,
|
||||
mults: {str: 1.7, def: 1.7},
|
||||
|
@ -25,7 +25,8 @@ import {Bladeburner} from "./Bladeburner";
|
||||
import {CharacterOverview} from "./CharacterOverview";
|
||||
import {cinematicTextFlag} from "./CinematicText";
|
||||
import {generateRandomContract} from "./CodingContractGenerator";
|
||||
import {CompanyPositions, initCompanies} from "./Company";
|
||||
import {CompanyPositions} from "./Company/CompanyPositions";
|
||||
import {initCompanies} from "./Company/Companies";
|
||||
import {Corporation} from "./CompanyManagement";
|
||||
import {CONSTANTS} from "./Constants";
|
||||
import {displayCreateProgramContent,
|
||||
@ -338,7 +339,13 @@ const Engine = {
|
||||
loadLocationContent: function() {
|
||||
Engine.hideAllContent();
|
||||
Engine.Display.locationContent.style.display = "block";
|
||||
displayLocationContent();
|
||||
try {
|
||||
displayLocationContent();
|
||||
} catch(e) {
|
||||
exceptionAlert(e);
|
||||
console.error(e);
|
||||
}
|
||||
|
||||
routing.navigateTo(Page.Location);
|
||||
},
|
||||
|
||||
@ -539,8 +546,8 @@ const Engine = {
|
||||
removeChildrenFromElement(Engine.Display.characterInfo);
|
||||
|
||||
var companyPosition = "";
|
||||
if (Player.companyPosition != "") {
|
||||
companyPosition = Player.companyPosition.positionName;
|
||||
if (Player.companyPosition !== "") {
|
||||
companyPosition = Player.companyPosition;
|
||||
}
|
||||
|
||||
var intText = "";
|
||||
@ -1204,7 +1211,6 @@ const Engine = {
|
||||
initSourceFiles();
|
||||
Engine.setDisplayElements(); //Sets variables for important DOM elements
|
||||
Engine.init(); //Initialize buttons, work, etc.
|
||||
CompanyPositions.init();
|
||||
initAugmentations(); //Also calls Player.reapplyAllAugmentations()
|
||||
Player.reapplyAllSourceFiles();
|
||||
initStockSymbols();
|
||||
@ -1312,7 +1318,6 @@ const Engine = {
|
||||
initForeignServers();
|
||||
initCompanies();
|
||||
initFactions();
|
||||
CompanyPositions.init();
|
||||
initAugmentations();
|
||||
initMessages();
|
||||
initStockSymbols();
|
||||
|
@ -32,6 +32,8 @@ class NumeralFormatter {
|
||||
}
|
||||
|
||||
format(n, format) {
|
||||
// numeraljs doesnt properly format numbers that are too big or too small
|
||||
if (Math.abs(n) < 1e-6) { n = 0; }
|
||||
return numeral(n).format(format);
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"baseUrl" : ".",
|
||||
"lib" : ["es2016", "dom"],
|
||||
"module": "commonjs",
|
||||
"target": "es6",
|
||||
|
Loading…
Reference in New Issue
Block a user