2021-09-24 00:47:43 +02:00
|
|
|
import { IPlayer } from "../IPlayer";
|
2021-10-27 19:28:36 +02:00
|
|
|
import { PlayerObject } from "./PlayerObject";
|
2019-05-05 06:03:40 +02:00
|
|
|
import { Augmentations } from "../../Augmentation/Augmentations";
|
|
|
|
import { applyAugmentation } from "../../Augmentation/AugmentationHelpers";
|
|
|
|
import { PlayerOwnedAugmentation } from "../../Augmentation/PlayerOwnedAugmentation";
|
|
|
|
import { AugmentationNames } from "../../Augmentation/data/AugmentationNames";
|
|
|
|
import { BitNodeMultipliers } from "../../BitNode/BitNodeMultipliers";
|
2021-09-25 08:36:49 +02:00
|
|
|
import { CodingContractRewardType, ICodingContractReward } from "../../CodingContracts";
|
2019-05-05 06:03:40 +02:00
|
|
|
import { Company } from "../../Company/Company";
|
|
|
|
import { Companies } from "../../Company/Companies";
|
|
|
|
import { getNextCompanyPositionHelper } from "../../Company/GetNextCompanyPosition";
|
|
|
|
import { getJobRequirementText } from "../../Company/GetJobRequirementText";
|
|
|
|
import { CompanyPositions } from "../../Company/CompanyPositions";
|
2021-09-24 00:47:43 +02:00
|
|
|
import { CompanyPosition } from "../../Company/CompanyPosition";
|
2019-05-05 06:03:40 +02:00
|
|
|
import * as posNames from "../../Company/data/companypositionnames";
|
2021-09-05 01:09:30 +02:00
|
|
|
import { CONSTANTS } from "../../Constants";
|
2019-05-05 06:03:40 +02:00
|
|
|
import { Programs } from "../../Programs/Programs";
|
|
|
|
import { determineCrimeSuccess } from "../../Crime/CrimeHelpers";
|
|
|
|
import { Crimes } from "../../Crime/Crimes";
|
2021-09-24 00:47:43 +02:00
|
|
|
import { Exploit } from "../../Exploits/Exploit";
|
2019-05-05 06:03:40 +02:00
|
|
|
import { Faction } from "../../Faction/Faction";
|
|
|
|
import { Factions } from "../../Faction/Factions";
|
2021-06-16 06:28:20 +02:00
|
|
|
import { resetGangs } from "../../Gang/AllGangs";
|
2019-05-05 06:03:40 +02:00
|
|
|
import { Cities } from "../../Locations/Cities";
|
|
|
|
import { Locations } from "../../Locations/Locations";
|
|
|
|
import { CityName } from "../../Locations/data/CityNames";
|
|
|
|
import { LocationName } from "../../Locations/data/LocationNames";
|
|
|
|
import { Sleeve } from "../../PersonObjects/Sleeve/Sleeve";
|
2021-03-31 06:45:21 +02:00
|
|
|
import { calculateSkill as calculateSkillF } from "../formulas/skill";
|
|
|
|
import { calculateIntelligenceBonus } from "../formulas/intelligence";
|
2021-04-18 17:18:56 +02:00
|
|
|
import {
|
2021-09-05 01:09:30 +02:00
|
|
|
getHackingWorkRepGain,
|
|
|
|
getFactionSecurityWorkRepGain,
|
|
|
|
getFactionFieldWorkRepGain,
|
|
|
|
} from "../formulas/reputation";
|
2021-10-07 22:56:01 +02:00
|
|
|
import { GetServer, AddToAllServers, createUniqueRandomIp } from "../../Server/AllServers";
|
2021-09-24 00:47:43 +02:00
|
|
|
import { Server } from "../../Server/Server";
|
2021-10-07 22:56:01 +02:00
|
|
|
import { safetlyCreateUniqueServer } from "../../Server/ServerHelpers";
|
2021-11-12 03:35:26 +01:00
|
|
|
|
2021-10-07 23:55:49 +02:00
|
|
|
import { SpecialServers } from "../../Server/data/SpecialServers";
|
2019-05-15 05:56:59 +02:00
|
|
|
import { applySourceFile } from "../../SourceFile/applySourceFile";
|
2021-03-09 02:31:34 +01:00
|
|
|
import { applyExploit } from "../../Exploits/applyExploits";
|
2019-05-15 05:56:59 +02:00
|
|
|
import { SourceFiles } from "../../SourceFile/SourceFiles";
|
2019-05-05 06:03:40 +02:00
|
|
|
import { SourceFileFlags } from "../../SourceFile/SourceFileFlags";
|
2019-06-04 07:21:36 +02:00
|
|
|
import { influenceStockThroughCompanyWork } from "../../StockMarket/PlayerInfluencing";
|
2021-04-06 09:50:09 +02:00
|
|
|
import { getHospitalizationCost } from "../../Hospital/Hospital";
|
2021-09-24 00:47:43 +02:00
|
|
|
import { WorkerScript } from "../../Netscript/WorkerScript";
|
2021-10-07 22:04:04 +02:00
|
|
|
import { HacknetServer } from "../../Hacknet/HacknetServer";
|
2019-05-05 06:03:40 +02:00
|
|
|
|
|
|
|
import { numeralWrapper } from "../../ui/numeralFormat";
|
2021-09-24 00:47:43 +02:00
|
|
|
import { IRouter } from "../../ui/Router";
|
2019-05-05 06:03:40 +02:00
|
|
|
import { MoneySourceTracker } from "../../utils/MoneySourceTracker";
|
2021-09-25 20:42:57 +02:00
|
|
|
import { dialogBoxCreate } from "../../ui/React/DialogBox";
|
|
|
|
import { convertTimeMsToTimeElapsedString } from "../../utils/StringHelperFunctions";
|
2019-04-04 02:08:11 +02:00
|
|
|
|
2021-03-31 06:45:21 +02:00
|
|
|
import { Reputation } from "../../ui/React/Reputation";
|
|
|
|
import { Money } from "../../ui/React/Money";
|
|
|
|
|
|
|
|
import React from "react";
|
2021-10-16 03:03:25 +02:00
|
|
|
import { serverMetadata } from "../../Server/data/servers";
|
2021-10-22 22:35:05 +02:00
|
|
|
import { SnackbarEvents } from "../../ui/React/Snackbar";
|
2021-11-12 05:40:48 +01:00
|
|
|
import { calculateClassEarnings } from "../formulas/work";
|
2019-04-04 02:08:11 +02:00
|
|
|
|
2021-09-25 08:36:49 +02:00
|
|
|
export function init(this: IPlayer): void {
|
2021-09-05 01:09:30 +02:00
|
|
|
/* Initialize Player's home computer */
|
2021-09-25 07:26:03 +02:00
|
|
|
const t_homeComp = safetlyCreateUniqueServer({
|
2021-09-05 01:09:30 +02:00
|
|
|
adminRights: true,
|
|
|
|
hostname: "home",
|
|
|
|
ip: createUniqueRandomIp(),
|
|
|
|
isConnectedTo: true,
|
|
|
|
maxRam: 8,
|
|
|
|
organizationName: "Home PC",
|
|
|
|
purchasedByPlayer: true,
|
|
|
|
});
|
2021-10-07 23:55:49 +02:00
|
|
|
this.currentServer = SpecialServers.Home;
|
2021-09-05 01:09:30 +02:00
|
|
|
AddToAllServers(t_homeComp);
|
|
|
|
|
|
|
|
this.getHomeComputer().programs.push(Programs.NukeProgram.name);
|
2019-04-04 02:08:11 +02:00
|
|
|
}
|
|
|
|
|
2021-10-27 19:28:36 +02:00
|
|
|
export function prestigeAugmentation(this: PlayerObject): void {
|
2021-10-07 23:55:49 +02:00
|
|
|
this.currentServer = SpecialServers.Home;
|
2019-04-04 02:08:11 +02:00
|
|
|
|
2021-09-05 01:09:30 +02:00
|
|
|
this.numPeopleKilled = 0;
|
|
|
|
this.karma = 0;
|
2019-04-04 02:08:11 +02:00
|
|
|
|
2021-09-05 01:09:30 +02:00
|
|
|
//Reset stats
|
2021-11-05 22:12:52 +01:00
|
|
|
this.hacking = 1;
|
2019-04-04 02:08:11 +02:00
|
|
|
|
2021-09-05 01:09:30 +02:00
|
|
|
this.strength = 1;
|
|
|
|
this.defense = 1;
|
|
|
|
this.dexterity = 1;
|
|
|
|
this.agility = 1;
|
2019-04-04 02:08:11 +02:00
|
|
|
|
2021-09-05 01:09:30 +02:00
|
|
|
this.charisma = 1;
|
2019-04-04 02:08:11 +02:00
|
|
|
|
2021-09-05 01:09:30 +02:00
|
|
|
this.hacking_exp = 0;
|
|
|
|
this.strength_exp = 0;
|
|
|
|
this.defense_exp = 0;
|
|
|
|
this.dexterity_exp = 0;
|
|
|
|
this.agility_exp = 0;
|
|
|
|
this.charisma_exp = 0;
|
2019-04-04 02:08:11 +02:00
|
|
|
|
2021-11-12 03:35:26 +01:00
|
|
|
this.money = 1000;
|
2019-04-04 02:08:11 +02:00
|
|
|
|
2021-09-05 01:09:30 +02:00
|
|
|
this.city = CityName.Sector12;
|
2021-09-24 00:47:43 +02:00
|
|
|
this.location = LocationName.TravelAgency;
|
2019-04-04 02:08:11 +02:00
|
|
|
|
2021-09-05 01:09:30 +02:00
|
|
|
this.companyName = "";
|
|
|
|
this.jobs = {};
|
2019-04-04 02:08:11 +02:00
|
|
|
|
2021-09-05 01:09:30 +02:00
|
|
|
this.purchasedServers = [];
|
2019-04-04 02:08:11 +02:00
|
|
|
|
2021-09-05 01:09:30 +02:00
|
|
|
this.factions = [];
|
|
|
|
this.factionInvitations = [];
|
2019-04-04 02:08:11 +02:00
|
|
|
|
2021-09-05 01:09:30 +02:00
|
|
|
this.queuedAugmentations = [];
|
2019-04-04 02:08:11 +02:00
|
|
|
|
2021-09-05 01:09:30 +02:00
|
|
|
this.resleeves = [];
|
2019-04-04 02:08:11 +02:00
|
|
|
|
2021-09-24 00:47:43 +02:00
|
|
|
const numSleeves = Math.min(3, SourceFileFlags[10] + (this.bitNodeN === 10 ? 1 : 0)) + this.sleevesFromCovenant;
|
2021-09-05 01:09:30 +02:00
|
|
|
if (this.sleeves.length > numSleeves) this.sleeves.length = numSleeves;
|
|
|
|
for (let i = this.sleeves.length; i < numSleeves; i++) {
|
|
|
|
this.sleeves.push(new Sleeve(this));
|
|
|
|
}
|
2021-09-04 18:15:16 +02:00
|
|
|
|
2021-09-05 01:09:30 +02:00
|
|
|
for (let i = 0; i < this.sleeves.length; ++i) {
|
|
|
|
if (this.sleeves[i] instanceof Sleeve) {
|
|
|
|
if (this.sleeves[i].shock >= 100) {
|
|
|
|
this.sleeves[i].synchronize(this);
|
|
|
|
} else {
|
|
|
|
this.sleeves[i].shockRecovery(this);
|
|
|
|
}
|
2019-04-04 02:08:11 +02:00
|
|
|
}
|
2021-09-05 01:09:30 +02:00
|
|
|
}
|
2019-04-04 02:08:11 +02:00
|
|
|
|
2021-09-05 01:09:30 +02:00
|
|
|
this.isWorking = false;
|
|
|
|
this.currentWorkFactionName = "";
|
|
|
|
this.currentWorkFactionDescription = "";
|
|
|
|
this.createProgramName = "";
|
|
|
|
this.className = "";
|
|
|
|
this.crimeType = "";
|
|
|
|
|
|
|
|
this.workHackExpGainRate = 0;
|
|
|
|
this.workStrExpGainRate = 0;
|
|
|
|
this.workDefExpGainRate = 0;
|
|
|
|
this.workDexExpGainRate = 0;
|
|
|
|
this.workAgiExpGainRate = 0;
|
|
|
|
this.workChaExpGainRate = 0;
|
|
|
|
this.workRepGainRate = 0;
|
|
|
|
this.workMoneyGainRate = 0;
|
|
|
|
|
|
|
|
this.workHackExpGained = 0;
|
|
|
|
this.workStrExpGained = 0;
|
|
|
|
this.workDefExpGained = 0;
|
|
|
|
this.workDexExpGained = 0;
|
|
|
|
this.workAgiExpGained = 0;
|
|
|
|
this.workChaExpGained = 0;
|
|
|
|
this.workRepGained = 0;
|
|
|
|
this.workMoneyGained = 0;
|
|
|
|
|
|
|
|
this.timeWorked = 0;
|
|
|
|
|
|
|
|
this.lastUpdate = new Date().getTime();
|
|
|
|
|
|
|
|
// Statistics Trackers
|
|
|
|
this.playtimeSinceLastAug = 0;
|
|
|
|
this.scriptProdSinceLastAug = 0;
|
|
|
|
this.moneySourceA.reset();
|
|
|
|
|
|
|
|
this.hacknetNodes.length = 0;
|
|
|
|
this.hashManager.prestige();
|
|
|
|
|
2021-09-16 19:41:48 +02:00
|
|
|
// Reapply augs, re-calculate skills and reset HP
|
|
|
|
this.reapplyAllAugmentations(true);
|
2021-09-05 01:09:30 +02:00
|
|
|
this.hp = this.max_hp;
|
2019-04-04 02:08:11 +02:00
|
|
|
}
|
|
|
|
|
2021-09-25 08:36:49 +02:00
|
|
|
export function prestigeSourceFile(this: IPlayer): void {
|
2021-09-05 01:09:30 +02:00
|
|
|
this.prestigeAugmentation();
|
|
|
|
// Duplicate sleeves are reset to level 1 every Bit Node (but the number of sleeves you have persists)
|
|
|
|
for (let i = 0; i < this.sleeves.length; ++i) {
|
2021-09-09 05:47:34 +02:00
|
|
|
if (this.sleeves[i] instanceof Sleeve) {
|
|
|
|
this.sleeves[i].prestige(this);
|
|
|
|
} else {
|
|
|
|
this.sleeves[i] = new Sleeve(this);
|
|
|
|
}
|
2021-09-05 01:09:30 +02:00
|
|
|
}
|
2019-04-04 02:08:11 +02:00
|
|
|
|
2021-09-05 01:09:30 +02:00
|
|
|
if (this.bitNodeN === 10) {
|
|
|
|
for (let i = 0; i < this.sleeves.length; i++) {
|
|
|
|
this.sleeves[i].shock = Math.max(25, this.sleeves[i].shock);
|
|
|
|
this.sleeves[i].sync = Math.max(25, this.sleeves[i].sync);
|
2019-05-14 10:35:37 +02:00
|
|
|
}
|
2021-09-05 01:09:30 +02:00
|
|
|
}
|
2019-05-14 10:35:37 +02:00
|
|
|
|
2021-09-05 01:09:30 +02:00
|
|
|
this.timeWorked = 0;
|
2019-04-04 02:08:11 +02:00
|
|
|
|
2021-09-05 01:09:30 +02:00
|
|
|
// Gang
|
|
|
|
this.gang = null;
|
|
|
|
resetGangs();
|
2019-04-04 02:08:11 +02:00
|
|
|
|
2021-09-05 01:09:30 +02:00
|
|
|
// Reset Stock market
|
|
|
|
this.hasWseAccount = false;
|
|
|
|
this.hasTixApiAccess = false;
|
|
|
|
this.has4SData = false;
|
|
|
|
this.has4SDataTixApi = false;
|
2019-04-04 02:08:11 +02:00
|
|
|
|
2021-09-05 01:09:30 +02:00
|
|
|
// BitNode 3: Corporatocracy
|
2021-09-24 00:47:43 +02:00
|
|
|
this.corporation = null;
|
2019-04-04 02:08:11 +02:00
|
|
|
|
2021-09-05 01:09:30 +02:00
|
|
|
this.moneySourceB.reset();
|
|
|
|
this.playtimeSinceLastBitnode = 0;
|
|
|
|
this.augmentations = [];
|
2019-04-04 02:08:11 +02:00
|
|
|
}
|
|
|
|
|
2021-09-24 00:47:43 +02:00
|
|
|
export function receiveInvite(this: IPlayer, factionName: string): void {
|
2021-09-09 05:47:34 +02:00
|
|
|
if (this.factionInvitations.includes(factionName) || this.factions.includes(factionName)) {
|
2021-09-05 01:09:30 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
this.factionInvitations.push(factionName);
|
2019-04-04 02:08:11 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//Calculates skill level based on experience. The same formula will be used for every skill
|
2021-09-24 00:47:43 +02:00
|
|
|
export function calculateSkill(this: IPlayer, exp: number, mult = 1): number {
|
2021-09-05 01:09:30 +02:00
|
|
|
return calculateSkillF(exp, mult);
|
2019-04-04 02:08:11 +02:00
|
|
|
}
|
|
|
|
|
2021-09-24 00:47:43 +02:00
|
|
|
export function updateSkillLevels(this: IPlayer): void {
|
2021-11-05 22:12:52 +01:00
|
|
|
this.hacking = Math.max(
|
2021-09-05 01:09:30 +02:00
|
|
|
1,
|
2021-09-09 05:47:34 +02:00
|
|
|
Math.floor(this.calculateSkill(this.hacking_exp, this.hacking_mult * BitNodeMultipliers.HackingLevelMultiplier)),
|
2021-09-05 01:09:30 +02:00
|
|
|
);
|
|
|
|
this.strength = Math.max(
|
|
|
|
1,
|
2021-09-09 05:47:34 +02:00
|
|
|
Math.floor(this.calculateSkill(this.strength_exp, this.strength_mult * BitNodeMultipliers.StrengthLevelMultiplier)),
|
2021-09-05 01:09:30 +02:00
|
|
|
);
|
|
|
|
this.defense = Math.max(
|
|
|
|
1,
|
2021-09-09 05:47:34 +02:00
|
|
|
Math.floor(this.calculateSkill(this.defense_exp, this.defense_mult * BitNodeMultipliers.DefenseLevelMultiplier)),
|
2021-09-05 01:09:30 +02:00
|
|
|
);
|
|
|
|
this.dexterity = Math.max(
|
|
|
|
1,
|
|
|
|
Math.floor(
|
2021-09-09 05:47:34 +02:00
|
|
|
this.calculateSkill(this.dexterity_exp, this.dexterity_mult * BitNodeMultipliers.DexterityLevelMultiplier),
|
2021-09-05 01:09:30 +02:00
|
|
|
),
|
|
|
|
);
|
|
|
|
this.agility = Math.max(
|
|
|
|
1,
|
2021-09-09 05:47:34 +02:00
|
|
|
Math.floor(this.calculateSkill(this.agility_exp, this.agility_mult * BitNodeMultipliers.AgilityLevelMultiplier)),
|
2021-09-05 01:09:30 +02:00
|
|
|
);
|
|
|
|
this.charisma = Math.max(
|
|
|
|
1,
|
2021-09-09 05:47:34 +02:00
|
|
|
Math.floor(this.calculateSkill(this.charisma_exp, this.charisma_mult * BitNodeMultipliers.CharismaLevelMultiplier)),
|
2021-09-05 01:09:30 +02:00
|
|
|
);
|
|
|
|
|
|
|
|
if (this.intelligence > 0) {
|
|
|
|
this.intelligence = Math.floor(this.calculateSkill(this.intelligence_exp));
|
|
|
|
} else {
|
|
|
|
this.intelligence = 0;
|
|
|
|
}
|
|
|
|
|
2021-09-25 07:26:03 +02:00
|
|
|
const ratio = this.hp / this.max_hp;
|
2021-09-05 01:09:30 +02:00
|
|
|
this.max_hp = Math.floor(10 + this.defense / 10);
|
|
|
|
this.hp = Math.round(this.max_hp * ratio);
|
2019-04-04 02:08:11 +02:00
|
|
|
}
|
|
|
|
|
2021-09-24 00:47:43 +02:00
|
|
|
export function resetMultipliers(this: IPlayer): void {
|
2021-09-05 01:09:30 +02:00
|
|
|
this.hacking_chance_mult = 1;
|
|
|
|
this.hacking_speed_mult = 1;
|
|
|
|
this.hacking_money_mult = 1;
|
|
|
|
this.hacking_grow_mult = 1;
|
2019-04-04 02:08:11 +02:00
|
|
|
|
2021-09-05 01:09:30 +02:00
|
|
|
this.hacking_mult = 1;
|
|
|
|
this.strength_mult = 1;
|
|
|
|
this.defense_mult = 1;
|
|
|
|
this.dexterity_mult = 1;
|
|
|
|
this.agility_mult = 1;
|
|
|
|
this.charisma_mult = 1;
|
2019-04-04 02:08:11 +02:00
|
|
|
|
2021-09-05 01:09:30 +02:00
|
|
|
this.hacking_exp_mult = 1;
|
|
|
|
this.strength_exp_mult = 1;
|
|
|
|
this.defense_exp_mult = 1;
|
|
|
|
this.dexterity_exp_mult = 1;
|
|
|
|
this.agility_exp_mult = 1;
|
|
|
|
this.charisma_exp_mult = 1;
|
2019-04-04 02:08:11 +02:00
|
|
|
|
2021-09-05 01:09:30 +02:00
|
|
|
this.company_rep_mult = 1;
|
|
|
|
this.faction_rep_mult = 1;
|
2019-04-04 02:08:11 +02:00
|
|
|
|
2021-09-05 01:09:30 +02:00
|
|
|
this.crime_money_mult = 1;
|
|
|
|
this.crime_success_mult = 1;
|
2019-04-04 02:08:11 +02:00
|
|
|
|
2021-09-05 01:09:30 +02:00
|
|
|
this.hacknet_node_money_mult = 1;
|
|
|
|
this.hacknet_node_purchase_cost_mult = 1;
|
|
|
|
this.hacknet_node_ram_cost_mult = 1;
|
|
|
|
this.hacknet_node_core_cost_mult = 1;
|
|
|
|
this.hacknet_node_level_cost_mult = 1;
|
2019-04-04 02:08:11 +02:00
|
|
|
|
2021-09-05 01:09:30 +02:00
|
|
|
this.work_money_mult = 1;
|
2019-04-04 02:08:11 +02:00
|
|
|
|
2021-09-05 01:09:30 +02:00
|
|
|
this.bladeburner_max_stamina_mult = 1;
|
|
|
|
this.bladeburner_stamina_gain_mult = 1;
|
|
|
|
this.bladeburner_analysis_mult = 1;
|
|
|
|
this.bladeburner_success_chance_mult = 1;
|
2019-04-04 02:08:11 +02:00
|
|
|
}
|
|
|
|
|
2021-09-24 00:47:43 +02:00
|
|
|
export function hasProgram(this: IPlayer, programName: string): boolean {
|
2021-09-05 01:09:30 +02:00
|
|
|
const home = this.getHomeComputer();
|
|
|
|
if (home == null) {
|
|
|
|
return false;
|
|
|
|
}
|
2019-04-04 02:08:11 +02:00
|
|
|
|
2021-09-25 07:26:03 +02:00
|
|
|
for (let i = 0; i < home.programs.length; ++i) {
|
2021-09-05 01:09:30 +02:00
|
|
|
if (programName.toLowerCase() == home.programs[i].toLowerCase()) {
|
|
|
|
return true;
|
2019-04-04 02:08:11 +02:00
|
|
|
}
|
2021-09-05 01:09:30 +02:00
|
|
|
}
|
|
|
|
return false;
|
2019-04-04 02:08:11 +02:00
|
|
|
}
|
|
|
|
|
2021-10-27 19:28:36 +02:00
|
|
|
export function setMoney(this: PlayerObject, money: number): void {
|
2021-09-05 01:09:30 +02:00
|
|
|
if (isNaN(money)) {
|
|
|
|
console.error("NaN passed into Player.setMoney()");
|
|
|
|
return;
|
|
|
|
}
|
2021-11-12 03:35:26 +01:00
|
|
|
this.money = money;
|
2019-04-04 02:08:11 +02:00
|
|
|
}
|
|
|
|
|
2021-10-27 20:18:33 +02:00
|
|
|
export function gainMoney(this: PlayerObject, money: number, source: string): void {
|
2021-09-05 01:09:30 +02:00
|
|
|
if (isNaN(money)) {
|
|
|
|
console.error("NaN passed into Player.gainMoney()");
|
|
|
|
return;
|
|
|
|
}
|
2021-11-12 03:35:26 +01:00
|
|
|
|
2021-11-12 01:56:09 +01:00
|
|
|
this.money = this.money + money;
|
2021-10-27 20:18:33 +02:00
|
|
|
this.recordMoneySource(money, source);
|
2019-04-04 02:08:11 +02:00
|
|
|
}
|
|
|
|
|
2021-10-27 20:18:33 +02:00
|
|
|
export function loseMoney(this: PlayerObject, money: number, source: string): void {
|
2021-09-05 01:09:30 +02:00
|
|
|
if (isNaN(money)) {
|
|
|
|
console.error("NaN passed into Player.loseMoney()");
|
|
|
|
return;
|
|
|
|
}
|
2021-11-12 02:42:19 +01:00
|
|
|
if (this.money === Infinity && money === Infinity) return;
|
2021-11-12 01:56:09 +01:00
|
|
|
this.money = this.money - money;
|
2021-10-27 20:18:33 +02:00
|
|
|
this.recordMoneySource(-1 * money, source);
|
2019-04-04 02:08:11 +02:00
|
|
|
}
|
|
|
|
|
2021-09-24 00:47:43 +02:00
|
|
|
export function canAfford(this: IPlayer, cost: number): boolean {
|
2021-09-05 01:09:30 +02:00
|
|
|
if (isNaN(cost)) {
|
|
|
|
console.error(`NaN passed into Player.canAfford()`);
|
|
|
|
return false;
|
|
|
|
}
|
2021-11-12 03:35:26 +01:00
|
|
|
return this.money >= cost;
|
2019-04-04 02:08:11 +02:00
|
|
|
}
|
|
|
|
|
2021-10-27 20:18:33 +02:00
|
|
|
export function recordMoneySource(this: PlayerObject, amt: number, source: string): void {
|
2021-09-05 01:09:30 +02:00
|
|
|
if (!(this.moneySourceA instanceof MoneySourceTracker)) {
|
|
|
|
console.warn(`Player.moneySourceA was not properly initialized. Resetting`);
|
|
|
|
this.moneySourceA = new MoneySourceTracker();
|
|
|
|
}
|
|
|
|
if (!(this.moneySourceB instanceof MoneySourceTracker)) {
|
|
|
|
console.warn(`Player.moneySourceB was not properly initialized. Resetting`);
|
|
|
|
this.moneySourceB = new MoneySourceTracker();
|
|
|
|
}
|
|
|
|
this.moneySourceA.record(amt, source);
|
|
|
|
this.moneySourceB.record(amt, source);
|
2019-04-04 02:08:11 +02:00
|
|
|
}
|
|
|
|
|
2021-09-25 08:36:49 +02:00
|
|
|
export function gainHackingExp(this: IPlayer, exp: number): void {
|
2021-09-05 01:09:30 +02:00
|
|
|
if (isNaN(exp)) {
|
|
|
|
console.error("ERR: NaN passed into Player.gainHackingExp()");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
this.hacking_exp += exp;
|
|
|
|
if (this.hacking_exp < 0) {
|
|
|
|
this.hacking_exp = 0;
|
|
|
|
}
|
2021-04-20 03:26:51 +02:00
|
|
|
|
2021-11-05 22:12:52 +01:00
|
|
|
this.hacking = calculateSkillF(this.hacking_exp, this.hacking_mult * BitNodeMultipliers.HackingLevelMultiplier);
|
2019-04-04 02:08:11 +02:00
|
|
|
}
|
|
|
|
|
2021-09-25 08:36:49 +02:00
|
|
|
export function gainStrengthExp(this: IPlayer, exp: number): void {
|
2021-09-05 01:09:30 +02:00
|
|
|
if (isNaN(exp)) {
|
|
|
|
console.error("ERR: NaN passed into Player.gainStrengthExp()");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
this.strength_exp += exp;
|
|
|
|
if (this.strength_exp < 0) {
|
|
|
|
this.strength_exp = 0;
|
|
|
|
}
|
2021-04-20 03:26:51 +02:00
|
|
|
|
2021-09-09 05:47:34 +02:00
|
|
|
this.strength = calculateSkillF(this.strength_exp, this.strength_mult * BitNodeMultipliers.StrengthLevelMultiplier);
|
2019-04-04 02:08:11 +02:00
|
|
|
}
|
|
|
|
|
2021-09-25 08:36:49 +02:00
|
|
|
export function gainDefenseExp(this: IPlayer, exp: number): void {
|
2021-09-05 01:09:30 +02:00
|
|
|
if (isNaN(exp)) {
|
|
|
|
console.error("ERR: NaN passed into player.gainDefenseExp()");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
this.defense_exp += exp;
|
|
|
|
if (this.defense_exp < 0) {
|
|
|
|
this.defense_exp = 0;
|
|
|
|
}
|
2021-04-20 03:26:51 +02:00
|
|
|
|
2021-09-09 05:47:34 +02:00
|
|
|
this.defense = calculateSkillF(this.defense_exp, this.defense_mult * BitNodeMultipliers.DefenseLevelMultiplier);
|
2019-04-04 02:08:11 +02:00
|
|
|
}
|
|
|
|
|
2021-09-25 08:36:49 +02:00
|
|
|
export function gainDexterityExp(this: IPlayer, exp: number): void {
|
2021-09-05 01:09:30 +02:00
|
|
|
if (isNaN(exp)) {
|
|
|
|
console.error("ERR: NaN passed into Player.gainDexterityExp()");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
this.dexterity_exp += exp;
|
|
|
|
if (this.dexterity_exp < 0) {
|
|
|
|
this.dexterity_exp = 0;
|
|
|
|
}
|
2021-04-20 03:26:51 +02:00
|
|
|
|
2021-09-05 01:09:30 +02:00
|
|
|
this.dexterity = calculateSkillF(
|
|
|
|
this.dexterity_exp,
|
|
|
|
this.dexterity_mult * BitNodeMultipliers.DexterityLevelMultiplier,
|
|
|
|
);
|
2019-04-04 02:08:11 +02:00
|
|
|
}
|
|
|
|
|
2021-09-24 00:47:43 +02:00
|
|
|
export function gainAgilityExp(this: IPlayer, exp: number): void {
|
2021-09-05 01:09:30 +02:00
|
|
|
if (isNaN(exp)) {
|
|
|
|
console.error("ERR: NaN passed into Player.gainAgilityExp()");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
this.agility_exp += exp;
|
|
|
|
if (this.agility_exp < 0) {
|
|
|
|
this.agility_exp = 0;
|
|
|
|
}
|
2021-04-20 03:26:51 +02:00
|
|
|
|
2021-09-09 05:47:34 +02:00
|
|
|
this.agility = calculateSkillF(this.agility_exp, this.agility_mult * BitNodeMultipliers.AgilityLevelMultiplier);
|
2019-04-04 02:08:11 +02:00
|
|
|
}
|
|
|
|
|
2021-09-24 00:47:43 +02:00
|
|
|
export function gainCharismaExp(this: IPlayer, exp: number): void {
|
2021-09-05 01:09:30 +02:00
|
|
|
if (isNaN(exp)) {
|
|
|
|
console.error("ERR: NaN passed into Player.gainCharismaExp()");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
this.charisma_exp += exp;
|
|
|
|
if (this.charisma_exp < 0) {
|
|
|
|
this.charisma_exp = 0;
|
|
|
|
}
|
2021-04-20 03:26:51 +02:00
|
|
|
|
2021-09-09 05:47:34 +02:00
|
|
|
this.charisma = calculateSkillF(this.charisma_exp, this.charisma_mult * BitNodeMultipliers.CharismaLevelMultiplier);
|
2019-04-04 02:08:11 +02:00
|
|
|
}
|
|
|
|
|
2021-09-24 00:47:43 +02:00
|
|
|
export function gainIntelligenceExp(this: IPlayer, exp: number): void {
|
2021-09-05 01:09:30 +02:00
|
|
|
if (isNaN(exp)) {
|
|
|
|
console.error("ERROR: NaN passed into Player.gainIntelligenceExp()");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (SourceFileFlags[5] > 0 || this.intelligence > 0) {
|
|
|
|
this.intelligence_exp += exp;
|
2021-10-12 16:29:41 +02:00
|
|
|
this.intelligence = Math.floor(this.calculateSkill(this.intelligence_exp));
|
2021-09-05 01:09:30 +02:00
|
|
|
}
|
2019-04-04 02:08:11 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//Given a string expression like "str" or "strength", returns the given stat
|
2021-09-24 00:47:43 +02:00
|
|
|
export function queryStatFromString(this: IPlayer, str: string): number {
|
2021-09-05 01:09:30 +02:00
|
|
|
const tempStr = str.toLowerCase();
|
|
|
|
if (tempStr.includes("hack")) {
|
2021-11-05 22:12:52 +01:00
|
|
|
return this.hacking;
|
2021-09-05 01:09:30 +02:00
|
|
|
}
|
|
|
|
if (tempStr.includes("str")) {
|
|
|
|
return this.strength;
|
|
|
|
}
|
|
|
|
if (tempStr.includes("def")) {
|
|
|
|
return this.defense;
|
|
|
|
}
|
|
|
|
if (tempStr.includes("dex")) {
|
|
|
|
return this.dexterity;
|
|
|
|
}
|
|
|
|
if (tempStr.includes("agi")) {
|
|
|
|
return this.agility;
|
|
|
|
}
|
|
|
|
if (tempStr.includes("cha")) {
|
|
|
|
return this.charisma;
|
|
|
|
}
|
|
|
|
if (tempStr.includes("int")) {
|
|
|
|
return this.intelligence;
|
|
|
|
}
|
2021-09-24 00:47:43 +02:00
|
|
|
return 0;
|
2019-04-04 02:08:11 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/******* Working functions *******/
|
2021-09-24 00:47:43 +02:00
|
|
|
export function resetWorkStatus(this: IPlayer, generalType?: string, group?: string, workType?: string): void {
|
2021-09-23 19:15:27 +02:00
|
|
|
if (this.workType !== CONSTANTS.WorkTypeFaction && generalType === this.workType && group === this.companyName)
|
|
|
|
return;
|
2021-09-09 05:47:34 +02:00
|
|
|
if (generalType === this.workType && group === this.currentWorkFactionName && workType === this.factionWorkType)
|
2021-09-05 01:09:30 +02:00
|
|
|
return;
|
|
|
|
if (this.isWorking) this.singularityStopWork();
|
|
|
|
this.workHackExpGainRate = 0;
|
|
|
|
this.workStrExpGainRate = 0;
|
|
|
|
this.workDefExpGainRate = 0;
|
|
|
|
this.workDexExpGainRate = 0;
|
|
|
|
this.workAgiExpGainRate = 0;
|
|
|
|
this.workChaExpGainRate = 0;
|
|
|
|
this.workRepGainRate = 0;
|
|
|
|
this.workMoneyGainRate = 0;
|
|
|
|
this.workMoneyLossRate = 0;
|
|
|
|
|
|
|
|
this.workHackExpGained = 0;
|
|
|
|
this.workStrExpGained = 0;
|
|
|
|
this.workDefExpGained = 0;
|
|
|
|
this.workDexExpGained = 0;
|
|
|
|
this.workAgiExpGained = 0;
|
|
|
|
this.workChaExpGained = 0;
|
|
|
|
this.workRepGained = 0;
|
|
|
|
this.workMoneyGained = 0;
|
|
|
|
|
|
|
|
this.timeWorked = 0;
|
|
|
|
this.timeWorkedCreateProgram = 0;
|
|
|
|
|
|
|
|
this.currentWorkFactionName = "";
|
|
|
|
this.currentWorkFactionDescription = "";
|
|
|
|
this.createProgramName = "";
|
|
|
|
this.className = "";
|
2021-10-16 21:43:28 +02:00
|
|
|
this.workType = "";
|
2021-09-05 01:09:30 +02:00
|
|
|
}
|
|
|
|
|
2021-09-25 08:36:49 +02:00
|
|
|
export function processWorkEarnings(this: IPlayer, numCycles = 1): void {
|
2021-09-27 03:11:49 +02:00
|
|
|
let focusBonus = 1;
|
|
|
|
if (!this.hasAugmentation(AugmentationNames["NeuroreceptorManager"])) {
|
|
|
|
focusBonus = this.focus ? 1 : CONSTANTS.BaseFocusBonus;
|
|
|
|
}
|
2021-09-05 01:09:30 +02:00
|
|
|
const hackExpGain = focusBonus * this.workHackExpGainRate * numCycles;
|
|
|
|
const strExpGain = focusBonus * this.workStrExpGainRate * numCycles;
|
|
|
|
const defExpGain = focusBonus * this.workDefExpGainRate * numCycles;
|
|
|
|
const dexExpGain = focusBonus * this.workDexExpGainRate * numCycles;
|
|
|
|
const agiExpGain = focusBonus * this.workAgiExpGainRate * numCycles;
|
|
|
|
const chaExpGain = focusBonus * this.workChaExpGainRate * numCycles;
|
2021-09-09 05:47:34 +02:00
|
|
|
const moneyGain = (this.workMoneyGainRate - this.workMoneyLossRate) * numCycles;
|
2021-09-05 01:09:30 +02:00
|
|
|
this.gainHackingExp(hackExpGain);
|
|
|
|
this.gainStrengthExp(strExpGain);
|
|
|
|
this.gainDefenseExp(defExpGain);
|
|
|
|
this.gainDexterityExp(dexExpGain);
|
|
|
|
this.gainAgilityExp(agiExpGain);
|
|
|
|
this.gainCharismaExp(chaExpGain);
|
2021-10-27 20:18:33 +02:00
|
|
|
this.gainMoney(moneyGain, this.className ? "class" : "work");
|
2021-09-05 01:09:30 +02:00
|
|
|
this.workHackExpGained += hackExpGain;
|
|
|
|
this.workStrExpGained += strExpGain;
|
|
|
|
this.workDefExpGained += defExpGain;
|
|
|
|
this.workDexExpGained += dexExpGain;
|
|
|
|
this.workAgiExpGained += agiExpGain;
|
|
|
|
this.workChaExpGained += chaExpGain;
|
|
|
|
this.workRepGained += focusBonus * this.workRepGainRate * numCycles;
|
|
|
|
this.workMoneyGained += focusBonus * this.workMoneyGainRate * numCycles;
|
|
|
|
this.workMoneyGained -= focusBonus * this.workMoneyLossRate * numCycles;
|
2019-04-04 02:08:11 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Working for Company */
|
2021-09-24 00:47:43 +02:00
|
|
|
export function startWork(this: IPlayer, router: IRouter, companyName: string): void {
|
2021-09-05 01:09:30 +02:00
|
|
|
this.resetWorkStatus(CONSTANTS.WorkTypeCompany, companyName);
|
|
|
|
this.isWorking = true;
|
|
|
|
this.focus = true;
|
|
|
|
this.companyName = companyName;
|
|
|
|
this.workType = CONSTANTS.WorkTypeCompany;
|
|
|
|
|
|
|
|
this.workHackExpGainRate = this.getWorkHackExpGain();
|
|
|
|
this.workStrExpGainRate = this.getWorkStrExpGain();
|
|
|
|
this.workDefExpGainRate = this.getWorkDefExpGain();
|
|
|
|
this.workDexExpGainRate = this.getWorkDexExpGain();
|
|
|
|
this.workAgiExpGainRate = this.getWorkAgiExpGain();
|
|
|
|
this.workChaExpGainRate = this.getWorkChaExpGain();
|
|
|
|
this.workRepGainRate = this.getWorkRepGain();
|
|
|
|
this.workMoneyGainRate = this.getWorkMoneyGain();
|
|
|
|
|
|
|
|
this.timeNeededToCompleteWork = CONSTANTS.MillisecondsPer8Hours;
|
2021-09-20 07:45:32 +02:00
|
|
|
router.toWork();
|
2019-04-04 02:08:11 +02:00
|
|
|
}
|
|
|
|
|
2021-10-12 05:14:15 +02:00
|
|
|
export function process(this: IPlayer, router: IRouter, numCycles = 1): void {
|
|
|
|
// Working
|
|
|
|
if (this.isWorking) {
|
|
|
|
if (this.workType == CONSTANTS.WorkTypeFaction) {
|
|
|
|
if (this.workForFaction(numCycles)) {
|
|
|
|
router.toFaction();
|
|
|
|
}
|
|
|
|
} else if (this.workType == CONSTANTS.WorkTypeCreateProgram) {
|
|
|
|
if (this.createProgramWork(numCycles)) {
|
|
|
|
router.toTerminal();
|
|
|
|
}
|
|
|
|
} else if (this.workType == CONSTANTS.WorkTypeStudyClass) {
|
|
|
|
if (this.takeClass(numCycles)) {
|
|
|
|
router.toCity();
|
|
|
|
}
|
|
|
|
} else if (this.workType == CONSTANTS.WorkTypeCrime) {
|
|
|
|
if (this.commitCrime(numCycles)) {
|
|
|
|
router.toLocation(Locations[LocationName.Slums]);
|
|
|
|
}
|
|
|
|
} else if (this.workType == CONSTANTS.WorkTypeCompanyPartTime) {
|
|
|
|
if (this.workPartTime(numCycles)) {
|
|
|
|
router.toCity();
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (this.work(numCycles)) {
|
|
|
|
router.toCity();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-09-25 08:36:49 +02:00
|
|
|
export function cancelationPenalty(this: IPlayer): number {
|
2021-10-16 03:03:25 +02:00
|
|
|
const data = serverMetadata.find((s) => s.specialName === this.companyName);
|
2021-10-16 18:19:53 +02:00
|
|
|
if (!data) return 0.5; // Does not have special server.
|
2021-10-16 03:03:25 +02:00
|
|
|
const server = GetServer(data.hostname);
|
2021-10-07 23:55:49 +02:00
|
|
|
if (server instanceof Server) {
|
|
|
|
if (server && server.backdoorInstalled) return 0.75;
|
2021-09-05 01:09:30 +02:00
|
|
|
}
|
2021-10-07 23:55:49 +02:00
|
|
|
|
2021-09-05 01:09:30 +02:00
|
|
|
return 0.5;
|
2021-04-20 03:26:51 +02:00
|
|
|
}
|
|
|
|
|
2021-09-24 00:47:43 +02:00
|
|
|
export function work(this: IPlayer, numCycles: number): boolean {
|
2021-09-05 01:09:30 +02:00
|
|
|
// Cap the number of cycles being processed to whatever would put you at
|
|
|
|
// the work time limit (8 hours)
|
2021-09-25 07:26:03 +02:00
|
|
|
let overMax = false;
|
2021-09-18 01:43:08 +02:00
|
|
|
if (this.timeWorked + CONSTANTS._idleSpeed * numCycles >= CONSTANTS.MillisecondsPer8Hours) {
|
2021-09-05 01:09:30 +02:00
|
|
|
overMax = true;
|
2021-09-18 01:43:08 +02:00
|
|
|
numCycles = Math.round((CONSTANTS.MillisecondsPer8Hours - this.timeWorked) / CONSTANTS._idleSpeed);
|
2021-09-05 01:09:30 +02:00
|
|
|
}
|
2021-09-18 01:43:08 +02:00
|
|
|
this.timeWorked += CONSTANTS._idleSpeed * numCycles;
|
2021-09-05 01:09:30 +02:00
|
|
|
|
|
|
|
this.workRepGainRate = this.getWorkRepGain();
|
2021-10-27 04:03:34 +02:00
|
|
|
this.workMoneyGainRate = this.getWorkMoneyGain();
|
2021-09-05 01:09:30 +02:00
|
|
|
this.processWorkEarnings(numCycles);
|
|
|
|
|
2021-09-18 18:13:20 +02:00
|
|
|
const comp = Companies[this.companyName];
|
|
|
|
influenceStockThroughCompanyWork(comp, this.workRepGainRate, numCycles);
|
|
|
|
|
2021-09-05 01:09:30 +02:00
|
|
|
// If timeWorked == 8 hours, then finish. You can only gain 8 hours worth of exp and money
|
|
|
|
if (overMax || this.timeWorked >= CONSTANTS.MillisecondsPer8Hours) {
|
2021-09-24 00:47:43 +02:00
|
|
|
this.finishWork(false);
|
2021-09-18 18:13:20 +02:00
|
|
|
return true;
|
2021-09-05 01:09:30 +02:00
|
|
|
}
|
2021-09-18 18:13:20 +02:00
|
|
|
return false;
|
2021-09-05 01:09:30 +02:00
|
|
|
}
|
|
|
|
|
2021-09-24 00:47:43 +02:00
|
|
|
export function finishWork(this: IPlayer, cancelled: boolean, sing = false): string {
|
2021-09-05 01:09:30 +02:00
|
|
|
//Since the work was cancelled early, player only gains half of what they've earned so far
|
|
|
|
if (cancelled) {
|
|
|
|
this.workRepGained *= this.cancelationPenalty();
|
|
|
|
}
|
|
|
|
|
|
|
|
const company = Companies[this.companyName];
|
|
|
|
company.playerReputation += this.workRepGained;
|
|
|
|
|
|
|
|
this.updateSkillLevels();
|
|
|
|
|
|
|
|
let content = (
|
|
|
|
<>
|
|
|
|
You earned a total of: <br />
|
|
|
|
<Money money={this.workMoneyGained} />
|
|
|
|
<br />
|
2021-10-01 19:08:37 +02:00
|
|
|
<Reputation reputation={this.workRepGained} /> reputation for the company <br />
|
2021-09-05 01:09:30 +02:00
|
|
|
{numeralWrapper.formatExp(this.workHackExpGained)} hacking exp <br />
|
|
|
|
{numeralWrapper.formatExp(this.workStrExpGained)} strength exp <br />
|
|
|
|
{numeralWrapper.formatExp(this.workDefExpGained)} defense exp <br />
|
|
|
|
{numeralWrapper.formatExp(this.workDexExpGained)} dexterity exp <br />
|
|
|
|
{numeralWrapper.formatExp(this.workAgiExpGained)} agility exp <br />
|
|
|
|
{numeralWrapper.formatExp(this.workChaExpGained)} charisma exp
|
|
|
|
<br />
|
2021-03-31 06:45:21 +02:00
|
|
|
</>
|
2021-09-05 01:09:30 +02:00
|
|
|
);
|
|
|
|
|
|
|
|
if (cancelled) {
|
|
|
|
content = (
|
|
|
|
<>
|
2021-09-09 05:47:34 +02:00
|
|
|
You worked a short shift of {convertTimeMsToTimeElapsedString(this.timeWorked)} <br />
|
2021-09-05 01:09:30 +02:00
|
|
|
<br />
|
2021-09-09 05:47:34 +02:00
|
|
|
Since you cancelled your work early, you only gained half of the reputation you earned. <br />
|
2021-09-05 01:09:30 +02:00
|
|
|
<br />
|
|
|
|
{content}
|
|
|
|
</>
|
|
|
|
);
|
|
|
|
} else {
|
|
|
|
content = (
|
|
|
|
<>
|
|
|
|
You worked a full shift of 8 hours! <br />
|
|
|
|
<br />
|
|
|
|
{content}
|
|
|
|
</>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
if (!sing) {
|
|
|
|
dialogBoxCreate(content);
|
|
|
|
}
|
|
|
|
|
|
|
|
this.isWorking = false;
|
|
|
|
|
2021-09-24 00:47:43 +02:00
|
|
|
this.resetWorkStatus();
|
2021-09-05 01:09:30 +02:00
|
|
|
if (sing) {
|
2021-09-24 00:47:43 +02:00
|
|
|
const res =
|
2021-09-05 01:09:30 +02:00
|
|
|
"You worked a short shift of " +
|
|
|
|
convertTimeMsToTimeElapsedString(this.timeWorked) +
|
|
|
|
" and " +
|
|
|
|
"earned $" +
|
|
|
|
numeralWrapper.formatMoney(this.workMoneyGained) +
|
|
|
|
", " +
|
|
|
|
numeralWrapper.formatReputation(this.workRepGained) +
|
|
|
|
" reputation, " +
|
|
|
|
numeralWrapper.formatExp(this.workHackExpGained) +
|
|
|
|
" hacking exp, " +
|
|
|
|
numeralWrapper.formatExp(this.workStrExpGained) +
|
|
|
|
" strength exp, " +
|
|
|
|
numeralWrapper.formatExp(this.workDefExpGained) +
|
|
|
|
" defense exp, " +
|
|
|
|
numeralWrapper.formatExp(this.workDexExpGained) +
|
|
|
|
" dexterity exp, " +
|
|
|
|
numeralWrapper.formatExp(this.workAgiExpGained) +
|
|
|
|
" agility exp, and " +
|
|
|
|
numeralWrapper.formatExp(this.workChaExpGained) +
|
|
|
|
" charisma exp.";
|
2021-09-24 00:47:43 +02:00
|
|
|
|
2021-09-05 01:09:30 +02:00
|
|
|
return res;
|
|
|
|
}
|
2021-09-24 00:47:43 +02:00
|
|
|
|
|
|
|
return "";
|
2019-04-04 02:08:11 +02:00
|
|
|
}
|
|
|
|
|
2021-09-24 00:47:43 +02:00
|
|
|
export function startWorkPartTime(this: IPlayer, router: IRouter, companyName: string): void {
|
2021-09-05 01:09:30 +02:00
|
|
|
this.resetWorkStatus(CONSTANTS.WorkTypeCompanyPartTime, companyName);
|
|
|
|
this.isWorking = true;
|
|
|
|
this.focus = true;
|
|
|
|
this.companyName = companyName;
|
|
|
|
this.workType = CONSTANTS.WorkTypeCompanyPartTime;
|
|
|
|
|
|
|
|
this.workHackExpGainRate = this.getWorkHackExpGain();
|
|
|
|
this.workStrExpGainRate = this.getWorkStrExpGain();
|
|
|
|
this.workDefExpGainRate = this.getWorkDefExpGain();
|
|
|
|
this.workDexExpGainRate = this.getWorkDexExpGain();
|
|
|
|
this.workAgiExpGainRate = this.getWorkAgiExpGain();
|
|
|
|
this.workChaExpGainRate = this.getWorkChaExpGain();
|
|
|
|
this.workRepGainRate = this.getWorkRepGain();
|
|
|
|
this.workMoneyGainRate = this.getWorkMoneyGain();
|
|
|
|
|
|
|
|
this.timeNeededToCompleteWork = CONSTANTS.MillisecondsPer8Hours;
|
2021-09-20 07:45:32 +02:00
|
|
|
router.toWork();
|
2019-04-04 02:08:11 +02:00
|
|
|
}
|
|
|
|
|
2021-09-24 00:47:43 +02:00
|
|
|
export function workPartTime(this: IPlayer, numCycles: number): boolean {
|
2021-09-05 01:09:30 +02:00
|
|
|
//Cap the number of cycles being processed to whatever would put you at the
|
|
|
|
//work time limit (8 hours)
|
2021-09-25 07:26:03 +02:00
|
|
|
let overMax = false;
|
2021-09-18 01:43:08 +02:00
|
|
|
if (this.timeWorked + CONSTANTS._idleSpeed * numCycles >= CONSTANTS.MillisecondsPer8Hours) {
|
2021-09-05 01:09:30 +02:00
|
|
|
overMax = true;
|
2021-09-18 01:43:08 +02:00
|
|
|
numCycles = Math.round((CONSTANTS.MillisecondsPer8Hours - this.timeWorked) / CONSTANTS._idleSpeed);
|
2021-09-05 01:09:30 +02:00
|
|
|
}
|
2021-09-18 01:43:08 +02:00
|
|
|
this.timeWorked += CONSTANTS._idleSpeed * numCycles;
|
2021-09-05 01:09:30 +02:00
|
|
|
|
|
|
|
this.workRepGainRate = this.getWorkRepGain();
|
|
|
|
this.processWorkEarnings(numCycles);
|
|
|
|
|
|
|
|
//If timeWorked == 8 hours, then finish. You can only gain 8 hours worth of exp and money
|
|
|
|
if (overMax || this.timeWorked >= CONSTANTS.MillisecondsPer8Hours) {
|
2021-09-24 00:47:43 +02:00
|
|
|
this.finishWorkPartTime();
|
2021-09-18 18:13:20 +02:00
|
|
|
return true;
|
2021-09-05 01:09:30 +02:00
|
|
|
}
|
2021-09-18 18:13:20 +02:00
|
|
|
return false;
|
2021-09-05 01:09:30 +02:00
|
|
|
}
|
|
|
|
|
2021-09-24 00:47:43 +02:00
|
|
|
export function finishWorkPartTime(this: IPlayer, sing = false): string {
|
2021-09-25 07:26:03 +02:00
|
|
|
const company = Companies[this.companyName];
|
2021-09-05 01:09:30 +02:00
|
|
|
company.playerReputation += this.workRepGained;
|
|
|
|
|
|
|
|
this.updateSkillLevels();
|
|
|
|
|
|
|
|
const content = (
|
|
|
|
<>
|
|
|
|
You worked for {convertTimeMsToTimeElapsedString(this.timeWorked)}
|
|
|
|
<br />
|
|
|
|
<br />
|
|
|
|
You earned a total of: <br />
|
|
|
|
<Money money={this.workMoneyGained} />
|
|
|
|
<br />
|
2021-10-01 19:08:37 +02:00
|
|
|
<Reputation reputation={this.workRepGained} /> reputation for the company <br />
|
2021-09-05 01:09:30 +02:00
|
|
|
{numeralWrapper.formatExp(this.workHackExpGained)} hacking exp <br />
|
|
|
|
{numeralWrapper.formatExp(this.workStrExpGained)} strength exp <br />
|
|
|
|
{numeralWrapper.formatExp(this.workDefExpGained)} defense exp <br />
|
|
|
|
{numeralWrapper.formatExp(this.workDexExpGained)} dexterity exp <br />
|
|
|
|
{numeralWrapper.formatExp(this.workAgiExpGained)} agility exp <br />
|
|
|
|
{numeralWrapper.formatExp(this.workChaExpGained)} charisma exp
|
|
|
|
<br />
|
|
|
|
</>
|
|
|
|
);
|
|
|
|
if (!sing) {
|
|
|
|
dialogBoxCreate(content);
|
|
|
|
}
|
|
|
|
|
|
|
|
this.isWorking = false;
|
2021-09-24 00:47:43 +02:00
|
|
|
this.resetWorkStatus();
|
|
|
|
|
2021-09-05 01:09:30 +02:00
|
|
|
if (sing) {
|
2021-09-25 07:26:03 +02:00
|
|
|
const res =
|
2021-09-05 01:09:30 +02:00
|
|
|
"You worked for " +
|
|
|
|
convertTimeMsToTimeElapsedString(this.timeWorked) +
|
|
|
|
" and " +
|
|
|
|
"earned a total of " +
|
|
|
|
"$" +
|
|
|
|
numeralWrapper.formatMoney(this.workMoneyGained) +
|
|
|
|
", " +
|
|
|
|
numeralWrapper.formatReputation(this.workRepGained) +
|
|
|
|
" reputation, " +
|
|
|
|
numeralWrapper.formatExp(this.workHackExpGained) +
|
|
|
|
" hacking exp, " +
|
|
|
|
numeralWrapper.formatExp(this.workStrExpGained) +
|
|
|
|
" strength exp, " +
|
|
|
|
numeralWrapper.formatExp(this.workDefExpGained) +
|
|
|
|
" defense exp, " +
|
|
|
|
numeralWrapper.formatExp(this.workDexExpGained) +
|
|
|
|
" dexterity exp, " +
|
|
|
|
numeralWrapper.formatExp(this.workAgiExpGained) +
|
|
|
|
" agility exp, and " +
|
|
|
|
numeralWrapper.formatExp(this.workChaExpGained) +
|
|
|
|
" charisma exp";
|
|
|
|
return res;
|
|
|
|
}
|
2021-09-24 00:47:43 +02:00
|
|
|
return "";
|
2019-04-04 02:08:11 +02:00
|
|
|
}
|
|
|
|
|
2021-09-24 00:47:43 +02:00
|
|
|
export function startFocusing(this: IPlayer): void {
|
2021-09-05 01:09:30 +02:00
|
|
|
this.focus = true;
|
2021-05-31 23:34:23 +02:00
|
|
|
}
|
|
|
|
|
2021-09-24 00:47:43 +02:00
|
|
|
export function stopFocusing(this: IPlayer): void {
|
2021-09-05 01:09:30 +02:00
|
|
|
this.focus = false;
|
2021-05-31 23:34:23 +02:00
|
|
|
}
|
|
|
|
|
2019-04-04 02:08:11 +02:00
|
|
|
/* Working for Faction */
|
2021-09-24 00:47:43 +02:00
|
|
|
export function startFactionWork(this: IPlayer, router: IRouter, faction: Faction): void {
|
2021-09-05 01:09:30 +02:00
|
|
|
//Update reputation gain rate to account for faction favor
|
2021-09-25 07:26:03 +02:00
|
|
|
let favorMult = 1 + faction.favor / 100;
|
2021-09-05 01:09:30 +02:00
|
|
|
if (isNaN(favorMult)) {
|
|
|
|
favorMult = 1;
|
|
|
|
}
|
|
|
|
this.workRepGainRate *= favorMult;
|
|
|
|
this.workRepGainRate *= BitNodeMultipliers.FactionWorkRepGain;
|
|
|
|
|
|
|
|
this.isWorking = true;
|
|
|
|
this.focus = true;
|
|
|
|
this.workType = CONSTANTS.WorkTypeFaction;
|
|
|
|
this.currentWorkFactionName = faction.name;
|
|
|
|
|
|
|
|
this.timeNeededToCompleteWork = CONSTANTS.MillisecondsPer20Hours;
|
2021-09-20 07:45:32 +02:00
|
|
|
router.toWork();
|
2019-04-04 02:08:11 +02:00
|
|
|
}
|
|
|
|
|
2021-09-25 07:26:03 +02:00
|
|
|
export function startFactionHackWork(this: IPlayer, router: IRouter, faction: Faction): void {
|
2021-09-09 05:47:34 +02:00
|
|
|
this.resetWorkStatus(CONSTANTS.WorkTypeFaction, faction.name, CONSTANTS.FactionWorkHacking);
|
2019-04-04 02:08:11 +02:00
|
|
|
|
2021-09-09 05:47:34 +02:00
|
|
|
this.workHackExpGainRate = 0.15 * this.hacking_exp_mult * BitNodeMultipliers.FactionWorkExpGain;
|
2021-11-16 05:49:33 +01:00
|
|
|
this.workRepGainRate = getHackingWorkRepGain(this, faction);
|
2019-04-04 02:08:11 +02:00
|
|
|
|
2021-09-05 01:09:30 +02:00
|
|
|
this.factionWorkType = CONSTANTS.FactionWorkHacking;
|
|
|
|
this.currentWorkFactionDescription = "carrying out hacking contracts";
|
2019-04-04 02:08:11 +02:00
|
|
|
|
2021-09-20 07:45:32 +02:00
|
|
|
this.startFactionWork(router, faction);
|
2019-04-04 02:08:11 +02:00
|
|
|
}
|
|
|
|
|
2021-09-25 07:26:03 +02:00
|
|
|
export function startFactionFieldWork(this: IPlayer, router: IRouter, faction: Faction): void {
|
2021-09-09 05:47:34 +02:00
|
|
|
this.resetWorkStatus(CONSTANTS.WorkTypeFaction, faction.name, CONSTANTS.FactionWorkField);
|
|
|
|
|
|
|
|
this.workHackExpGainRate = 0.1 * this.hacking_exp_mult * BitNodeMultipliers.FactionWorkExpGain;
|
|
|
|
this.workStrExpGainRate = 0.1 * this.strength_exp_mult * BitNodeMultipliers.FactionWorkExpGain;
|
|
|
|
this.workDefExpGainRate = 0.1 * this.defense_exp_mult * BitNodeMultipliers.FactionWorkExpGain;
|
|
|
|
this.workDexExpGainRate = 0.1 * this.dexterity_exp_mult * BitNodeMultipliers.FactionWorkExpGain;
|
|
|
|
this.workAgiExpGainRate = 0.1 * this.agility_exp_mult * BitNodeMultipliers.FactionWorkExpGain;
|
|
|
|
this.workChaExpGainRate = 0.1 * this.charisma_exp_mult * BitNodeMultipliers.FactionWorkExpGain;
|
2021-09-05 01:09:30 +02:00
|
|
|
this.workRepGainRate = getFactionFieldWorkRepGain(this, faction);
|
|
|
|
|
|
|
|
this.factionWorkType = CONSTANTS.FactionWorkField;
|
|
|
|
this.currentWorkFactionDescription = "carrying out field missions";
|
|
|
|
|
2021-09-20 07:45:32 +02:00
|
|
|
this.startFactionWork(router, faction);
|
2019-04-04 02:08:11 +02:00
|
|
|
}
|
|
|
|
|
2021-09-25 07:26:03 +02:00
|
|
|
export function startFactionSecurityWork(this: IPlayer, router: IRouter, faction: Faction): void {
|
2021-09-09 05:47:34 +02:00
|
|
|
this.resetWorkStatus(CONSTANTS.WorkTypeFaction, faction.name, CONSTANTS.FactionWorkSecurity);
|
|
|
|
|
|
|
|
this.workHackExpGainRate = 0.05 * this.hacking_exp_mult * BitNodeMultipliers.FactionWorkExpGain;
|
|
|
|
this.workStrExpGainRate = 0.15 * this.strength_exp_mult * BitNodeMultipliers.FactionWorkExpGain;
|
|
|
|
this.workDefExpGainRate = 0.15 * this.defense_exp_mult * BitNodeMultipliers.FactionWorkExpGain;
|
|
|
|
this.workDexExpGainRate = 0.15 * this.dexterity_exp_mult * BitNodeMultipliers.FactionWorkExpGain;
|
|
|
|
this.workAgiExpGainRate = 0.15 * this.agility_exp_mult * BitNodeMultipliers.FactionWorkExpGain;
|
|
|
|
this.workChaExpGainRate = 0.0 * this.charisma_exp_mult * BitNodeMultipliers.FactionWorkExpGain;
|
2021-09-05 01:09:30 +02:00
|
|
|
this.workRepGainRate = getFactionSecurityWorkRepGain(this, faction);
|
|
|
|
|
|
|
|
this.factionWorkType = CONSTANTS.FactionWorkSecurity;
|
|
|
|
this.currentWorkFactionDescription = "performing security detail";
|
|
|
|
|
2021-09-20 07:45:32 +02:00
|
|
|
this.startFactionWork(router, faction);
|
2019-04-04 02:08:11 +02:00
|
|
|
}
|
|
|
|
|
2021-09-25 07:26:03 +02:00
|
|
|
export function workForFaction(this: IPlayer, numCycles: number): boolean {
|
2021-09-05 01:09:30 +02:00
|
|
|
const faction = Factions[this.currentWorkFactionName];
|
|
|
|
|
|
|
|
//Constantly update the rep gain rate
|
|
|
|
switch (this.factionWorkType) {
|
|
|
|
case CONSTANTS.FactionWorkHacking:
|
|
|
|
this.workRepGainRate = getHackingWorkRepGain(this, faction);
|
|
|
|
break;
|
|
|
|
case CONSTANTS.FactionWorkField:
|
|
|
|
this.workRepGainRate = getFactionFieldWorkRepGain(this, faction);
|
|
|
|
break;
|
|
|
|
case CONSTANTS.FactionWorkSecurity:
|
|
|
|
this.workRepGainRate = getFactionSecurityWorkRepGain(this, faction);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
2021-11-16 05:49:33 +01:00
|
|
|
let favorMult = 1 + faction.favor / 100;
|
|
|
|
if (isNaN(favorMult)) {
|
|
|
|
favorMult = 1;
|
|
|
|
}
|
|
|
|
this.workRepGainRate *= favorMult;
|
|
|
|
this.workRepGainRate *= BitNodeMultipliers.FactionWorkRepGain;
|
2021-09-05 01:09:30 +02:00
|
|
|
|
|
|
|
//Cap the number of cycles being processed to whatever would put you at limit (20 hours)
|
2021-09-24 00:47:43 +02:00
|
|
|
let overMax = false;
|
2021-09-18 01:43:08 +02:00
|
|
|
if (this.timeWorked + CONSTANTS._idleSpeed * numCycles >= CONSTANTS.MillisecondsPer20Hours) {
|
2021-09-05 01:09:30 +02:00
|
|
|
overMax = true;
|
2021-09-18 01:43:08 +02:00
|
|
|
numCycles = Math.round((CONSTANTS.MillisecondsPer20Hours - this.timeWorked) / CONSTANTS._idleSpeed);
|
2021-09-05 01:09:30 +02:00
|
|
|
}
|
2021-09-18 01:43:08 +02:00
|
|
|
this.timeWorked += CONSTANTS._idleSpeed * numCycles;
|
2021-09-05 01:09:30 +02:00
|
|
|
|
|
|
|
this.processWorkEarnings(numCycles);
|
|
|
|
|
|
|
|
//If timeWorked == 20 hours, then finish. You can only work for the faction for 20 hours
|
|
|
|
if (overMax || this.timeWorked >= CONSTANTS.MillisecondsPer20Hours) {
|
2021-09-18 18:13:20 +02:00
|
|
|
this.finishFactionWork(false);
|
|
|
|
return true;
|
2021-09-05 01:09:30 +02:00
|
|
|
}
|
2021-09-18 18:13:20 +02:00
|
|
|
return false;
|
2021-09-05 01:09:30 +02:00
|
|
|
}
|
|
|
|
|
2021-09-24 00:47:43 +02:00
|
|
|
export function finishFactionWork(this: IPlayer, cancelled: boolean, sing = false): string {
|
|
|
|
const faction = Factions[this.currentWorkFactionName];
|
2021-09-05 01:09:30 +02:00
|
|
|
faction.playerReputation += this.workRepGained;
|
|
|
|
|
|
|
|
this.updateSkillLevels();
|
|
|
|
|
|
|
|
if (!sing) {
|
|
|
|
dialogBoxCreate(
|
|
|
|
<>
|
2021-09-09 05:47:34 +02:00
|
|
|
You worked for your faction {faction.name} for a total of {convertTimeMsToTimeElapsedString(this.timeWorked)}{" "}
|
|
|
|
<br />
|
2021-09-05 01:09:30 +02:00
|
|
|
<br />
|
|
|
|
You earned a total of: <br />
|
|
|
|
<Money money={this.workMoneyGained} />
|
|
|
|
<br />
|
2021-10-01 19:08:37 +02:00
|
|
|
<Reputation reputation={this.workRepGained} /> reputation for the faction <br />
|
2021-09-05 01:09:30 +02:00
|
|
|
{numeralWrapper.formatExp(this.workHackExpGained)} hacking exp <br />
|
|
|
|
{numeralWrapper.formatExp(this.workStrExpGained)} strength exp <br />
|
|
|
|
{numeralWrapper.formatExp(this.workDefExpGained)} defense exp <br />
|
|
|
|
{numeralWrapper.formatExp(this.workDexExpGained)} dexterity exp <br />
|
|
|
|
{numeralWrapper.formatExp(this.workAgiExpGained)} agility exp <br />
|
|
|
|
{numeralWrapper.formatExp(this.workChaExpGained)} charisma exp
|
|
|
|
<br />
|
|
|
|
</>,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
this.isWorking = false;
|
2021-09-24 00:47:43 +02:00
|
|
|
this.resetWorkStatus();
|
2021-09-05 01:09:30 +02:00
|
|
|
if (sing) {
|
2021-09-25 07:26:03 +02:00
|
|
|
const res =
|
2021-09-05 01:09:30 +02:00
|
|
|
"You worked for your faction " +
|
|
|
|
faction.name +
|
|
|
|
" for a total of " +
|
|
|
|
convertTimeMsToTimeElapsedString(this.timeWorked) +
|
|
|
|
". " +
|
|
|
|
"You earned " +
|
|
|
|
numeralWrapper.formatReputation(this.workRepGained) +
|
|
|
|
" rep, " +
|
|
|
|
numeralWrapper.formatExp(this.workHackExpGained) +
|
|
|
|
" hacking exp, " +
|
|
|
|
numeralWrapper.formatExp(this.workStrExpGained) +
|
|
|
|
" str exp, " +
|
|
|
|
numeralWrapper.formatExp(this.workDefExpGained) +
|
|
|
|
" def exp, " +
|
|
|
|
numeralWrapper.formatExp(this.workDexExpGained) +
|
|
|
|
" dex exp, " +
|
|
|
|
numeralWrapper.formatExp(this.workAgiExpGained) +
|
|
|
|
" agi exp, and " +
|
|
|
|
numeralWrapper.formatExp(this.workChaExpGained) +
|
|
|
|
" cha exp.";
|
2021-09-24 00:47:43 +02:00
|
|
|
|
2021-09-05 01:09:30 +02:00
|
|
|
return res;
|
|
|
|
}
|
2021-09-24 00:47:43 +02:00
|
|
|
return "";
|
2019-04-04 02:08:11 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//Money gained per game cycle
|
2021-09-24 00:47:43 +02:00
|
|
|
export function getWorkMoneyGain(this: IPlayer): number {
|
2021-09-05 01:09:30 +02:00
|
|
|
// If player has SF-11, calculate salary multiplier from favor
|
|
|
|
let bn11Mult = 1;
|
|
|
|
const company = Companies[this.companyName];
|
|
|
|
if (SourceFileFlags[11] > 0) {
|
|
|
|
bn11Mult = 1 + company.favor / 100;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get base salary
|
|
|
|
const companyPositionName = this.jobs[this.companyName];
|
|
|
|
const companyPosition = CompanyPositions[companyPositionName];
|
|
|
|
if (companyPosition == null) {
|
2021-09-09 05:47:34 +02:00
|
|
|
console.error(`Could not find CompanyPosition object for ${companyPositionName}. Work salary will be 0`);
|
2021-09-05 01:09:30 +02:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return (
|
|
|
|
companyPosition.baseSalary *
|
|
|
|
company.salaryMultiplier *
|
|
|
|
this.work_money_mult *
|
|
|
|
BitNodeMultipliers.CompanyWorkMoney *
|
|
|
|
bn11Mult
|
|
|
|
);
|
2019-04-04 02:08:11 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//Hack exp gained per game cycle
|
2021-09-24 00:47:43 +02:00
|
|
|
export function getWorkHackExpGain(this: IPlayer): number {
|
2021-09-05 01:09:30 +02:00
|
|
|
const company = Companies[this.companyName];
|
|
|
|
const companyPositionName = this.jobs[this.companyName];
|
|
|
|
const companyPosition = CompanyPositions[companyPositionName];
|
|
|
|
if (company == null || companyPosition == null) {
|
|
|
|
console.error(
|
|
|
|
[
|
|
|
|
`Could not find Company object for ${this.companyName}`,
|
|
|
|
`or CompanyPosition object for ${companyPositionName}.`,
|
|
|
|
`Work hack exp gain will be 0`,
|
|
|
|
].join(" "),
|
|
|
|
);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return (
|
|
|
|
companyPosition.hackingExpGain *
|
|
|
|
company.expMultiplier *
|
|
|
|
this.hacking_exp_mult *
|
|
|
|
BitNodeMultipliers.CompanyWorkExpGain
|
|
|
|
);
|
2019-04-04 02:08:11 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//Str exp gained per game cycle
|
2021-09-24 00:47:43 +02:00
|
|
|
export function getWorkStrExpGain(this: IPlayer): number {
|
2021-09-05 01:09:30 +02:00
|
|
|
const company = Companies[this.companyName];
|
|
|
|
const companyPositionName = this.jobs[this.companyName];
|
|
|
|
const companyPosition = CompanyPositions[companyPositionName];
|
|
|
|
if (company == null || companyPosition == null) {
|
|
|
|
console.error(
|
|
|
|
[
|
|
|
|
`Could not find Company object for ${this.companyName}`,
|
|
|
|
`or CompanyPosition object for ${companyPositionName}.`,
|
|
|
|
`Work str exp gain will be 0`,
|
|
|
|
].join(" "),
|
|
|
|
);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return (
|
|
|
|
companyPosition.strengthExpGain *
|
|
|
|
company.expMultiplier *
|
|
|
|
this.strength_exp_mult *
|
|
|
|
BitNodeMultipliers.CompanyWorkExpGain
|
|
|
|
);
|
2019-04-04 02:08:11 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//Def exp gained per game cycle
|
2021-09-24 00:47:43 +02:00
|
|
|
export function getWorkDefExpGain(this: IPlayer): number {
|
2021-09-05 01:09:30 +02:00
|
|
|
const company = Companies[this.companyName];
|
|
|
|
const companyPositionName = this.jobs[this.companyName];
|
|
|
|
const companyPosition = CompanyPositions[companyPositionName];
|
|
|
|
if (company == null || companyPosition == null) {
|
|
|
|
console.error(
|
|
|
|
[
|
|
|
|
`Could not find Company object for ${this.companyName}`,
|
|
|
|
`or CompanyPosition object for ${companyPositionName}.`,
|
|
|
|
`Work def exp gain will be 0`,
|
|
|
|
].join(" "),
|
|
|
|
);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return (
|
|
|
|
companyPosition.defenseExpGain *
|
|
|
|
company.expMultiplier *
|
|
|
|
this.defense_exp_mult *
|
|
|
|
BitNodeMultipliers.CompanyWorkExpGain
|
|
|
|
);
|
2019-04-04 02:08:11 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//Dex exp gained per game cycle
|
2021-09-24 00:47:43 +02:00
|
|
|
export function getWorkDexExpGain(this: IPlayer): number {
|
2021-09-05 01:09:30 +02:00
|
|
|
const company = Companies[this.companyName];
|
|
|
|
const companyPositionName = this.jobs[this.companyName];
|
|
|
|
const companyPosition = CompanyPositions[companyPositionName];
|
|
|
|
if (company == null || companyPosition == null) {
|
|
|
|
console.error(
|
|
|
|
[
|
|
|
|
`Could not find Company object for ${this.companyName}`,
|
|
|
|
`or CompanyPosition object for ${companyPositionName}.`,
|
|
|
|
`Work dex exp gain will be 0`,
|
|
|
|
].join(" "),
|
|
|
|
);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return (
|
|
|
|
companyPosition.dexterityExpGain *
|
|
|
|
company.expMultiplier *
|
|
|
|
this.dexterity_exp_mult *
|
|
|
|
BitNodeMultipliers.CompanyWorkExpGain
|
|
|
|
);
|
2019-04-04 02:08:11 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//Agi exp gained per game cycle
|
2021-09-24 00:47:43 +02:00
|
|
|
export function getWorkAgiExpGain(this: IPlayer): number {
|
2021-09-05 01:09:30 +02:00
|
|
|
const company = Companies[this.companyName];
|
|
|
|
const companyPositionName = this.jobs[this.companyName];
|
|
|
|
const companyPosition = CompanyPositions[companyPositionName];
|
|
|
|
if (company == null || companyPosition == null) {
|
|
|
|
console.error(
|
|
|
|
[
|
|
|
|
`Could not find Company object for ${this.companyName}`,
|
|
|
|
`or CompanyPosition object for ${companyPositionName}.`,
|
|
|
|
`Work agi exp gain will be 0`,
|
|
|
|
].join(" "),
|
|
|
|
);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return (
|
|
|
|
companyPosition.agilityExpGain *
|
|
|
|
company.expMultiplier *
|
|
|
|
this.agility_exp_mult *
|
|
|
|
BitNodeMultipliers.CompanyWorkExpGain
|
|
|
|
);
|
2019-04-04 02:08:11 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//Charisma exp gained per game cycle
|
2021-09-24 00:47:43 +02:00
|
|
|
export function getWorkChaExpGain(this: IPlayer): number {
|
2021-09-05 01:09:30 +02:00
|
|
|
const company = Companies[this.companyName];
|
|
|
|
const companyPositionName = this.jobs[this.companyName];
|
|
|
|
const companyPosition = CompanyPositions[companyPositionName];
|
|
|
|
if (company == null || companyPosition == null) {
|
|
|
|
console.error(
|
|
|
|
[
|
|
|
|
`Could not find Company object for ${this.companyName}`,
|
|
|
|
`or CompanyPosition object for ${companyPositionName}.`,
|
|
|
|
`Work cha exp gain will be 0`,
|
|
|
|
].join(" "),
|
|
|
|
);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return (
|
|
|
|
companyPosition.charismaExpGain *
|
|
|
|
company.expMultiplier *
|
|
|
|
this.charisma_exp_mult *
|
|
|
|
BitNodeMultipliers.CompanyWorkExpGain
|
|
|
|
);
|
2019-04-04 02:08:11 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//Reputation gained per game cycle
|
2021-09-24 00:47:43 +02:00
|
|
|
export function getWorkRepGain(this: IPlayer): number {
|
2021-09-05 01:09:30 +02:00
|
|
|
const company = Companies[this.companyName];
|
|
|
|
const companyPositionName = this.jobs[this.companyName];
|
|
|
|
const companyPosition = CompanyPositions[companyPositionName];
|
|
|
|
if (company == null || companyPosition == null) {
|
|
|
|
console.error(
|
|
|
|
[
|
|
|
|
`Could not find Company object for ${this.companyName}`,
|
|
|
|
`or CompanyPosition object for ${companyPositionName}.`,
|
|
|
|
`Work rep gain will be 0`,
|
|
|
|
].join(" "),
|
|
|
|
);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2021-09-25 07:26:03 +02:00
|
|
|
let jobPerformance = companyPosition.calculateJobPerformance(
|
2021-11-05 22:12:52 +01:00
|
|
|
this.hacking,
|
2021-09-05 01:09:30 +02:00
|
|
|
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
|
2021-09-25 07:26:03 +02:00
|
|
|
let favorMult = 1 + company.favor / 100;
|
2021-09-05 01:09:30 +02:00
|
|
|
if (isNaN(favorMult)) {
|
|
|
|
favorMult = 1;
|
|
|
|
}
|
|
|
|
return jobPerformance * this.company_rep_mult * favorMult;
|
2019-04-04 02:08:11 +02:00
|
|
|
}
|
|
|
|
|
2021-09-24 00:47:43 +02:00
|
|
|
// export function getFactionSecurityWorkRepGain(this: IPlayer) {
|
2021-11-05 22:12:52 +01:00
|
|
|
// var t = 0.9 * (this.hacking / CONSTANTS.MaxSkillLevel +
|
2021-04-18 17:18:56 +02:00
|
|
|
// this.strength / CONSTANTS.MaxSkillLevel +
|
|
|
|
// this.defense / CONSTANTS.MaxSkillLevel +
|
|
|
|
// this.dexterity / CONSTANTS.MaxSkillLevel +
|
|
|
|
// this.agility / CONSTANTS.MaxSkillLevel) / 4.5;
|
|
|
|
// return t * this.faction_rep_mult;
|
|
|
|
// }
|
|
|
|
|
2021-09-24 00:47:43 +02:00
|
|
|
// export function getFactionFieldWorkRepGain(this: IPlayer) {
|
2021-11-05 22:12:52 +01:00
|
|
|
// var t = 0.9 * (this.hacking / CONSTANTS.MaxSkillLevel +
|
2021-04-18 17:18:56 +02:00
|
|
|
// this.strength / CONSTANTS.MaxSkillLevel +
|
|
|
|
// this.defense / CONSTANTS.MaxSkillLevel +
|
|
|
|
// this.dexterity / CONSTANTS.MaxSkillLevel +
|
|
|
|
// this.agility / CONSTANTS.MaxSkillLevel +
|
|
|
|
// this.charisma / CONSTANTS.MaxSkillLevel +
|
|
|
|
// this.intelligence / CONSTANTS.MaxSkillLevel) / 5.5;
|
|
|
|
// return t * this.faction_rep_mult;
|
|
|
|
// }
|
2019-04-04 02:08:11 +02:00
|
|
|
|
|
|
|
/* Creating a Program */
|
2021-09-24 00:47:43 +02:00
|
|
|
export function startCreateProgramWork(
|
|
|
|
this: IPlayer,
|
|
|
|
router: IRouter,
|
|
|
|
programName: string,
|
|
|
|
time: number,
|
|
|
|
reqLevel: number,
|
|
|
|
): void {
|
2021-09-05 01:09:30 +02:00
|
|
|
this.resetWorkStatus();
|
|
|
|
this.isWorking = true;
|
|
|
|
this.focus = true;
|
|
|
|
this.workType = CONSTANTS.WorkTypeCreateProgram;
|
|
|
|
|
|
|
|
//Time needed to complete work affected by hacking skill (linearly based on
|
|
|
|
//ratio of (your skill - required level) to MAX skill)
|
2021-11-05 22:12:52 +01:00
|
|
|
//var timeMultiplier = (CONSTANTS.MaxSkillLevel - (this.hacking - reqLevel)) / CONSTANTS.MaxSkillLevel;
|
2021-09-05 01:09:30 +02:00
|
|
|
//if (timeMultiplier > 1) {timeMultiplier = 1;}
|
|
|
|
//if (timeMultiplier < 0.01) {timeMultiplier = 0.01;}
|
|
|
|
this.createProgramReqLvl = reqLevel;
|
|
|
|
|
|
|
|
this.timeNeededToCompleteWork = time;
|
|
|
|
//Check for incomplete program
|
2021-09-25 07:26:03 +02:00
|
|
|
for (let i = 0; i < this.getHomeComputer().programs.length; ++i) {
|
|
|
|
const programFile = this.getHomeComputer().programs[i];
|
2021-09-05 01:09:30 +02:00
|
|
|
if (programFile.startsWith(programName) && programFile.endsWith("%-INC")) {
|
2021-09-25 07:26:03 +02:00
|
|
|
const res = programFile.split("-");
|
2021-09-05 01:09:30 +02:00
|
|
|
if (res.length != 3) {
|
|
|
|
break;
|
|
|
|
}
|
2021-09-25 07:26:03 +02:00
|
|
|
const percComplete = Number(res[1].slice(0, -1));
|
2021-09-05 01:09:30 +02:00
|
|
|
if (isNaN(percComplete) || percComplete < 0 || percComplete >= 100) {
|
|
|
|
break;
|
|
|
|
}
|
2021-09-09 05:47:34 +02:00
|
|
|
this.timeWorkedCreateProgram = (percComplete / 100) * this.timeNeededToCompleteWork;
|
2021-09-05 01:09:30 +02:00
|
|
|
this.getHomeComputer().programs.splice(i, 1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
this.createProgramName = programName;
|
2021-09-20 07:45:32 +02:00
|
|
|
router.toWork();
|
2019-04-04 02:08:11 +02:00
|
|
|
}
|
|
|
|
|
2021-09-24 00:47:43 +02:00
|
|
|
export function createProgramWork(this: IPlayer, numCycles: number): boolean {
|
2021-09-05 01:09:30 +02:00
|
|
|
//Higher hacking skill will allow you to create programs faster
|
2021-09-25 07:26:03 +02:00
|
|
|
const reqLvl = this.createProgramReqLvl;
|
2021-11-05 22:12:52 +01:00
|
|
|
let skillMult = (this.hacking / reqLvl) * this.getIntelligenceBonus(3); //This should always be greater than 1;
|
2021-09-05 01:09:30 +02:00
|
|
|
skillMult = 1 + (skillMult - 1) / 5; //The divider constant can be adjusted as necessary
|
|
|
|
|
|
|
|
//Skill multiplier directly applied to "time worked"
|
2021-09-18 01:43:08 +02:00
|
|
|
this.timeWorked += CONSTANTS._idleSpeed * numCycles;
|
|
|
|
this.timeWorkedCreateProgram += CONSTANTS._idleSpeed * numCycles * skillMult;
|
2021-09-05 01:09:30 +02:00
|
|
|
|
|
|
|
if (this.timeWorkedCreateProgram >= this.timeNeededToCompleteWork) {
|
|
|
|
this.finishCreateProgramWork(false);
|
2021-09-18 18:13:20 +02:00
|
|
|
return true;
|
2021-09-05 01:09:30 +02:00
|
|
|
}
|
2021-09-18 18:13:20 +02:00
|
|
|
return false;
|
2019-04-04 02:08:11 +02:00
|
|
|
}
|
|
|
|
|
2021-09-24 00:47:43 +02:00
|
|
|
export function finishCreateProgramWork(this: IPlayer, cancelled: boolean): string {
|
2021-09-25 07:26:03 +02:00
|
|
|
const programName = this.createProgramName;
|
2021-09-05 01:09:30 +02:00
|
|
|
if (cancelled === false) {
|
|
|
|
dialogBoxCreate(
|
2021-09-09 05:47:34 +02:00
|
|
|
"You've finished creating " + programName + "!<br>" + "The new program can be found on your home computer.",
|
2021-09-05 01:09:30 +02:00
|
|
|
);
|
|
|
|
|
|
|
|
this.getHomeComputer().programs.push(programName);
|
|
|
|
} else {
|
2021-09-25 07:26:03 +02:00
|
|
|
const perc = (Math.floor((this.timeWorkedCreateProgram / this.timeNeededToCompleteWork) * 10000) / 100).toString();
|
|
|
|
const incompleteName = programName + "-" + perc + "%-INC";
|
2021-09-05 01:09:30 +02:00
|
|
|
this.getHomeComputer().programs.push(incompleteName);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!cancelled) {
|
2021-11-05 22:12:52 +01:00
|
|
|
this.gainIntelligenceExp((CONSTANTS.IntelligenceProgramBaseExpGain * this.timeWorked) / 1000);
|
2021-09-05 01:09:30 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
this.isWorking = false;
|
|
|
|
|
|
|
|
this.resetWorkStatus();
|
2021-09-24 00:47:43 +02:00
|
|
|
return "You've finished creating " + programName + "! The new program can be found on your home computer.";
|
2019-04-04 02:08:11 +02:00
|
|
|
}
|
|
|
|
/* Studying/Taking Classes */
|
2021-09-24 00:47:43 +02:00
|
|
|
export function startClass(this: IPlayer, router: IRouter, costMult: number, expMult: number, className: string): void {
|
2021-09-05 01:09:30 +02:00
|
|
|
this.resetWorkStatus();
|
|
|
|
this.isWorking = true;
|
|
|
|
this.focus = true;
|
|
|
|
this.workType = CONSTANTS.WorkTypeStudyClass;
|
2021-11-12 05:40:48 +01:00
|
|
|
this.workCostMult = costMult;
|
|
|
|
this.workExpMult = expMult;
|
2021-09-05 01:09:30 +02:00
|
|
|
this.className = className;
|
2021-11-12 05:40:48 +01:00
|
|
|
const earnings = calculateClassEarnings(this);
|
|
|
|
this.workMoneyLossRate = earnings.workMoneyLossRate;
|
|
|
|
this.workHackExpGainRate = earnings.workHackExpGainRate;
|
|
|
|
this.workStrExpGainRate = earnings.workStrExpGainRate;
|
|
|
|
this.workDefExpGainRate = earnings.workDefExpGainRate;
|
|
|
|
this.workDexExpGainRate = earnings.workDexExpGainRate;
|
|
|
|
this.workAgiExpGainRate = earnings.workAgiExpGainRate;
|
|
|
|
this.workChaExpGainRate = earnings.workChaExpGainRate;
|
2021-09-20 07:45:32 +02:00
|
|
|
router.toWork();
|
2019-04-04 02:08:11 +02:00
|
|
|
}
|
|
|
|
|
2021-09-24 00:47:43 +02:00
|
|
|
export function takeClass(this: IPlayer, numCycles: number): boolean {
|
2021-09-18 01:43:08 +02:00
|
|
|
this.timeWorked += CONSTANTS._idleSpeed * numCycles;
|
2021-11-12 05:40:48 +01:00
|
|
|
const earnings = calculateClassEarnings(this);
|
|
|
|
this.workMoneyLossRate = earnings.workMoneyLossRate;
|
|
|
|
this.workHackExpGainRate = earnings.workHackExpGainRate;
|
|
|
|
this.workStrExpGainRate = earnings.workStrExpGainRate;
|
|
|
|
this.workDefExpGainRate = earnings.workDefExpGainRate;
|
|
|
|
this.workDexExpGainRate = earnings.workDexExpGainRate;
|
|
|
|
this.workAgiExpGainRate = earnings.workAgiExpGainRate;
|
|
|
|
this.workChaExpGainRate = earnings.workChaExpGainRate;
|
2021-09-05 01:09:30 +02:00
|
|
|
this.processWorkEarnings(numCycles);
|
2021-09-18 18:13:20 +02:00
|
|
|
return false;
|
2019-04-04 02:08:11 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//The 'sing' argument defines whether or not this function was called
|
|
|
|
//through a Singularity Netscript function
|
2021-09-24 00:47:43 +02:00
|
|
|
export function finishClass(this: IPlayer, sing = false): string {
|
2021-09-09 05:47:34 +02:00
|
|
|
this.gainIntelligenceExp(CONSTANTS.IntelligenceClassBaseExpGain * Math.round(this.timeWorked / 1000));
|
2021-09-05 01:09:30 +02:00
|
|
|
|
|
|
|
if (this.workMoneyGained > 0) {
|
|
|
|
throw new Error("ERR: Somehow gained money while taking class");
|
|
|
|
}
|
|
|
|
|
|
|
|
this.updateSkillLevels();
|
|
|
|
if (!sing) {
|
|
|
|
dialogBoxCreate(
|
|
|
|
<>
|
2021-09-09 05:47:34 +02:00
|
|
|
After {this.className} for {convertTimeMsToTimeElapsedString(this.timeWorked)}, <br />
|
2021-09-05 01:09:30 +02:00
|
|
|
you spent a total of <Money money={-this.workMoneyGained} />. <br />
|
|
|
|
<br />
|
|
|
|
You earned a total of: <br />
|
|
|
|
{numeralWrapper.formatExp(this.workHackExpGained)} hacking exp <br />
|
|
|
|
{numeralWrapper.formatExp(this.workStrExpGained)} strength exp <br />
|
|
|
|
{numeralWrapper.formatExp(this.workDefExpGained)} defense exp <br />
|
|
|
|
{numeralWrapper.formatExp(this.workDexExpGained)} dexterity exp <br />
|
|
|
|
{numeralWrapper.formatExp(this.workAgiExpGained)} agility exp <br />
|
|
|
|
{numeralWrapper.formatExp(this.workChaExpGained)} charisma exp
|
|
|
|
<br />
|
|
|
|
</>,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
this.isWorking = false;
|
|
|
|
|
|
|
|
if (sing) {
|
2021-09-25 07:26:03 +02:00
|
|
|
const res =
|
2021-09-05 01:09:30 +02:00
|
|
|
"After " +
|
|
|
|
this.className +
|
|
|
|
" for " +
|
|
|
|
convertTimeMsToTimeElapsedString(this.timeWorked) +
|
|
|
|
", " +
|
|
|
|
"you spent a total of " +
|
|
|
|
numeralWrapper.formatMoney(this.workMoneyGained * -1) +
|
|
|
|
". " +
|
|
|
|
"You earned a total of: " +
|
|
|
|
numeralWrapper.formatExp(this.workHackExpGained) +
|
|
|
|
" hacking exp, " +
|
|
|
|
numeralWrapper.formatExp(this.workStrExpGained) +
|
|
|
|
" strength exp, " +
|
|
|
|
numeralWrapper.formatExp(this.workDefExpGained) +
|
|
|
|
" defense exp, " +
|
|
|
|
numeralWrapper.formatExp(this.workDexExpGained) +
|
|
|
|
" dexterity exp, " +
|
|
|
|
numeralWrapper.formatExp(this.workAgiExpGained) +
|
|
|
|
" agility exp, and " +
|
|
|
|
numeralWrapper.formatExp(this.workChaExpGained) +
|
|
|
|
" charisma exp";
|
2019-04-04 02:08:11 +02:00
|
|
|
this.resetWorkStatus();
|
2021-09-05 01:09:30 +02:00
|
|
|
return res;
|
|
|
|
}
|
|
|
|
this.resetWorkStatus();
|
2021-09-24 00:47:43 +02:00
|
|
|
return "";
|
2019-04-04 02:08:11 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//The EXP and $ gains are hardcoded. Time is in ms
|
2021-09-20 07:45:32 +02:00
|
|
|
export function startCrime(
|
2021-09-24 00:47:43 +02:00
|
|
|
this: IPlayer,
|
|
|
|
router: IRouter,
|
|
|
|
crimeType: string,
|
|
|
|
hackExp: number,
|
|
|
|
strExp: number,
|
|
|
|
defExp: number,
|
|
|
|
dexExp: number,
|
|
|
|
agiExp: number,
|
|
|
|
chaExp: number,
|
|
|
|
money: number,
|
|
|
|
time: number,
|
|
|
|
workerscript: WorkerScript | null = null,
|
|
|
|
): void {
|
2021-09-05 01:09:30 +02:00
|
|
|
this.crimeType = crimeType;
|
|
|
|
|
|
|
|
this.resetWorkStatus();
|
|
|
|
this.isWorking = true;
|
|
|
|
this.focus = true;
|
|
|
|
this.workType = CONSTANTS.WorkTypeCrime;
|
|
|
|
|
2021-09-24 00:47:43 +02:00
|
|
|
if (workerscript !== null) {
|
2021-09-05 01:09:30 +02:00
|
|
|
this.committingCrimeThruSingFn = true;
|
2021-09-24 00:47:43 +02:00
|
|
|
this.singFnCrimeWorkerScript = workerscript;
|
2021-09-05 01:09:30 +02:00
|
|
|
}
|
|
|
|
|
2021-09-09 05:47:34 +02:00
|
|
|
this.workHackExpGained = hackExp * this.hacking_exp_mult * BitNodeMultipliers.CrimeExpGain;
|
|
|
|
this.workStrExpGained = strExp * this.strength_exp_mult * BitNodeMultipliers.CrimeExpGain;
|
|
|
|
this.workDefExpGained = defExp * this.defense_exp_mult * BitNodeMultipliers.CrimeExpGain;
|
|
|
|
this.workDexExpGained = dexExp * this.dexterity_exp_mult * BitNodeMultipliers.CrimeExpGain;
|
|
|
|
this.workAgiExpGained = agiExp * this.agility_exp_mult * BitNodeMultipliers.CrimeExpGain;
|
|
|
|
this.workChaExpGained = chaExp * this.charisma_exp_mult * BitNodeMultipliers.CrimeExpGain;
|
|
|
|
this.workMoneyGained = money * this.crime_money_mult * BitNodeMultipliers.CrimeMoney;
|
2021-09-05 01:09:30 +02:00
|
|
|
|
|
|
|
this.timeNeededToCompleteWork = time;
|
2021-09-20 07:45:32 +02:00
|
|
|
router.toWork();
|
2019-04-04 02:08:11 +02:00
|
|
|
}
|
|
|
|
|
2021-09-24 00:47:43 +02:00
|
|
|
export function commitCrime(this: IPlayer, numCycles: number): boolean {
|
2021-09-18 01:43:08 +02:00
|
|
|
this.timeWorked += CONSTANTS._idleSpeed * numCycles;
|
2021-09-05 01:09:30 +02:00
|
|
|
|
2021-09-18 18:13:20 +02:00
|
|
|
if (this.timeWorked >= this.timeNeededToCompleteWork) {
|
|
|
|
this.finishCrime(false);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
2019-04-04 02:08:11 +02:00
|
|
|
}
|
|
|
|
|
2021-09-24 00:47:43 +02:00
|
|
|
export function finishCrime(this: IPlayer, cancelled: boolean): string {
|
2021-09-05 01:09:30 +02:00
|
|
|
//Determine crime success/failure
|
|
|
|
if (!cancelled) {
|
|
|
|
if (determineCrimeSuccess(this, this.crimeType)) {
|
|
|
|
//Handle Karma and crime statistics
|
|
|
|
let crime = null;
|
|
|
|
for (const i in Crimes) {
|
|
|
|
if (Crimes[i].type == this.crimeType) {
|
|
|
|
crime = Crimes[i];
|
|
|
|
break;
|
2019-04-04 02:08:11 +02:00
|
|
|
}
|
2021-09-05 01:09:30 +02:00
|
|
|
}
|
|
|
|
if (crime == null) {
|
|
|
|
dialogBoxCreate(
|
|
|
|
`ERR: Unrecognized crime type (${this.crimeType}). This is probably a bug please contact the developer`,
|
|
|
|
);
|
2021-09-24 00:47:43 +02:00
|
|
|
return "";
|
2021-09-05 01:09:30 +02:00
|
|
|
}
|
2021-10-27 20:18:33 +02:00
|
|
|
this.gainMoney(this.workMoneyGained, "crime");
|
2021-09-05 01:09:30 +02:00
|
|
|
this.karma -= crime.karma;
|
|
|
|
this.numPeopleKilled += crime.kills;
|
|
|
|
if (crime.intelligence_exp > 0) {
|
|
|
|
this.gainIntelligenceExp(crime.intelligence_exp);
|
|
|
|
}
|
|
|
|
|
|
|
|
//On a crime success, gain 2x exp
|
|
|
|
this.workHackExpGained *= 2;
|
|
|
|
this.workStrExpGained *= 2;
|
|
|
|
this.workDefExpGained *= 2;
|
|
|
|
this.workDexExpGained *= 2;
|
|
|
|
this.workAgiExpGained *= 2;
|
|
|
|
this.workChaExpGained *= 2;
|
2021-09-24 00:47:43 +02:00
|
|
|
const ws = this.singFnCrimeWorkerScript;
|
|
|
|
if (this.committingCrimeThruSingFn && ws !== null) {
|
|
|
|
if (ws.disableLogs.ALL == null && ws.disableLogs.commitCrime == null) {
|
|
|
|
ws.scriptRef.log(
|
2021-11-19 21:44:12 +01:00
|
|
|
"SUCCESS: Crime successful! Gained " +
|
2021-10-27 04:03:34 +02:00
|
|
|
numeralWrapper.formatMoney(this.workMoneyGained) +
|
|
|
|
", " +
|
|
|
|
numeralWrapper.formatExp(this.workHackExpGained) +
|
|
|
|
" hack exp, " +
|
|
|
|
numeralWrapper.formatExp(this.workStrExpGained) +
|
|
|
|
" str exp, " +
|
|
|
|
numeralWrapper.formatExp(this.workDefExpGained) +
|
|
|
|
" def exp, " +
|
|
|
|
numeralWrapper.formatExp(this.workDexExpGained) +
|
|
|
|
" dex exp, " +
|
|
|
|
numeralWrapper.formatExp(this.workAgiExpGained) +
|
|
|
|
" agi exp, " +
|
|
|
|
numeralWrapper.formatExp(this.workChaExpGained) +
|
|
|
|
" cha exp.",
|
2021-09-05 01:09:30 +02:00
|
|
|
);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
dialogBoxCreate(
|
|
|
|
<>
|
|
|
|
Crime successful!
|
|
|
|
<br />
|
|
|
|
<br />
|
|
|
|
You gained:
|
|
|
|
<br />
|
|
|
|
<Money money={this.workMoneyGained} />
|
|
|
|
<br />
|
2021-09-09 05:47:34 +02:00
|
|
|
{numeralWrapper.formatExp(this.workHackExpGained)} hacking experience <br />
|
|
|
|
{numeralWrapper.formatExp(this.workStrExpGained)} strength experience
|
2021-09-05 01:09:30 +02:00
|
|
|
<br />
|
|
|
|
{numeralWrapper.formatExp(this.workDefExpGained)} defense experience
|
|
|
|
<br />
|
2021-09-09 05:47:34 +02:00
|
|
|
{numeralWrapper.formatExp(this.workDexExpGained)} dexterity experience
|
2021-09-05 01:09:30 +02:00
|
|
|
<br />
|
|
|
|
{numeralWrapper.formatExp(this.workAgiExpGained)} agility experience
|
|
|
|
<br />
|
2021-09-09 05:47:34 +02:00
|
|
|
{numeralWrapper.formatExp(this.workChaExpGained)} charisma experience
|
2021-09-05 01:09:30 +02:00
|
|
|
</>,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
//Exp halved on failure
|
|
|
|
this.workHackExpGained /= 2;
|
|
|
|
this.workStrExpGained /= 2;
|
|
|
|
this.workDefExpGained /= 2;
|
|
|
|
this.workDexExpGained /= 2;
|
|
|
|
this.workAgiExpGained /= 2;
|
|
|
|
this.workChaExpGained /= 2;
|
2021-09-24 00:47:43 +02:00
|
|
|
const ws = this.singFnCrimeWorkerScript;
|
|
|
|
if (this.committingCrimeThruSingFn && ws !== null) {
|
|
|
|
if (ws.disableLogs.ALL == null && ws.disableLogs.commitCrime == null) {
|
|
|
|
ws.scriptRef.log(
|
2021-11-19 21:44:12 +01:00
|
|
|
"FAIL: Crime failed! Gained " +
|
2021-10-27 04:03:34 +02:00
|
|
|
numeralWrapper.formatExp(this.workHackExpGained) +
|
|
|
|
" hack exp, " +
|
|
|
|
numeralWrapper.formatExp(this.workStrExpGained) +
|
|
|
|
" str exp, " +
|
|
|
|
numeralWrapper.formatExp(this.workDefExpGained) +
|
|
|
|
" def exp, " +
|
|
|
|
numeralWrapper.formatExp(this.workDexExpGained) +
|
|
|
|
" dex exp, " +
|
|
|
|
numeralWrapper.formatExp(this.workAgiExpGained) +
|
|
|
|
" agi exp, " +
|
|
|
|
numeralWrapper.formatExp(this.workChaExpGained) +
|
|
|
|
" cha exp.",
|
2021-09-05 01:09:30 +02:00
|
|
|
);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
dialogBoxCreate(
|
|
|
|
<>
|
|
|
|
Crime failed!
|
|
|
|
<br />
|
|
|
|
<br />
|
|
|
|
You gained:
|
|
|
|
<br />
|
2021-09-09 05:47:34 +02:00
|
|
|
{numeralWrapper.formatExp(this.workHackExpGained)} hacking experience <br />
|
|
|
|
{numeralWrapper.formatExp(this.workStrExpGained)} strength experience
|
2021-09-05 01:09:30 +02:00
|
|
|
<br />
|
|
|
|
{numeralWrapper.formatExp(this.workDefExpGained)} defense experience
|
|
|
|
<br />
|
2021-09-09 05:47:34 +02:00
|
|
|
{numeralWrapper.formatExp(this.workDexExpGained)} dexterity experience
|
2021-09-05 01:09:30 +02:00
|
|
|
<br />
|
|
|
|
{numeralWrapper.formatExp(this.workAgiExpGained)} agility experience
|
|
|
|
<br />
|
2021-09-09 05:47:34 +02:00
|
|
|
{numeralWrapper.formatExp(this.workChaExpGained)} charisma experience
|
2021-09-05 01:09:30 +02:00
|
|
|
</>,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
this.gainHackingExp(this.workHackExpGained);
|
|
|
|
this.gainStrengthExp(this.workStrExpGained);
|
|
|
|
this.gainDefenseExp(this.workDefExpGained);
|
|
|
|
this.gainDexterityExp(this.workDexExpGained);
|
|
|
|
this.gainAgilityExp(this.workAgiExpGained);
|
|
|
|
this.gainCharismaExp(this.workChaExpGained);
|
|
|
|
}
|
|
|
|
this.committingCrimeThruSingFn = false;
|
|
|
|
this.singFnCrimeWorkerScript = null;
|
|
|
|
this.isWorking = false;
|
2021-09-18 01:43:08 +02:00
|
|
|
this.crimeType = "";
|
2021-09-05 01:09:30 +02:00
|
|
|
this.resetWorkStatus();
|
2021-09-24 00:47:43 +02:00
|
|
|
return "";
|
2019-04-04 02:08:11 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//Cancels the player's current "work" assignment and gives the proper rewards
|
|
|
|
//Used only for Singularity functions, so no popups are created
|
2021-09-24 00:47:43 +02:00
|
|
|
export function singularityStopWork(this: IPlayer): string {
|
2021-09-05 01:09:30 +02:00
|
|
|
if (!this.isWorking) {
|
|
|
|
return "";
|
|
|
|
}
|
2021-09-24 00:47:43 +02:00
|
|
|
let res = ""; //Earnings text for work
|
2021-09-05 01:09:30 +02:00
|
|
|
switch (this.workType) {
|
|
|
|
case CONSTANTS.WorkTypeStudyClass:
|
|
|
|
res = this.finishClass(true);
|
|
|
|
break;
|
|
|
|
case CONSTANTS.WorkTypeCompany:
|
|
|
|
res = this.finishWork(true, true);
|
|
|
|
break;
|
|
|
|
case CONSTANTS.WorkTypeCompanyPartTime:
|
|
|
|
res = this.finishWorkPartTime(true);
|
|
|
|
break;
|
|
|
|
case CONSTANTS.WorkTypeFaction:
|
|
|
|
res = this.finishFactionWork(true, true);
|
|
|
|
break;
|
|
|
|
case CONSTANTS.WorkTypeCreateProgram:
|
|
|
|
res = this.finishCreateProgramWork(true);
|
|
|
|
break;
|
|
|
|
case CONSTANTS.WorkTypeCrime:
|
|
|
|
res = this.finishCrime(true);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
console.error(`Unrecognized work type (${this.workType})`);
|
|
|
|
return "";
|
|
|
|
}
|
|
|
|
return res;
|
2019-04-04 02:08:11 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// Returns true if hospitalized, false otherwise
|
2021-09-24 00:47:43 +02:00
|
|
|
export function takeDamage(this: IPlayer, amt: number): boolean {
|
2021-09-05 01:09:30 +02:00
|
|
|
if (typeof amt !== "number") {
|
2021-09-09 05:47:34 +02:00
|
|
|
console.warn(`Player.takeDamage() called without a numeric argument: ${amt}`);
|
2021-09-24 00:47:43 +02:00
|
|
|
return false;
|
2021-09-05 01:09:30 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
this.hp -= amt;
|
|
|
|
if (this.hp <= 0) {
|
|
|
|
this.hospitalize();
|
|
|
|
return true;
|
|
|
|
} else {
|
|
|
|
return false;
|
|
|
|
}
|
2019-04-04 02:08:11 +02:00
|
|
|
}
|
|
|
|
|
2021-09-24 00:47:43 +02:00
|
|
|
export function regenerateHp(this: IPlayer, amt: number): void {
|
2021-09-05 01:09:30 +02:00
|
|
|
if (typeof amt !== "number") {
|
2021-09-09 05:47:34 +02:00
|
|
|
console.warn(`Player.regenerateHp() called without a numeric argument: ${amt}`);
|
2021-09-05 01:09:30 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
this.hp += amt;
|
|
|
|
if (this.hp > this.max_hp) {
|
|
|
|
this.hp = this.max_hp;
|
|
|
|
}
|
2019-04-04 02:08:11 +02:00
|
|
|
}
|
|
|
|
|
2021-09-24 00:47:43 +02:00
|
|
|
export function hospitalize(this: IPlayer): number {
|
2021-09-05 01:09:30 +02:00
|
|
|
const cost = getHospitalizationCost(this);
|
2021-11-11 01:28:20 +01:00
|
|
|
SnackbarEvents.emit(`You've been Hospitalized for ${numeralWrapper.formatMoney(cost)}`, "warning");
|
2021-09-05 01:09:30 +02:00
|
|
|
|
2021-10-27 20:18:33 +02:00
|
|
|
this.loseMoney(cost, "hospitalization");
|
2021-09-05 01:09:30 +02:00
|
|
|
this.hp = this.max_hp;
|
|
|
|
return cost;
|
2019-04-04 02:08:11 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/********* Company job application **********/
|
|
|
|
//Determines the job that the Player should get (if any) at the current company
|
|
|
|
//The 'sing' argument designates whether or not this is being called from
|
|
|
|
//the applyToCompany() Netscript Singularity function
|
2021-09-24 00:47:43 +02:00
|
|
|
export function applyForJob(this: IPlayer, entryPosType: CompanyPosition, sing = false): boolean {
|
2021-09-05 01:09:30 +02:00
|
|
|
// Get current company and job
|
|
|
|
let currCompany = null;
|
|
|
|
if (this.companyName !== "") {
|
|
|
|
currCompany = Companies[this.companyName];
|
|
|
|
}
|
|
|
|
const currPositionName = this.jobs[this.companyName];
|
|
|
|
|
|
|
|
// Get company that's being applied to
|
|
|
|
const company = Companies[this.location]; //Company being applied to
|
|
|
|
if (!(company instanceof Company)) {
|
2021-09-24 00:47:43 +02:00
|
|
|
console.error(`Could not find company that matches the location: ${this.location}. Player.applyToCompany() failed`);
|
|
|
|
return false;
|
2021-09-05 01:09:30 +02:00
|
|
|
}
|
2019-04-04 02:08:11 +02:00
|
|
|
|
2021-09-05 01:09:30 +02:00
|
|
|
let pos = entryPosType;
|
2019-04-04 02:08:11 +02:00
|
|
|
|
2021-09-05 01:09:30 +02:00
|
|
|
if (!this.isQualified(company, pos)) {
|
2021-09-24 00:47:43 +02:00
|
|
|
const reqText = getJobRequirementText(company, pos);
|
|
|
|
if (!sing) {
|
|
|
|
dialogBoxCreate("Unforunately, you do not qualify for this position<br>" + reqText);
|
2021-09-05 01:09:30 +02:00
|
|
|
}
|
2021-09-24 00:47:43 +02:00
|
|
|
return false;
|
2021-09-05 01:09:30 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
while (true) {
|
2021-09-25 07:26:03 +02:00
|
|
|
const newPos = getNextCompanyPositionHelper(pos);
|
2021-09-05 01:09:30 +02:00
|
|
|
if (newPos == null) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
//Check if this company has this position
|
|
|
|
if (company.hasPosition(newPos)) {
|
|
|
|
if (!this.isQualified(company, newPos)) {
|
|
|
|
//If player not qualified for next job, break loop so player will be given current job
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
pos = newPos;
|
|
|
|
} else {
|
|
|
|
break;
|
2019-04-04 02:08:11 +02:00
|
|
|
}
|
2021-09-05 01:09:30 +02:00
|
|
|
}
|
2019-04-04 02:08:11 +02:00
|
|
|
|
2021-09-05 01:09:30 +02:00
|
|
|
//Check if the determined job is the same as the player's current job
|
|
|
|
if (currCompany != null) {
|
|
|
|
if (currCompany.name == company.name && pos.name == currPositionName) {
|
2021-09-24 00:47:43 +02:00
|
|
|
const nextPos = getNextCompanyPositionHelper(pos);
|
2021-09-05 01:09:30 +02:00
|
|
|
if (nextPos == null) {
|
2021-09-24 00:47:43 +02:00
|
|
|
if (!sing) {
|
|
|
|
dialogBoxCreate("You are already at the highest position for your field! No promotion available");
|
2019-04-04 02:08:11 +02:00
|
|
|
}
|
2021-09-24 00:47:43 +02:00
|
|
|
return false;
|
2021-09-05 01:09:30 +02:00
|
|
|
} else if (company.hasPosition(nextPos)) {
|
2021-09-24 00:47:43 +02:00
|
|
|
if (!sing) {
|
2021-09-25 07:26:03 +02:00
|
|
|
const reqText = getJobRequirementText(company, nextPos);
|
2021-09-24 00:47:43 +02:00
|
|
|
dialogBoxCreate("Unfortunately, you do not qualify for a promotion<br>" + reqText);
|
2021-09-05 01:09:30 +02:00
|
|
|
}
|
2021-09-24 00:47:43 +02:00
|
|
|
return false;
|
2021-09-05 01:09:30 +02:00
|
|
|
} else {
|
2021-09-24 00:47:43 +02:00
|
|
|
if (!sing) {
|
|
|
|
dialogBoxCreate("You are already at the highest position for your field! No promotion available");
|
2019-04-04 02:08:11 +02:00
|
|
|
}
|
2021-09-24 00:47:43 +02:00
|
|
|
return false;
|
2021-09-05 01:09:30 +02:00
|
|
|
}
|
2021-09-24 00:47:43 +02:00
|
|
|
return false; //Same job, do nothing
|
2019-04-04 02:08:11 +02:00
|
|
|
}
|
2021-09-05 01:09:30 +02:00
|
|
|
}
|
2019-04-04 02:08:11 +02:00
|
|
|
|
2021-09-05 01:09:30 +02:00
|
|
|
this.jobs[company.name] = pos.name;
|
2021-10-27 04:03:34 +02:00
|
|
|
if (!this.focus && this.isWorking && this.companyName !== this.location) this.resetWorkStatus();
|
2021-09-05 01:09:30 +02:00
|
|
|
this.companyName = this.location;
|
2019-04-04 02:08:11 +02:00
|
|
|
|
2021-09-24 00:47:43 +02:00
|
|
|
if (!sing) {
|
|
|
|
dialogBoxCreate("Congratulations! You were offered a new job at " + this.companyName + " as a " + pos.name + "!");
|
2021-09-05 01:09:30 +02:00
|
|
|
}
|
2021-09-24 00:47:43 +02:00
|
|
|
return true;
|
2019-04-04 02:08:11 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//Returns your next position at a company given the field (software, business, etc.)
|
2021-09-24 00:47:43 +02:00
|
|
|
export function getNextCompanyPosition(
|
|
|
|
this: IPlayer,
|
|
|
|
company: Company,
|
|
|
|
entryPosType: CompanyPosition,
|
|
|
|
): CompanyPosition | null {
|
2021-09-25 07:26:03 +02:00
|
|
|
let currCompany = null;
|
2021-09-05 01:09:30 +02:00
|
|
|
if (this.companyName !== "") {
|
|
|
|
currCompany = Companies[this.companyName];
|
|
|
|
}
|
2019-04-04 02:08:11 +02:00
|
|
|
|
2021-09-05 01:09:30 +02:00
|
|
|
//Not employed at this company, so return the entry position
|
|
|
|
if (currCompany == null || currCompany.name != company.name) {
|
2019-04-04 02:08:11 +02:00
|
|
|
return entryPosType;
|
2021-09-05 01:09:30 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//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.
|
|
|
|
const currentPositionName = this.jobs[this.companyName];
|
|
|
|
const currentPosition = CompanyPositions[currentPositionName];
|
|
|
|
if (
|
|
|
|
(currentPosition.isSoftwareJob() && entryPosType.isSoftwareJob()) ||
|
|
|
|
(currentPosition.isITJob() && entryPosType.isITJob()) ||
|
|
|
|
(currentPosition.isBusinessJob() && entryPosType.isBusinessJob()) ||
|
2021-09-09 05:47:34 +02:00
|
|
|
(currentPosition.isSecurityEngineerJob() && entryPosType.isSecurityEngineerJob()) ||
|
|
|
|
(currentPosition.isNetworkEngineerJob() && entryPosType.isNetworkEngineerJob()) ||
|
2021-09-05 01:09:30 +02:00
|
|
|
(currentPosition.isSecurityJob() && entryPosType.isSecurityJob()) ||
|
|
|
|
(currentPosition.isAgentJob() && entryPosType.isAgentJob()) ||
|
2021-09-09 05:47:34 +02:00
|
|
|
(currentPosition.isSoftwareConsultantJob() && entryPosType.isSoftwareConsultantJob()) ||
|
|
|
|
(currentPosition.isBusinessConsultantJob() && entryPosType.isBusinessConsultantJob()) ||
|
2021-09-05 01:09:30 +02:00
|
|
|
(currentPosition.isPartTimeJob() && entryPosType.isPartTimeJob())
|
|
|
|
) {
|
|
|
|
return getNextCompanyPositionHelper(currentPosition);
|
|
|
|
}
|
|
|
|
|
|
|
|
return entryPosType;
|
2019-04-04 02:08:11 +02:00
|
|
|
}
|
|
|
|
|
2021-09-24 00:47:43 +02:00
|
|
|
export function quitJob(this: IPlayer, company: string): void {
|
2021-09-05 01:09:30 +02:00
|
|
|
this.isWorking = false;
|
|
|
|
this.companyName = "";
|
|
|
|
delete this.jobs[company];
|
|
|
|
}
|
|
|
|
|
2021-09-24 00:47:43 +02:00
|
|
|
export function applyForSoftwareJob(this: IPlayer, sing = false): boolean {
|
2021-09-09 05:47:34 +02:00
|
|
|
return this.applyForJob(CompanyPositions[posNames.SoftwareCompanyPositions[0]], sing);
|
2021-09-05 01:09:30 +02:00
|
|
|
}
|
|
|
|
|
2021-09-24 00:47:43 +02:00
|
|
|
export function applyForSoftwareConsultantJob(this: IPlayer, sing = false): boolean {
|
2021-09-09 05:47:34 +02:00
|
|
|
return this.applyForJob(CompanyPositions[posNames.SoftwareConsultantCompanyPositions[0]], sing);
|
2021-09-05 01:09:30 +02:00
|
|
|
}
|
|
|
|
|
2021-09-24 00:47:43 +02:00
|
|
|
export function applyForItJob(this: IPlayer, sing = false): boolean {
|
2021-09-09 05:47:34 +02:00
|
|
|
return this.applyForJob(CompanyPositions[posNames.ITCompanyPositions[0]], sing);
|
2021-09-05 01:09:30 +02:00
|
|
|
}
|
|
|
|
|
2021-09-24 00:47:43 +02:00
|
|
|
export function applyForSecurityEngineerJob(this: IPlayer, sing = false): boolean {
|
2021-09-25 07:26:03 +02:00
|
|
|
const company = Companies[this.location]; //Company being applied to
|
2021-09-09 05:47:34 +02:00
|
|
|
if (this.isQualified(company, CompanyPositions[posNames.SecurityEngineerCompanyPositions[0]])) {
|
|
|
|
return this.applyForJob(CompanyPositions[posNames.SecurityEngineerCompanyPositions[0]], sing);
|
2021-09-05 01:09:30 +02:00
|
|
|
} else {
|
2021-09-24 00:47:43 +02:00
|
|
|
if (!sing) {
|
|
|
|
dialogBoxCreate("Unforunately, you do not qualify for this position");
|
2021-09-05 01:09:30 +02:00
|
|
|
}
|
2021-09-24 00:47:43 +02:00
|
|
|
return false;
|
2021-09-05 01:09:30 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-09-24 00:47:43 +02:00
|
|
|
export function applyForNetworkEngineerJob(this: IPlayer, sing = false): boolean {
|
2021-09-25 07:26:03 +02:00
|
|
|
const company = Companies[this.location]; //Company being applied to
|
2021-09-09 05:47:34 +02:00
|
|
|
if (this.isQualified(company, CompanyPositions[posNames.NetworkEngineerCompanyPositions[0]])) {
|
2021-09-24 00:47:43 +02:00
|
|
|
const pos = CompanyPositions[posNames.NetworkEngineerCompanyPositions[0]];
|
|
|
|
return this.applyForJob(pos, sing);
|
2021-09-05 01:09:30 +02:00
|
|
|
} else {
|
2021-09-24 00:47:43 +02:00
|
|
|
if (!sing) {
|
|
|
|
dialogBoxCreate("Unforunately, you do not qualify for this position");
|
2021-09-05 01:09:30 +02:00
|
|
|
}
|
2021-09-24 00:47:43 +02:00
|
|
|
return false;
|
2021-09-05 01:09:30 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-09-24 00:47:43 +02:00
|
|
|
export function applyForBusinessJob(this: IPlayer, sing = false): boolean {
|
2021-09-09 05:47:34 +02:00
|
|
|
return this.applyForJob(CompanyPositions[posNames.BusinessCompanyPositions[0]], sing);
|
2021-09-05 01:09:30 +02:00
|
|
|
}
|
|
|
|
|
2021-09-24 00:47:43 +02:00
|
|
|
export function applyForBusinessConsultantJob(this: IPlayer, sing = false): boolean {
|
2021-09-09 05:47:34 +02:00
|
|
|
return this.applyForJob(CompanyPositions[posNames.BusinessConsultantCompanyPositions[0]], sing);
|
2021-09-05 01:09:30 +02:00
|
|
|
}
|
|
|
|
|
2021-09-24 00:47:43 +02:00
|
|
|
export function applyForSecurityJob(this: IPlayer, sing = false): boolean {
|
2021-09-05 01:09:30 +02:00
|
|
|
// TODO Police Jobs
|
|
|
|
// Indexing starts at 2 because 0 is for police officer
|
2021-09-09 05:47:34 +02:00
|
|
|
return this.applyForJob(CompanyPositions[posNames.SecurityCompanyPositions[2]], sing);
|
2021-09-05 01:09:30 +02:00
|
|
|
}
|
|
|
|
|
2021-09-24 00:47:43 +02:00
|
|
|
export function applyForAgentJob(this: IPlayer, sing = false): boolean {
|
2021-09-25 07:26:03 +02:00
|
|
|
const company = Companies[this.location]; //Company being applied to
|
2021-09-09 05:47:34 +02:00
|
|
|
if (this.isQualified(company, CompanyPositions[posNames.AgentCompanyPositions[0]])) {
|
2021-09-24 00:47:43 +02:00
|
|
|
const pos = CompanyPositions[posNames.AgentCompanyPositions[0]];
|
|
|
|
return this.applyForJob(pos, sing);
|
2021-09-05 01:09:30 +02:00
|
|
|
} else {
|
2021-09-24 00:47:43 +02:00
|
|
|
if (!sing) {
|
|
|
|
dialogBoxCreate("Unforunately, you do not qualify for this position");
|
2021-09-05 01:09:30 +02:00
|
|
|
}
|
2021-09-24 00:47:43 +02:00
|
|
|
return false;
|
2021-09-05 01:09:30 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-09-24 00:47:43 +02:00
|
|
|
export function applyForEmployeeJob(this: IPlayer, sing = false): boolean {
|
2021-09-25 07:26:03 +02:00
|
|
|
const company = Companies[this.location]; //Company being applied to
|
2021-09-09 05:47:34 +02:00
|
|
|
if (this.isQualified(company, CompanyPositions[posNames.MiscCompanyPositions[1]])) {
|
2021-09-05 01:09:30 +02:00
|
|
|
this.companyName = company.name;
|
|
|
|
this.jobs[company.name] = posNames.MiscCompanyPositions[1];
|
2021-09-24 00:47:43 +02:00
|
|
|
if (!sing) {
|
2021-12-14 04:26:22 +01:00
|
|
|
dialogBoxCreate("Congratulations, you are now employed at " + this.location);
|
2019-04-04 02:08:11 +02:00
|
|
|
}
|
2021-09-24 00:47:43 +02:00
|
|
|
|
|
|
|
return true;
|
2021-09-05 01:09:30 +02:00
|
|
|
} else {
|
2021-09-24 00:47:43 +02:00
|
|
|
if (!sing) {
|
|
|
|
dialogBoxCreate("Unforunately, you do not qualify for this position");
|
2019-04-04 02:08:11 +02:00
|
|
|
}
|
2021-09-24 00:47:43 +02:00
|
|
|
|
|
|
|
return false;
|
2021-09-05 01:09:30 +02:00
|
|
|
}
|
2019-04-04 02:08:11 +02:00
|
|
|
}
|
|
|
|
|
2021-09-24 00:47:43 +02:00
|
|
|
export function applyForPartTimeEmployeeJob(this: IPlayer, sing = false): boolean {
|
2021-09-25 07:26:03 +02:00
|
|
|
const company = Companies[this.location]; //Company being applied to
|
2021-09-09 05:47:34 +02:00
|
|
|
if (this.isQualified(company, CompanyPositions[posNames.PartTimeCompanyPositions[1]])) {
|
2021-09-05 01:09:30 +02:00
|
|
|
this.jobs[company.name] = posNames.PartTimeCompanyPositions[1];
|
2021-09-24 00:47:43 +02:00
|
|
|
if (!sing) {
|
2021-12-14 04:26:22 +01:00
|
|
|
dialogBoxCreate("Congratulations, you are now employed part-time at " + this.location);
|
2019-04-04 02:08:11 +02:00
|
|
|
}
|
2021-09-24 00:47:43 +02:00
|
|
|
|
|
|
|
return true;
|
2021-09-05 01:09:30 +02:00
|
|
|
} else {
|
2021-09-24 00:47:43 +02:00
|
|
|
if (!sing) {
|
|
|
|
dialogBoxCreate("Unforunately, you do not qualify for this position");
|
2021-09-05 01:09:30 +02:00
|
|
|
}
|
2021-09-24 00:47:43 +02:00
|
|
|
|
|
|
|
return false;
|
2021-09-05 01:09:30 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-09-24 00:47:43 +02:00
|
|
|
export function applyForWaiterJob(this: IPlayer, sing = false): boolean {
|
2021-09-25 07:26:03 +02:00
|
|
|
const company = Companies[this.location]; //Company being applied to
|
2021-09-09 05:47:34 +02:00
|
|
|
if (this.isQualified(company, CompanyPositions[posNames.MiscCompanyPositions[0]])) {
|
2021-09-05 01:09:30 +02:00
|
|
|
this.companyName = company.name;
|
|
|
|
this.jobs[company.name] = posNames.MiscCompanyPositions[0];
|
2021-09-24 00:47:43 +02:00
|
|
|
if (!sing) {
|
2021-12-14 04:26:22 +01:00
|
|
|
dialogBoxCreate("Congratulations, you are now employed as a waiter at " + this.location);
|
2019-04-04 02:08:11 +02:00
|
|
|
}
|
2021-09-24 00:47:43 +02:00
|
|
|
return true;
|
2021-09-05 01:09:30 +02:00
|
|
|
} else {
|
2021-09-24 00:47:43 +02:00
|
|
|
if (!sing) {
|
|
|
|
dialogBoxCreate("Unforunately, you do not qualify for this position");
|
2021-09-05 01:09:30 +02:00
|
|
|
}
|
2021-09-24 00:47:43 +02:00
|
|
|
return false;
|
2021-09-05 01:09:30 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-09-24 00:47:43 +02:00
|
|
|
export function applyForPartTimeWaiterJob(this: IPlayer, sing = false): boolean {
|
2021-09-25 07:26:03 +02:00
|
|
|
const company = Companies[this.location]; //Company being applied to
|
2021-09-09 05:47:34 +02:00
|
|
|
if (this.isQualified(company, CompanyPositions[posNames.PartTimeCompanyPositions[0]])) {
|
2021-09-05 01:09:30 +02:00
|
|
|
this.companyName = company.name;
|
|
|
|
this.jobs[company.name] = posNames.PartTimeCompanyPositions[0];
|
2021-09-24 00:47:43 +02:00
|
|
|
if (!sing) {
|
2021-12-14 04:26:22 +01:00
|
|
|
dialogBoxCreate("Congratulations, you are now employed as a part-time waiter at " + this.location);
|
2019-04-04 02:08:11 +02:00
|
|
|
}
|
2021-09-24 00:47:43 +02:00
|
|
|
return true;
|
2021-09-05 01:09:30 +02:00
|
|
|
} else {
|
2021-09-24 00:47:43 +02:00
|
|
|
if (!sing) {
|
|
|
|
dialogBoxCreate("Unforunately, you do not qualify for this position");
|
2019-04-04 02:08:11 +02:00
|
|
|
}
|
2021-09-24 00:47:43 +02:00
|
|
|
return false;
|
2021-09-05 01:09:30 +02:00
|
|
|
}
|
2019-04-04 02:08:11 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//Checks if the Player is qualified for a certain position
|
2021-09-24 00:47:43 +02:00
|
|
|
export function isQualified(this: IPlayer, company: Company, position: CompanyPosition): boolean {
|
2021-09-25 07:26:03 +02:00
|
|
|
const offset = company.jobStatReqOffset;
|
|
|
|
const reqHacking = position.requiredHacking > 0 ? position.requiredHacking + offset : 0;
|
|
|
|
const reqStrength = position.requiredStrength > 0 ? position.requiredStrength + offset : 0;
|
|
|
|
const reqDefense = position.requiredDefense > 0 ? position.requiredDefense + offset : 0;
|
|
|
|
const reqDexterity = position.requiredDexterity > 0 ? position.requiredDexterity + offset : 0;
|
|
|
|
const reqAgility = position.requiredDexterity > 0 ? position.requiredDexterity + offset : 0;
|
|
|
|
const reqCharisma = position.requiredCharisma > 0 ? position.requiredCharisma + offset : 0;
|
2021-09-05 01:09:30 +02:00
|
|
|
|
|
|
|
if (
|
2021-11-05 22:12:52 +01:00
|
|
|
this.hacking >= reqHacking &&
|
2021-09-05 01:09:30 +02:00
|
|
|
this.strength >= reqStrength &&
|
|
|
|
this.defense >= reqDefense &&
|
|
|
|
this.dexterity >= reqDexterity &&
|
|
|
|
this.agility >= reqAgility &&
|
|
|
|
this.charisma >= reqCharisma &&
|
|
|
|
company.playerReputation >= position.requiredReputation
|
|
|
|
) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
2019-04-04 02:08:11 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/********** Reapplying Augmentations and Source File ***********/
|
2021-09-24 00:47:43 +02:00
|
|
|
export function reapplyAllAugmentations(this: IPlayer, resetMultipliers = true): void {
|
2021-09-05 01:09:30 +02:00
|
|
|
if (resetMultipliers) {
|
|
|
|
this.resetMultipliers();
|
|
|
|
}
|
|
|
|
|
|
|
|
for (let i = 0; i < this.augmentations.length; ++i) {
|
|
|
|
//Compatibility with new version
|
2021-09-09 05:47:34 +02:00
|
|
|
if (this.augmentations[i].name === "HacknetNode NIC Architecture Neural-Upload") {
|
|
|
|
this.augmentations[i].name = "Hacknet Node NIC Architecture Neural-Upload";
|
2021-09-05 01:09:30 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
const augName = this.augmentations[i].name;
|
2021-09-25 07:26:03 +02:00
|
|
|
const aug = Augmentations[augName];
|
2021-09-05 01:09:30 +02:00
|
|
|
if (aug == null) {
|
2021-09-09 05:47:34 +02:00
|
|
|
console.warn(`Invalid augmentation name in Player.reapplyAllAugmentations(). Aug ${augName} will be skipped`);
|
2021-09-05 01:09:30 +02:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
aug.owned = true;
|
|
|
|
if (aug.name == AugmentationNames.NeuroFluxGovernor) {
|
|
|
|
for (let j = 0; j < aug.level; ++j) {
|
2019-04-04 02:08:11 +02:00
|
|
|
applyAugmentation(this.augmentations[i], true);
|
2021-09-05 01:09:30 +02:00
|
|
|
}
|
|
|
|
continue;
|
2019-04-04 02:08:11 +02:00
|
|
|
}
|
2021-09-05 01:09:30 +02:00
|
|
|
applyAugmentation(this.augmentations[i], true);
|
|
|
|
}
|
2021-09-16 19:41:48 +02:00
|
|
|
|
|
|
|
this.updateSkillLevels();
|
2019-04-04 02:08:11 +02:00
|
|
|
}
|
|
|
|
|
2021-09-24 00:47:43 +02:00
|
|
|
export function reapplyAllSourceFiles(this: IPlayer): void {
|
2021-09-05 01:09:30 +02:00
|
|
|
//Will always be called after reapplyAllAugmentations() so multipliers do not have to be reset
|
|
|
|
//this.resetMultipliers();
|
|
|
|
|
|
|
|
for (let i = 0; i < this.sourceFiles.length; ++i) {
|
2021-09-25 07:26:03 +02:00
|
|
|
const srcFileKey = "SourceFile" + this.sourceFiles[i].n;
|
|
|
|
const sourceFileObject = SourceFiles[srcFileKey];
|
2021-09-05 01:09:30 +02:00
|
|
|
if (sourceFileObject == null) {
|
|
|
|
console.error(`Invalid source file number: ${this.sourceFiles[i].n}`);
|
|
|
|
continue;
|
2019-04-04 02:08:11 +02:00
|
|
|
}
|
2021-09-05 01:09:30 +02:00
|
|
|
applySourceFile(this.sourceFiles[i]);
|
|
|
|
}
|
|
|
|
applyExploit();
|
2021-11-05 22:12:52 +01:00
|
|
|
this.updateSkillLevels();
|
2019-04-04 02:08:11 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*************** Check for Faction Invitations *************/
|
|
|
|
//This function sets the requirements to join a Faction. It checks whether the Player meets
|
|
|
|
//those requirements and will return an array of all factions that the Player should
|
|
|
|
//receive an invitation to
|
2021-09-25 00:29:25 +02:00
|
|
|
export function checkForFactionInvitations(this: IPlayer): Faction[] {
|
2021-09-25 07:26:03 +02:00
|
|
|
const invitedFactions: Faction[] = []; //Array which will hold all Factions the player should be invited to
|
2019-04-04 02:08:11 +02:00
|
|
|
|
2021-09-25 07:26:03 +02:00
|
|
|
const numAugmentations = this.augmentations.length;
|
2019-04-04 02:08:11 +02:00
|
|
|
|
2021-09-05 01:09:30 +02:00
|
|
|
const allCompanies = Object.keys(this.jobs);
|
|
|
|
const allPositions = Object.values(this.jobs);
|
2019-04-04 02:08:11 +02:00
|
|
|
|
2021-09-05 01:09:30 +02:00
|
|
|
// Given a company name, safely returns the reputation (returns 0 if invalid company is specified)
|
2021-09-24 00:47:43 +02:00
|
|
|
function getCompanyRep(companyName: string): number {
|
2021-09-05 01:09:30 +02:00
|
|
|
const company = Companies[companyName];
|
|
|
|
if (company == null) {
|
|
|
|
return 0;
|
2019-04-04 02:08:11 +02:00
|
|
|
} else {
|
2021-09-05 01:09:30 +02:00
|
|
|
return company.playerReputation;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Helper function that returns a boolean indicating whether the Player meets
|
|
|
|
// the requirements for the specified company. There are two requirements:
|
|
|
|
// 1. High enough reputation
|
|
|
|
// 2. Player is employed at the company
|
2021-09-24 00:47:43 +02:00
|
|
|
function checkMegacorpRequirements(companyName: string, repNeeded = CONSTANTS.CorpFactionRepRequirement): boolean {
|
2021-09-09 05:47:34 +02:00
|
|
|
return allCompanies.includes(companyName) && getCompanyRep(companyName) > repNeeded;
|
2021-09-05 01:09:30 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//Illuminati
|
2021-09-25 07:26:03 +02:00
|
|
|
const illuminatiFac = Factions["Illuminati"];
|
2021-09-05 01:09:30 +02:00
|
|
|
if (
|
|
|
|
!illuminatiFac.isBanned &&
|
|
|
|
!illuminatiFac.isMember &&
|
|
|
|
!illuminatiFac.alreadyInvited &&
|
|
|
|
numAugmentations >= 30 &&
|
2021-11-12 03:35:26 +01:00
|
|
|
this.money >= 150000000000 &&
|
2021-11-05 22:12:52 +01:00
|
|
|
this.hacking >= 1500 &&
|
2021-09-05 01:09:30 +02:00
|
|
|
this.strength >= 1200 &&
|
|
|
|
this.defense >= 1200 &&
|
|
|
|
this.dexterity >= 1200 &&
|
|
|
|
this.agility >= 1200
|
|
|
|
) {
|
|
|
|
invitedFactions.push(illuminatiFac);
|
|
|
|
}
|
|
|
|
|
|
|
|
//Daedalus
|
2021-09-25 07:26:03 +02:00
|
|
|
const daedalusFac = Factions["Daedalus"];
|
2021-09-05 01:09:30 +02:00
|
|
|
if (
|
|
|
|
!daedalusFac.isBanned &&
|
|
|
|
!daedalusFac.isMember &&
|
|
|
|
!daedalusFac.alreadyInvited &&
|
2021-09-09 05:47:34 +02:00
|
|
|
numAugmentations >= Math.round(30 * BitNodeMultipliers.DaedalusAugsRequirement) &&
|
2021-11-12 03:35:26 +01:00
|
|
|
this.money >= 100000000000 &&
|
2021-11-05 22:12:52 +01:00
|
|
|
(this.hacking >= 2500 ||
|
2021-09-09 05:47:34 +02:00
|
|
|
(this.strength >= 1500 && this.defense >= 1500 && this.dexterity >= 1500 && this.agility >= 1500))
|
2021-09-05 01:09:30 +02:00
|
|
|
) {
|
|
|
|
invitedFactions.push(daedalusFac);
|
|
|
|
}
|
|
|
|
|
|
|
|
//The Covenant
|
2021-09-25 07:26:03 +02:00
|
|
|
const covenantFac = Factions["The Covenant"];
|
2021-09-05 01:09:30 +02:00
|
|
|
if (
|
|
|
|
!covenantFac.isBanned &&
|
|
|
|
!covenantFac.isMember &&
|
|
|
|
!covenantFac.alreadyInvited &&
|
|
|
|
numAugmentations >= 20 &&
|
2021-11-12 03:35:26 +01:00
|
|
|
this.money >= 75000000000 &&
|
2021-11-05 22:12:52 +01:00
|
|
|
this.hacking >= 850 &&
|
2021-09-05 01:09:30 +02:00
|
|
|
this.strength >= 850 &&
|
|
|
|
this.defense >= 850 &&
|
|
|
|
this.dexterity >= 850 &&
|
|
|
|
this.agility >= 850
|
|
|
|
) {
|
|
|
|
invitedFactions.push(covenantFac);
|
|
|
|
}
|
|
|
|
|
|
|
|
//ECorp
|
2021-09-25 07:26:03 +02:00
|
|
|
const ecorpFac = Factions["ECorp"];
|
2021-09-05 01:09:30 +02:00
|
|
|
if (
|
|
|
|
!ecorpFac.isBanned &&
|
|
|
|
!ecorpFac.isMember &&
|
|
|
|
!ecorpFac.alreadyInvited &&
|
|
|
|
checkMegacorpRequirements(LocationName.AevumECorp)
|
|
|
|
) {
|
|
|
|
invitedFactions.push(ecorpFac);
|
|
|
|
}
|
|
|
|
|
|
|
|
//MegaCorp
|
2021-09-25 07:26:03 +02:00
|
|
|
const megacorpFac = Factions["MegaCorp"];
|
2021-09-05 01:09:30 +02:00
|
|
|
if (
|
|
|
|
!megacorpFac.isBanned &&
|
|
|
|
!megacorpFac.isMember &&
|
|
|
|
!megacorpFac.alreadyInvited &&
|
|
|
|
checkMegacorpRequirements(LocationName.Sector12MegaCorp)
|
|
|
|
) {
|
|
|
|
invitedFactions.push(megacorpFac);
|
|
|
|
}
|
|
|
|
|
|
|
|
//Bachman & Associates
|
2021-09-25 07:26:03 +02:00
|
|
|
const bachmanandassociatesFac = Factions["Bachman & Associates"];
|
2021-09-05 01:09:30 +02:00
|
|
|
if (
|
|
|
|
!bachmanandassociatesFac.isBanned &&
|
|
|
|
!bachmanandassociatesFac.isMember &&
|
|
|
|
!bachmanandassociatesFac.alreadyInvited &&
|
|
|
|
checkMegacorpRequirements(LocationName.AevumBachmanAndAssociates)
|
|
|
|
) {
|
|
|
|
invitedFactions.push(bachmanandassociatesFac);
|
|
|
|
}
|
|
|
|
|
|
|
|
//Blade Industries
|
2021-09-25 07:26:03 +02:00
|
|
|
const bladeindustriesFac = Factions["Blade Industries"];
|
2021-09-05 01:09:30 +02:00
|
|
|
if (
|
|
|
|
!bladeindustriesFac.isBanned &&
|
|
|
|
!bladeindustriesFac.isMember &&
|
|
|
|
!bladeindustriesFac.alreadyInvited &&
|
|
|
|
checkMegacorpRequirements(LocationName.Sector12BladeIndustries)
|
|
|
|
) {
|
|
|
|
invitedFactions.push(bladeindustriesFac);
|
|
|
|
}
|
|
|
|
|
|
|
|
//NWO
|
2021-09-25 07:26:03 +02:00
|
|
|
const nwoFac = Factions["NWO"];
|
2021-09-05 01:09:30 +02:00
|
|
|
if (
|
|
|
|
!nwoFac.isBanned &&
|
|
|
|
!nwoFac.isMember &&
|
|
|
|
!nwoFac.alreadyInvited &&
|
|
|
|
checkMegacorpRequirements(LocationName.VolhavenNWO)
|
|
|
|
) {
|
|
|
|
invitedFactions.push(nwoFac);
|
|
|
|
}
|
|
|
|
|
|
|
|
//Clarke Incorporated
|
2021-09-25 07:26:03 +02:00
|
|
|
const clarkeincorporatedFac = Factions["Clarke Incorporated"];
|
2021-09-05 01:09:30 +02:00
|
|
|
if (
|
|
|
|
!clarkeincorporatedFac.isBanned &&
|
|
|
|
!clarkeincorporatedFac.isMember &&
|
|
|
|
!clarkeincorporatedFac.alreadyInvited &&
|
|
|
|
checkMegacorpRequirements(LocationName.AevumClarkeIncorporated)
|
|
|
|
) {
|
|
|
|
invitedFactions.push(clarkeincorporatedFac);
|
|
|
|
}
|
|
|
|
|
|
|
|
//OmniTek Incorporated
|
2021-09-25 07:26:03 +02:00
|
|
|
const omnitekincorporatedFac = Factions["OmniTek Incorporated"];
|
2021-09-05 01:09:30 +02:00
|
|
|
if (
|
|
|
|
!omnitekincorporatedFac.isBanned &&
|
|
|
|
!omnitekincorporatedFac.isMember &&
|
|
|
|
!omnitekincorporatedFac.alreadyInvited &&
|
|
|
|
checkMegacorpRequirements(LocationName.VolhavenOmniTekIncorporated)
|
|
|
|
) {
|
|
|
|
invitedFactions.push(omnitekincorporatedFac);
|
|
|
|
}
|
|
|
|
|
|
|
|
//Four Sigma
|
2021-09-25 07:26:03 +02:00
|
|
|
const foursigmaFac = Factions["Four Sigma"];
|
2021-09-05 01:09:30 +02:00
|
|
|
if (
|
|
|
|
!foursigmaFac.isBanned &&
|
|
|
|
!foursigmaFac.isMember &&
|
|
|
|
!foursigmaFac.alreadyInvited &&
|
|
|
|
checkMegacorpRequirements(LocationName.Sector12FourSigma)
|
|
|
|
) {
|
|
|
|
invitedFactions.push(foursigmaFac);
|
|
|
|
}
|
|
|
|
|
|
|
|
//KuaiGong International
|
2021-09-25 07:26:03 +02:00
|
|
|
const kuaigonginternationalFac = Factions["KuaiGong International"];
|
2021-09-05 01:09:30 +02:00
|
|
|
if (
|
|
|
|
!kuaigonginternationalFac.isBanned &&
|
|
|
|
!kuaigonginternationalFac.isMember &&
|
|
|
|
!kuaigonginternationalFac.alreadyInvited &&
|
|
|
|
checkMegacorpRequirements(LocationName.ChongqingKuaiGongInternational)
|
|
|
|
) {
|
|
|
|
invitedFactions.push(kuaigonginternationalFac);
|
|
|
|
}
|
|
|
|
|
|
|
|
//Fulcrum Secret Technologies - If u've unlocked fulcrum secret technolgoies server and have a high rep with the company
|
2021-09-24 00:47:43 +02:00
|
|
|
const fulcrumsecrettechonologiesFac = Factions["Fulcrum Secret Technologies"];
|
2021-10-07 23:55:49 +02:00
|
|
|
const fulcrumSecretServer = GetServer(SpecialServers.FulcrumSecretTechnologies);
|
2021-09-24 00:47:43 +02:00
|
|
|
if (!(fulcrumSecretServer instanceof Server)) throw new Error("Fulcrum Secret Technologies should be normal server");
|
2021-09-05 01:09:30 +02:00
|
|
|
if (fulcrumSecretServer == null) {
|
|
|
|
console.error("Could not find Fulcrum Secret Technologies Server");
|
|
|
|
} else {
|
|
|
|
if (
|
|
|
|
!fulcrumsecrettechonologiesFac.isBanned &&
|
|
|
|
!fulcrumsecrettechonologiesFac.isMember &&
|
|
|
|
!fulcrumsecrettechonologiesFac.alreadyInvited &&
|
|
|
|
fulcrumSecretServer.backdoorInstalled &&
|
|
|
|
checkMegacorpRequirements(LocationName.AevumFulcrumTechnologies, 250e3)
|
|
|
|
) {
|
|
|
|
invitedFactions.push(fulcrumsecrettechonologiesFac);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//BitRunners
|
2021-09-24 00:47:43 +02:00
|
|
|
const bitrunnersFac = Factions["BitRunners"];
|
2021-10-07 23:55:49 +02:00
|
|
|
const bitrunnersServer = GetServer(SpecialServers.BitRunnersServer);
|
2021-09-24 00:47:43 +02:00
|
|
|
if (!(bitrunnersServer instanceof Server)) throw new Error("BitRunners should be normal server");
|
2021-09-05 01:09:30 +02:00
|
|
|
if (bitrunnersServer == null) {
|
|
|
|
console.error("Could not find BitRunners Server");
|
|
|
|
} else if (
|
|
|
|
!bitrunnersFac.isBanned &&
|
|
|
|
!bitrunnersFac.isMember &&
|
|
|
|
bitrunnersServer.backdoorInstalled &&
|
2021-09-07 19:22:39 +02:00
|
|
|
!bitrunnersFac.alreadyInvited
|
2021-09-05 01:09:30 +02:00
|
|
|
) {
|
|
|
|
invitedFactions.push(bitrunnersFac);
|
|
|
|
}
|
|
|
|
|
|
|
|
//The Black Hand
|
2021-09-24 00:47:43 +02:00
|
|
|
|
|
|
|
const theblackhandFac = Factions["The Black Hand"];
|
2021-10-07 23:55:49 +02:00
|
|
|
const blackhandServer = GetServer(SpecialServers.TheBlackHandServer);
|
2021-09-24 00:47:43 +02:00
|
|
|
if (!(blackhandServer instanceof Server)) throw new Error("TheBlackHand should be normal server");
|
2021-09-05 01:09:30 +02:00
|
|
|
if (blackhandServer == null) {
|
|
|
|
console.error("Could not find The Black Hand Server");
|
|
|
|
} else if (
|
|
|
|
!theblackhandFac.isBanned &&
|
|
|
|
!theblackhandFac.isMember &&
|
|
|
|
blackhandServer.backdoorInstalled &&
|
2021-09-07 19:22:39 +02:00
|
|
|
!theblackhandFac.alreadyInvited
|
2021-09-05 01:09:30 +02:00
|
|
|
) {
|
|
|
|
invitedFactions.push(theblackhandFac);
|
|
|
|
}
|
|
|
|
|
|
|
|
//NiteSec
|
2021-09-24 00:47:43 +02:00
|
|
|
const nitesecFac = Factions["NiteSec"];
|
2021-10-07 23:55:49 +02:00
|
|
|
const nitesecServer = GetServer(SpecialServers.NiteSecServer);
|
2021-09-24 00:47:43 +02:00
|
|
|
if (!(nitesecServer instanceof Server)) throw new Error("NiteSec should be normal server");
|
2021-09-05 01:09:30 +02:00
|
|
|
if (nitesecServer == null) {
|
|
|
|
console.error("Could not find NiteSec Server");
|
|
|
|
} else if (
|
|
|
|
!nitesecFac.isBanned &&
|
|
|
|
!nitesecFac.isMember &&
|
|
|
|
nitesecServer.backdoorInstalled &&
|
2021-09-07 19:22:39 +02:00
|
|
|
!nitesecFac.alreadyInvited
|
2021-09-05 01:09:30 +02:00
|
|
|
) {
|
|
|
|
invitedFactions.push(nitesecFac);
|
|
|
|
}
|
|
|
|
|
|
|
|
//Chongqing
|
2021-09-25 07:26:03 +02:00
|
|
|
const chongqingFac = Factions["Chongqing"];
|
2021-09-05 01:09:30 +02:00
|
|
|
if (
|
|
|
|
!chongqingFac.isBanned &&
|
|
|
|
!chongqingFac.isMember &&
|
|
|
|
!chongqingFac.alreadyInvited &&
|
2021-11-12 03:35:26 +01:00
|
|
|
this.money >= 20000000 &&
|
2021-09-05 01:09:30 +02:00
|
|
|
this.city == CityName.Chongqing
|
|
|
|
) {
|
|
|
|
invitedFactions.push(chongqingFac);
|
|
|
|
}
|
|
|
|
|
|
|
|
//Sector-12
|
2021-09-25 07:26:03 +02:00
|
|
|
const sector12Fac = Factions["Sector-12"];
|
2021-09-05 01:09:30 +02:00
|
|
|
if (
|
|
|
|
!sector12Fac.isBanned &&
|
|
|
|
!sector12Fac.isMember &&
|
|
|
|
!sector12Fac.alreadyInvited &&
|
2021-11-12 03:35:26 +01:00
|
|
|
this.money >= 15000000 &&
|
2021-09-05 01:09:30 +02:00
|
|
|
this.city == CityName.Sector12
|
|
|
|
) {
|
|
|
|
invitedFactions.push(sector12Fac);
|
|
|
|
}
|
|
|
|
|
|
|
|
//New Tokyo
|
2021-09-25 07:26:03 +02:00
|
|
|
const newtokyoFac = Factions["New Tokyo"];
|
2021-09-05 01:09:30 +02:00
|
|
|
if (
|
|
|
|
!newtokyoFac.isBanned &&
|
|
|
|
!newtokyoFac.isMember &&
|
|
|
|
!newtokyoFac.alreadyInvited &&
|
2021-11-12 03:35:26 +01:00
|
|
|
this.money >= 20000000 &&
|
2021-09-05 01:09:30 +02:00
|
|
|
this.city == CityName.NewTokyo
|
|
|
|
) {
|
|
|
|
invitedFactions.push(newtokyoFac);
|
|
|
|
}
|
|
|
|
|
|
|
|
//Aevum
|
2021-09-25 07:26:03 +02:00
|
|
|
const aevumFac = Factions["Aevum"];
|
2021-09-05 01:09:30 +02:00
|
|
|
if (
|
|
|
|
!aevumFac.isBanned &&
|
|
|
|
!aevumFac.isMember &&
|
|
|
|
!aevumFac.alreadyInvited &&
|
2021-11-12 03:35:26 +01:00
|
|
|
this.money >= 40000000 &&
|
2021-09-05 01:09:30 +02:00
|
|
|
this.city == CityName.Aevum
|
|
|
|
) {
|
|
|
|
invitedFactions.push(aevumFac);
|
|
|
|
}
|
|
|
|
|
|
|
|
//Ishima
|
2021-09-25 07:26:03 +02:00
|
|
|
const ishimaFac = Factions["Ishima"];
|
2021-09-05 01:09:30 +02:00
|
|
|
if (
|
|
|
|
!ishimaFac.isBanned &&
|
|
|
|
!ishimaFac.isMember &&
|
|
|
|
!ishimaFac.alreadyInvited &&
|
2021-11-12 03:35:26 +01:00
|
|
|
this.money >= 30000000 &&
|
2021-09-05 01:09:30 +02:00
|
|
|
this.city == CityName.Ishima
|
|
|
|
) {
|
|
|
|
invitedFactions.push(ishimaFac);
|
|
|
|
}
|
|
|
|
|
|
|
|
//Volhaven
|
2021-09-25 07:26:03 +02:00
|
|
|
const volhavenFac = Factions["Volhaven"];
|
2021-09-05 01:09:30 +02:00
|
|
|
if (
|
|
|
|
!volhavenFac.isBanned &&
|
|
|
|
!volhavenFac.isMember &&
|
|
|
|
!volhavenFac.alreadyInvited &&
|
2021-11-12 03:35:26 +01:00
|
|
|
this.money >= 50000000 &&
|
2021-09-05 01:09:30 +02:00
|
|
|
this.city == CityName.Volhaven
|
|
|
|
) {
|
|
|
|
invitedFactions.push(volhavenFac);
|
|
|
|
}
|
|
|
|
|
|
|
|
//Speakers for the Dead
|
2021-09-25 07:26:03 +02:00
|
|
|
const speakersforthedeadFac = Factions["Speakers for the Dead"];
|
2021-09-05 01:09:30 +02:00
|
|
|
if (
|
|
|
|
!speakersforthedeadFac.isBanned &&
|
|
|
|
!speakersforthedeadFac.isMember &&
|
|
|
|
!speakersforthedeadFac.alreadyInvited &&
|
2021-11-05 22:12:52 +01:00
|
|
|
this.hacking >= 100 &&
|
2021-09-05 01:09:30 +02:00
|
|
|
this.strength >= 300 &&
|
|
|
|
this.defense >= 300 &&
|
|
|
|
this.dexterity >= 300 &&
|
|
|
|
this.agility >= 300 &&
|
|
|
|
this.numPeopleKilled >= 30 &&
|
|
|
|
this.karma <= -45 &&
|
|
|
|
!allCompanies.includes(LocationName.Sector12CIA) &&
|
|
|
|
!allCompanies.includes(LocationName.Sector12NSA)
|
|
|
|
) {
|
|
|
|
invitedFactions.push(speakersforthedeadFac);
|
|
|
|
}
|
|
|
|
|
|
|
|
//The Dark Army
|
2021-09-25 07:26:03 +02:00
|
|
|
const thedarkarmyFac = Factions["The Dark Army"];
|
2021-09-05 01:09:30 +02:00
|
|
|
if (
|
|
|
|
!thedarkarmyFac.isBanned &&
|
|
|
|
!thedarkarmyFac.isMember &&
|
|
|
|
!thedarkarmyFac.alreadyInvited &&
|
2021-11-05 22:12:52 +01:00
|
|
|
this.hacking >= 300 &&
|
2021-09-05 01:09:30 +02:00
|
|
|
this.strength >= 300 &&
|
|
|
|
this.defense >= 300 &&
|
|
|
|
this.dexterity >= 300 &&
|
|
|
|
this.agility >= 300 &&
|
|
|
|
this.city == CityName.Chongqing &&
|
|
|
|
this.numPeopleKilled >= 5 &&
|
|
|
|
this.karma <= -45 &&
|
|
|
|
!allCompanies.includes(LocationName.Sector12CIA) &&
|
|
|
|
!allCompanies.includes(LocationName.Sector12NSA)
|
|
|
|
) {
|
|
|
|
invitedFactions.push(thedarkarmyFac);
|
|
|
|
}
|
|
|
|
|
|
|
|
//The Syndicate
|
2021-09-25 07:26:03 +02:00
|
|
|
const thesyndicateFac = Factions["The Syndicate"];
|
2021-09-05 01:09:30 +02:00
|
|
|
if (
|
|
|
|
!thesyndicateFac.isBanned &&
|
|
|
|
!thesyndicateFac.isMember &&
|
|
|
|
!thesyndicateFac.alreadyInvited &&
|
2021-11-05 22:12:52 +01:00
|
|
|
this.hacking >= 200 &&
|
2021-09-05 01:09:30 +02:00
|
|
|
this.strength >= 200 &&
|
|
|
|
this.defense >= 200 &&
|
|
|
|
this.dexterity >= 200 &&
|
|
|
|
this.agility >= 200 &&
|
|
|
|
(this.city == CityName.Aevum || this.city == CityName.Sector12) &&
|
2021-11-12 03:35:26 +01:00
|
|
|
this.money >= 10000000 &&
|
2021-09-05 01:09:30 +02:00
|
|
|
this.karma <= -90 &&
|
|
|
|
!allCompanies.includes(LocationName.Sector12CIA) &&
|
|
|
|
!allCompanies.includes(LocationName.Sector12NSA)
|
|
|
|
) {
|
|
|
|
invitedFactions.push(thesyndicateFac);
|
|
|
|
}
|
|
|
|
|
|
|
|
//Silhouette
|
2021-09-25 07:26:03 +02:00
|
|
|
const silhouetteFac = Factions["Silhouette"];
|
2021-09-05 01:09:30 +02:00
|
|
|
if (
|
|
|
|
!silhouetteFac.isBanned &&
|
|
|
|
!silhouetteFac.isMember &&
|
|
|
|
!silhouetteFac.alreadyInvited &&
|
|
|
|
(allPositions.includes("Chief Technology Officer") ||
|
|
|
|
allPositions.includes("Chief Financial Officer") ||
|
|
|
|
allPositions.includes("Chief Executive Officer")) &&
|
2021-11-12 03:35:26 +01:00
|
|
|
this.money >= 15000000 &&
|
2021-09-05 01:09:30 +02:00
|
|
|
this.karma <= -22
|
|
|
|
) {
|
|
|
|
invitedFactions.push(silhouetteFac);
|
|
|
|
}
|
|
|
|
|
|
|
|
//Tetrads
|
2021-09-25 07:26:03 +02:00
|
|
|
const tetradsFac = Factions["Tetrads"];
|
2021-09-05 01:09:30 +02:00
|
|
|
if (
|
|
|
|
!tetradsFac.isBanned &&
|
|
|
|
!tetradsFac.isMember &&
|
|
|
|
!tetradsFac.alreadyInvited &&
|
2021-09-09 05:47:34 +02:00
|
|
|
(this.city == CityName.Chongqing || this.city == CityName.NewTokyo || this.city == CityName.Ishima) &&
|
2021-09-05 01:09:30 +02:00
|
|
|
this.strength >= 75 &&
|
|
|
|
this.defense >= 75 &&
|
|
|
|
this.dexterity >= 75 &&
|
|
|
|
this.agility >= 75 &&
|
|
|
|
this.karma <= -18
|
|
|
|
) {
|
|
|
|
invitedFactions.push(tetradsFac);
|
|
|
|
}
|
|
|
|
|
|
|
|
//SlumSnakes
|
2021-09-25 07:26:03 +02:00
|
|
|
const slumsnakesFac = Factions["Slum Snakes"];
|
2021-09-05 01:09:30 +02:00
|
|
|
if (
|
|
|
|
!slumsnakesFac.isBanned &&
|
|
|
|
!slumsnakesFac.isMember &&
|
|
|
|
!slumsnakesFac.alreadyInvited &&
|
|
|
|
this.strength >= 30 &&
|
|
|
|
this.defense >= 30 &&
|
|
|
|
this.dexterity >= 30 &&
|
|
|
|
this.agility >= 30 &&
|
|
|
|
this.karma <= -9 &&
|
2021-11-12 03:35:26 +01:00
|
|
|
this.money >= 1000000
|
2021-09-05 01:09:30 +02:00
|
|
|
) {
|
|
|
|
invitedFactions.push(slumsnakesFac);
|
|
|
|
}
|
|
|
|
|
|
|
|
//Netburners
|
2021-09-25 07:26:03 +02:00
|
|
|
const netburnersFac = Factions["Netburners"];
|
|
|
|
let totalHacknetRam = 0;
|
|
|
|
let totalHacknetCores = 0;
|
|
|
|
let totalHacknetLevels = 0;
|
2021-09-05 01:09:30 +02:00
|
|
|
for (let i = 0; i < this.hacknetNodes.length; ++i) {
|
2021-09-24 00:47:43 +02:00
|
|
|
const v = this.hacknetNodes[i];
|
|
|
|
if (typeof v === "string") {
|
2021-10-07 22:56:01 +02:00
|
|
|
const hserver = GetServer(v);
|
2021-10-07 22:04:04 +02:00
|
|
|
if (hserver === null || !(hserver instanceof HacknetServer))
|
|
|
|
throw new Error("player hacknet server was not HacknetServer");
|
2021-09-24 00:47:43 +02:00
|
|
|
totalHacknetLevels += hserver.level;
|
|
|
|
totalHacknetRam += hserver.maxRam;
|
|
|
|
totalHacknetCores += hserver.cores;
|
2021-09-05 01:09:30 +02:00
|
|
|
} else {
|
2021-09-24 00:47:43 +02:00
|
|
|
totalHacknetLevels += v.level;
|
|
|
|
totalHacknetRam += v.ram;
|
|
|
|
totalHacknetCores += v.cores;
|
2021-09-05 01:09:30 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if (
|
|
|
|
!netburnersFac.isBanned &&
|
|
|
|
!netburnersFac.isMember &&
|
|
|
|
!netburnersFac.alreadyInvited &&
|
2021-11-05 22:12:52 +01:00
|
|
|
this.hacking >= 80 &&
|
2021-09-05 01:09:30 +02:00
|
|
|
totalHacknetRam >= 8 &&
|
|
|
|
totalHacknetCores >= 4 &&
|
|
|
|
totalHacknetLevels >= 100
|
|
|
|
) {
|
|
|
|
invitedFactions.push(netburnersFac);
|
|
|
|
}
|
|
|
|
|
|
|
|
//Tian Di Hui
|
2021-09-25 07:26:03 +02:00
|
|
|
const tiandihuiFac = Factions["Tian Di Hui"];
|
2021-09-05 01:09:30 +02:00
|
|
|
if (
|
|
|
|
!tiandihuiFac.isBanned &&
|
|
|
|
!tiandihuiFac.isMember &&
|
|
|
|
!tiandihuiFac.alreadyInvited &&
|
2021-11-12 03:35:26 +01:00
|
|
|
this.money >= 1000000 &&
|
2021-11-05 22:12:52 +01:00
|
|
|
this.hacking >= 50 &&
|
2021-09-09 05:47:34 +02:00
|
|
|
(this.city == CityName.Chongqing || this.city == CityName.NewTokyo || this.city == CityName.Ishima)
|
2021-09-05 01:09:30 +02:00
|
|
|
) {
|
|
|
|
invitedFactions.push(tiandihuiFac);
|
|
|
|
}
|
|
|
|
|
|
|
|
//CyberSec
|
2021-09-24 00:47:43 +02:00
|
|
|
const cybersecFac = Factions["CyberSec"];
|
2021-10-07 23:55:49 +02:00
|
|
|
const cybersecServer = GetServer(SpecialServers.CyberSecServer);
|
2021-09-24 00:47:43 +02:00
|
|
|
if (!(cybersecServer instanceof Server)) throw new Error("cybersec should be normal server");
|
2021-09-05 01:09:30 +02:00
|
|
|
if (cybersecServer == null) {
|
|
|
|
console.error("Could not find CyberSec Server");
|
|
|
|
} else if (
|
|
|
|
!cybersecFac.isBanned &&
|
|
|
|
!cybersecFac.isMember &&
|
|
|
|
cybersecServer.backdoorInstalled &&
|
|
|
|
!cybersecFac.alreadyInvited
|
|
|
|
) {
|
|
|
|
invitedFactions.push(cybersecFac);
|
|
|
|
}
|
|
|
|
|
|
|
|
return invitedFactions;
|
2019-04-04 02:08:11 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/************* BitNodes **************/
|
2021-09-25 07:26:03 +02:00
|
|
|
export function setBitNodeNumber(this: IPlayer, n: number): void {
|
2021-09-05 01:09:30 +02:00
|
|
|
this.bitNodeN = n;
|
2019-04-04 02:08:11 +02:00
|
|
|
}
|
|
|
|
|
2021-09-25 07:26:03 +02:00
|
|
|
export function queueAugmentation(this: IPlayer, name: string): void {
|
2021-09-05 01:09:30 +02:00
|
|
|
for (const i in this.queuedAugmentations) {
|
|
|
|
if (this.queuedAugmentations[i].name == name) {
|
|
|
|
console.warn(`tried to queue ${name} twice, this may be a bug`);
|
|
|
|
return;
|
2019-04-04 02:08:11 +02:00
|
|
|
}
|
2021-09-05 01:09:30 +02:00
|
|
|
}
|
2019-04-04 02:08:11 +02:00
|
|
|
|
2021-09-05 01:09:30 +02:00
|
|
|
for (const i in this.augmentations) {
|
|
|
|
if (this.augmentations[i].name == name) {
|
|
|
|
console.warn(`tried to queue ${name} twice, this may be a bug`);
|
|
|
|
return;
|
2019-04-04 02:08:11 +02:00
|
|
|
}
|
2021-09-05 01:09:30 +02:00
|
|
|
}
|
2019-04-04 02:08:11 +02:00
|
|
|
|
2021-09-05 01:09:30 +02:00
|
|
|
this.queuedAugmentations.push(new PlayerOwnedAugmentation(name));
|
2019-04-04 02:08:11 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/************* Coding Contracts **************/
|
2021-09-25 07:26:03 +02:00
|
|
|
export function gainCodingContractReward(this: IPlayer, reward: ICodingContractReward, difficulty = 1): string {
|
2021-09-05 01:09:30 +02:00
|
|
|
if (reward == null || reward.type == null || reward == null) {
|
|
|
|
return `No reward for this contract`;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* eslint-disable no-case-declarations */
|
|
|
|
switch (reward.type) {
|
|
|
|
case CodingContractRewardType.FactionReputation:
|
|
|
|
if (reward.name == null || !(Factions[reward.name] instanceof Faction)) {
|
|
|
|
// If no/invalid faction was designated, just give rewards to all factions
|
|
|
|
reward.type = CodingContractRewardType.FactionReputationAll;
|
|
|
|
return this.gainCodingContractReward(reward);
|
|
|
|
}
|
2021-09-25 07:26:03 +02:00
|
|
|
const repGain = CONSTANTS.CodingContractBaseFactionRepGain * difficulty;
|
2021-09-05 01:09:30 +02:00
|
|
|
Factions[reward.name].playerReputation += repGain;
|
|
|
|
return `Gained ${repGain} faction reputation for ${reward.name}`;
|
|
|
|
case CodingContractRewardType.FactionReputationAll:
|
|
|
|
const totalGain = CONSTANTS.CodingContractBaseFactionRepGain * difficulty;
|
|
|
|
|
|
|
|
// Ignore Bladeburners and other special factions for this calculation
|
|
|
|
const specialFactions = ["Bladeburners"];
|
2021-09-25 08:36:49 +02:00
|
|
|
const factions = this.factions.slice().filter((f) => {
|
2021-09-05 01:09:30 +02:00
|
|
|
return !specialFactions.includes(f);
|
|
|
|
});
|
|
|
|
|
|
|
|
// If the player was only part of the special factions, we'll just give money
|
|
|
|
if (factions.length == 0) {
|
|
|
|
reward.type = CodingContractRewardType.Money;
|
|
|
|
return this.gainCodingContractReward(reward, difficulty);
|
|
|
|
}
|
|
|
|
|
|
|
|
const gainPerFaction = Math.floor(totalGain / factions.length);
|
|
|
|
for (const facName of factions) {
|
|
|
|
if (!(Factions[facName] instanceof Faction)) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
Factions[facName].playerReputation += gainPerFaction;
|
|
|
|
}
|
|
|
|
return `Gained ${gainPerFaction} reputation for each of the following factions: ${factions.toString()}`;
|
|
|
|
break;
|
2021-09-25 08:36:49 +02:00
|
|
|
case CodingContractRewardType.CompanyReputation: {
|
2021-09-05 01:09:30 +02:00
|
|
|
if (reward.name == null || !(Companies[reward.name] instanceof Company)) {
|
|
|
|
//If no/invalid company was designated, just give rewards to all factions
|
|
|
|
reward.type = CodingContractRewardType.FactionReputationAll;
|
|
|
|
return this.gainCodingContractReward(reward);
|
|
|
|
}
|
2021-09-25 07:26:03 +02:00
|
|
|
const repGain = CONSTANTS.CodingContractBaseCompanyRepGain * difficulty;
|
2021-09-05 01:09:30 +02:00
|
|
|
Companies[reward.name].playerReputation += repGain;
|
|
|
|
return `Gained ${repGain} company reputation for ${reward.name}`;
|
2021-09-25 08:36:49 +02:00
|
|
|
}
|
2021-09-05 01:09:30 +02:00
|
|
|
case CodingContractRewardType.Money:
|
2021-09-25 08:36:49 +02:00
|
|
|
default: {
|
2021-09-25 07:26:03 +02:00
|
|
|
const moneyGain = CONSTANTS.CodingContractBaseMoneyGain * difficulty * BitNodeMultipliers.CodingContractMoney;
|
2021-10-27 20:18:33 +02:00
|
|
|
this.gainMoney(moneyGain, "codingcontract");
|
2021-09-05 01:09:30 +02:00
|
|
|
return `Gained ${numeralWrapper.formatMoney(moneyGain)}`;
|
2021-09-25 08:36:49 +02:00
|
|
|
}
|
2021-09-05 01:09:30 +02:00
|
|
|
}
|
|
|
|
/* eslint-enable no-case-declarations */
|
2019-04-04 02:08:11 +02:00
|
|
|
}
|
|
|
|
|
2021-09-25 07:26:03 +02:00
|
|
|
export function travel(this: IPlayer, to: CityName): boolean {
|
2021-09-05 01:09:30 +02:00
|
|
|
if (Cities[to] == null) {
|
|
|
|
console.warn(`Player.travel() called with invalid city: ${to}`);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
this.city = to;
|
2019-04-04 02:08:11 +02:00
|
|
|
|
2021-09-05 01:09:30 +02:00
|
|
|
return true;
|
2019-04-04 02:08:11 +02:00
|
|
|
}
|
|
|
|
|
2021-09-25 07:26:03 +02:00
|
|
|
export function gotoLocation(this: IPlayer, to: LocationName): boolean {
|
2021-09-05 01:09:30 +02:00
|
|
|
if (Locations[to] == null) {
|
|
|
|
console.warn(`Player.gotoLocation() called with invalid location: ${to}`);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
this.location = to;
|
2019-04-04 02:08:11 +02:00
|
|
|
|
2021-09-05 01:09:30 +02:00
|
|
|
return true;
|
2019-04-04 02:08:11 +02:00
|
|
|
}
|
|
|
|
|
2021-09-25 07:26:03 +02:00
|
|
|
export function canAccessResleeving(this: IPlayer): boolean {
|
2021-09-05 01:09:30 +02:00
|
|
|
return this.bitNodeN === 10 || SourceFileFlags[10] > 0;
|
2019-04-04 02:08:11 +02:00
|
|
|
}
|
2021-03-09 02:31:34 +01:00
|
|
|
|
2021-09-25 07:26:03 +02:00
|
|
|
export function giveExploit(this: IPlayer, exploit: Exploit): void {
|
2021-09-05 01:09:30 +02:00
|
|
|
if (!this.exploits.includes(exploit)) {
|
|
|
|
this.exploits.push(exploit);
|
2021-11-11 01:28:20 +01:00
|
|
|
SnackbarEvents.emit("SF -1 acquired!", "success");
|
2021-09-05 01:09:30 +02:00
|
|
|
}
|
2021-03-20 10:29:53 +01:00
|
|
|
}
|
|
|
|
|
2021-09-25 07:26:03 +02:00
|
|
|
export function getIntelligenceBonus(this: IPlayer, weight: number): number {
|
2021-09-05 01:09:30 +02:00
|
|
|
return calculateIntelligenceBonus(this.intelligence, weight);
|
2021-04-10 00:12:31 +02:00
|
|
|
}
|
|
|
|
|
2021-09-25 07:26:03 +02:00
|
|
|
export function getCasinoWinnings(this: IPlayer): number {
|
2021-09-05 01:09:30 +02:00
|
|
|
return this.moneySourceA.casino;
|
|
|
|
}
|
2021-09-24 22:02:38 +02:00
|
|
|
|
|
|
|
export function getMult(this: IPlayer, name: string): number {
|
|
|
|
if (!this.hasOwnProperty(name)) return 1;
|
|
|
|
return (this as any)[name];
|
|
|
|
}
|
|
|
|
|
|
|
|
export function setMult(this: IPlayer, name: string, mult: number): void {
|
|
|
|
if (!this.hasOwnProperty(name)) return;
|
|
|
|
(this as any)[name] = mult;
|
|
|
|
}
|
2021-10-14 09:22:02 +02:00
|
|
|
|
2021-10-16 18:19:53 +02:00
|
|
|
export function canAccessCotMG(this: IPlayer): boolean {
|
|
|
|
return this.bitNodeN === 13 || SourceFileFlags[13] > 0;
|
|
|
|
}
|
|
|
|
|
2021-10-14 09:22:02 +02:00
|
|
|
export function sourceFileLvl(this: IPlayer, n: number): number {
|
2021-10-16 18:19:53 +02:00
|
|
|
const sf = this.sourceFiles.find((sf) => sf.n === n);
|
|
|
|
if (!sf) return 0;
|
|
|
|
return sf.lvl;
|
2021-10-14 09:22:02 +02:00
|
|
|
}
|