bitburner-src/src/Prestige.ts

341 lines
12 KiB
TypeScript
Raw Normal View History

import { AugmentationName, CityName, CompletedProgramName, FactionName, LiteratureName, CompanyName } from "@enums";
import { Augmentations } from "./Augmentation/Augmentations";
import { initBitNodeMultipliers } from "./BitNode/BitNode";
2023-07-11 15:23:17 +02:00
import { Companies } from "./Company/Companies";
import { resetIndustryResearchTrees } from "./Corporation/data/IndustryData";
2023-06-26 04:53:35 +02:00
import { Factions } from "./Faction/Factions";
import { joinFaction } from "./Faction/FactionHelpers";
import { updateHashManagerCapacity } from "./Hacknet/HacknetHelpers";
import { prestigeWorkerScripts } from "./NetscriptWorker";
import { Player } from "@player";
import { recentScripts } from "./Netscript/RecentScripts";
import { resetPidCounter } from "./Netscript/Pid";
2018-03-12 20:39:04 +01:00
2021-10-07 22:56:01 +02:00
import { GetServer, AddToAllServers, initForeignServers, prestigeAllServers } from "./Server/AllServers";
import { prestigeHomeComputer } from "./Server/ServerHelpers";
2021-10-07 23:55:49 +02:00
import { SpecialServers } from "./Server/data/SpecialServers";
import { deleteStockMarket, initStockMarket } from "./StockMarket/StockMarket";
2021-09-16 08:52:45 +02:00
import { Terminal } from "./Terminal";
2019-02-09 03:46:30 +01:00
2021-09-25 20:42:57 +02:00
import { dialogBoxCreate } from "./ui/React/DialogBox";
2017-02-20 23:06:16 +01:00
2021-10-17 03:38:03 +02:00
import { staneksGift } from "./CotMG/Helper";
2021-10-23 21:22:58 +02:00
import { ProgramsSeen } from "./Programs/ui/ProgramsRoot";
import { InvitationsSeen } from "./Faction/ui/FactionsRoot";
2021-11-14 04:44:17 +01:00
import { CONSTANTS } from "./Constants";
2021-11-27 00:47:12 +01:00
import { LogBoxClearEvents } from "./ui/React/LogBoxManager";
2023-06-26 04:53:35 +02:00
import { initCircadianModulator } from "./Augmentation/Augmentations";
import { Go } from "./Go/Go";
import { calculateExp } from "./PersonObjects/formulas/skill";
import { currentNodeMults } from "./BitNode/BitNodeMultipliers";
2024-07-14 23:30:30 +02:00
import { canAccessBitNodeFeature } from "./BitNode/BitNodeUtils";
const BitNode8StartingMoney = 250e6;
function delayedDialog(message: string) {
setTimeout(() => dialogBoxCreate(message), 200);
}
2018-06-03 03:37:56 +02:00
function setInitialExpForPlayer() {
Player.exp.hacking = calculateExp(1, Player.mults.hacking * currentNodeMults.HackingLevelMultiplier);
Player.exp.strength = calculateExp(1, Player.mults.strength * currentNodeMults.StrengthLevelMultiplier);
Player.exp.defense = calculateExp(1, Player.mults.defense * currentNodeMults.DefenseLevelMultiplier);
Player.exp.dexterity = calculateExp(1, Player.mults.dexterity * currentNodeMults.DexterityLevelMultiplier);
Player.exp.agility = calculateExp(1, Player.mults.agility * currentNodeMults.AgilityLevelMultiplier);
Player.exp.charisma = calculateExp(1, Player.mults.charisma * currentNodeMults.CharismaLevelMultiplier);
Player.updateSkillLevels();
Player.hp.current = Player.hp.max;
}
// Prestige by purchasing augmentation
2021-10-23 16:08:06 +02:00
export function prestigeAugmentation(): void {
// We must kill all scripts before doing anything else.
prestigeWorkerScripts();
2022-09-06 15:07:12 +02:00
initBitNodeMultipliers();
2021-09-05 01:09:30 +02:00
// Maintain invites to factions with the 'keepOnInstall' flag, and rumors about others
const maintainInvites = new Set<FactionName>();
const maintainRumors = new Set<FactionName>();
for (const facName of [...Player.factions, ...Player.factionInvitations]) {
if (Factions[facName].getInfo().keep) {
maintainInvites.add(facName);
} else {
maintainRumors.add(facName);
}
}
2021-09-05 01:09:30 +02:00
Player.prestigeAugmentation();
Go.prestigeAugmentation();
2021-09-05 01:09:30 +02:00
2021-09-24 23:07:53 +02:00
const homeComp = Player.getHomeComputer();
2021-09-05 01:09:30 +02:00
// Delete all servers except home computer
prestigeAllServers();
// Reset home computer (only the programs) and add to AllServers
AddToAllServers(homeComp);
2022-09-18 03:09:15 +02:00
prestigeHomeComputer(homeComp);
2021-09-05 01:09:30 +02:00
// Receive starting money and programs from installed augmentations
for (const ownedAug of Player.augmentations) {
const aug = Augmentations[ownedAug.name];
Player.gainMoney(aug.startingMoney, "other");
for (const program of aug.programs) {
homeComp.pushProgram(program);
}
2021-09-05 01:09:30 +02:00
}
2024-07-14 23:30:30 +02:00
if (canAccessBitNodeFeature(5)) {
homeComp.pushProgram(CompletedProgramName.formulas);
2021-10-28 05:41:47 +02:00
}
2021-09-05 01:09:30 +02:00
// Re-create foreign servers
initForeignServers(Player.getHomeComputer());
// Gain favor for Companies and Factions
2023-07-11 15:23:17 +02:00
for (const company of Object.values(Companies)) company.prestigeAugmentation();
2023-06-26 04:53:35 +02:00
for (const faction of Object.values(Factions)) faction.prestigeAugmentation();
2021-09-05 01:09:30 +02:00
2021-11-27 00:47:12 +01:00
// Stop a Terminal action if there is one.
2021-09-25 00:29:25 +02:00
if (Terminal.action !== null) {
2022-09-06 15:07:12 +02:00
Terminal.finishAction(true);
2021-09-05 01:09:30 +02:00
}
2021-10-07 22:56:01 +02:00
Terminal.clear();
2021-11-27 00:47:12 +01:00
LogBoxClearEvents.emit();
2021-09-05 01:09:30 +02:00
2023-06-26 04:53:35 +02:00
// Recalculate the bonus for circadian modulator aug
initCircadianModulator();
Player.factionInvitations = Player.factionInvitations.concat([...maintainInvites]);
for (const factionName of maintainInvites) {
Factions[factionName].alreadyInvited = true;
}
Player.reapplyAllAugmentations();
2021-09-05 01:09:30 +02:00
Player.reapplyAllSourceFiles();
staneksGift.prestigeAugmentation();
2022-03-19 19:15:31 +01:00
// Apply entropy from grafting
2022-03-29 20:09:17 +02:00
Player.applyEntropy(Player.entropy);
2022-03-19 19:15:31 +01:00
2021-09-05 01:09:30 +02:00
// Gang
2021-09-24 23:07:53 +02:00
const gang = Player.gang;
if (gang) {
2021-09-24 23:07:53 +02:00
const faction = Factions[gang.facName];
if (faction) joinFaction(faction);
2022-01-18 20:02:12 +01:00
for (const m of gang.members) {
const results = m.getPostInstallPoints();
m.hack_asc_points = results.hack;
m.str_asc_points = results.str;
m.def_asc_points = results.def;
m.dex_asc_points = results.dex;
m.agi_asc_points = results.agi;
m.cha_asc_points = results.cha;
2022-01-18 20:02:12 +01:00
}
2021-09-05 01:09:30 +02:00
}
// BitNode 3: Corporatocracy
if (Player.bitNodeN === 3) {
FILES: Path rework & typesafety (#479) * Added new types for various file paths, all in the Paths folder. * TypeSafety and other helper functions related to these types * Added basic globbing support with * and ?. Currently only implemented for Script/Text, on nano and download terminal commands * Enforcing the new types throughout the codebase, plus whatever rewrites happened along the way * Server.textFiles is now a map * TextFile no longer uses a fn property, now it is filename * Added a shared ContentFile interface for shared functionality between TextFile and Script. * related to ContentFile change above, the player is now allowed to move a text file to a script file and vice versa. * File paths no longer conditionally start with slashes, and all directory names other than root have ending slashes. The player is still able to provide paths starting with / but this now indicates that the player is specifying an absolute path instead of one relative to root. * Singularized the MessageFilename and LiteratureName enums * Because they now only accept correct types, server.writeToXFile functions now always succeed (the only reasons they could fail before were invalid filepath). * Fix several issues with tab completion, which included pretty much a complete rewrite * Changed the autocomplete display options so there's less chance it clips outside the display area. * Turned CompletedProgramName into an enum. * Got rid of programsMetadata, and programs and DarkWebItems are now initialized immediately instead of relying on initializers called from the engine. * For any executable (program, cct, or script file) pathing can be used directly to execute without using the run command (previously the command had to start with ./ and it wasn't actually using pathing).
2023-04-24 16:26:57 +02:00
// Easiest way to comply with type constraint, instead of revalidating the enum member's file path
homeComp.messages.push(LiteratureName.CorporationManagementHandbook);
}
2021-09-05 01:09:30 +02:00
// Cancel Bladeburner action
if (Player.bladeburner) {
Player.bladeburner.prestigeAugmentation();
2021-09-05 01:09:30 +02:00
}
// BitNode 8: Ghost of Wall Street
if (Player.bitNodeN === 8) {
2021-11-12 03:35:26 +01:00
Player.money = BitNode8StartingMoney;
2021-09-05 01:09:30 +02:00
}
2024-07-14 23:30:30 +02:00
if (canAccessBitNodeFeature(8)) {
2021-09-05 01:09:30 +02:00
Player.hasWseAccount = true;
Player.hasTixApiAccess = true;
}
// Reset Stock market
if (Player.hasWseAccount) {
initStockMarket();
}
// Red Pill
if (Player.hasAugmentation(AugmentationName.TheRedPill, true)) {
2021-10-07 23:55:49 +02:00
const WorldDaemon = GetServer(SpecialServers.WorldDaemon);
const DaedalusServer = GetServer(SpecialServers.DaedalusServer);
2021-09-05 01:09:30 +02:00
if (WorldDaemon && DaedalusServer) {
2021-10-07 23:55:49 +02:00
WorldDaemon.serversOnNetwork.push(DaedalusServer.hostname);
DaedalusServer.serversOnNetwork.push(WorldDaemon.hostname);
2017-07-22 00:54:55 +02:00
}
2021-09-05 01:09:30 +02:00
}
// Bitnode 13: Church of the Machine God
if (Player.hasAugmentation(AugmentationName.StaneksGift1, true)) {
joinFaction(Factions[FactionName.ChurchOfTheMachineGod]);
2024-07-14 23:30:30 +02:00
} else if (Player.bitNodeN !== 13) {
if (Player.augmentations.some((a) => a.name !== AugmentationName.NeuroFluxGovernor)) {
Factions[FactionName.ChurchOfTheMachineGod].isBanned = true;
}
2021-09-25 23:21:50 +02:00
}
2021-10-17 03:38:03 +02:00
// Hear rumors after all invites/bans
for (const factionName of maintainRumors) Player.receiveRumor(factionName);
2021-09-05 01:09:30 +02:00
resetPidCounter();
ProgramsSeen.clear();
InvitationsSeen.clear();
setInitialExpForPlayer();
}
2017-08-13 07:01:33 +02:00
// Prestige by destroying Bit Node and gaining a Source File
export function prestigeSourceFile(isFlume: boolean): void {
// We must kill all scripts before doing anything else.
prestigeWorkerScripts();
2022-09-06 15:07:12 +02:00
initBitNodeMultipliers();
2021-09-05 01:09:30 +02:00
Player.prestigeSourceFile();
Go.prestigeSourceFile();
2021-09-25 07:26:03 +02:00
const homeComp = Player.getHomeComputer();
2017-08-13 07:01:33 +02:00
2021-12-16 18:40:24 +01:00
// Stop a Terminal action if there is one.
if (Terminal.action !== null) {
2022-09-06 15:07:12 +02:00
Terminal.finishAction(true);
2021-12-16 18:40:24 +01:00
}
Terminal.clear();
LogBoxClearEvents.emit();
2021-09-05 01:09:30 +02:00
// Delete all servers except home computer
prestigeAllServers(); // Must be done before initForeignServers()
2021-09-05 01:09:30 +02:00
// Reset home computer (only the programs) and add to AllServers
AddToAllServers(homeComp);
2022-09-18 03:09:15 +02:00
prestigeHomeComputer(homeComp);
// Ram usage needs to be cleared for bitnode-level resets, due to possible change in singularity cost.
for (const script of homeComp.scripts.values()) script.ramUsage = null;
2017-08-13 07:01:33 +02:00
2021-09-05 01:09:30 +02:00
// Re-create foreign servers
initForeignServers(Player.getHomeComputer());
2017-08-13 07:01:33 +02:00
2024-07-14 23:30:30 +02:00
if (Player.activeSourceFileLvl(9) >= 2) {
2021-09-05 01:09:30 +02:00
homeComp.setMaxRam(128);
2024-07-14 23:30:30 +02:00
} else if (Player.activeSourceFileLvl(1) > 0) {
2021-09-05 01:09:30 +02:00
homeComp.setMaxRam(32);
} else {
homeComp.setMaxRam(8);
}
homeComp.cpuCores = 1;
2017-08-20 03:36:19 +02:00
// Reset favor for Companies and Factions
2023-07-11 15:23:17 +02:00
for (const company of Object.values(Companies)) company.prestigeSourceFile();
2023-06-26 04:53:35 +02:00
for (const faction of Object.values(Factions)) faction.prestigeSourceFile();
2021-09-05 01:09:30 +02:00
// Stop a Terminal action if there is one
2021-09-25 00:29:25 +02:00
if (Terminal.action !== null) {
2022-09-06 15:07:12 +02:00
Terminal.finishAction(true);
2021-09-05 01:09:30 +02:00
}
2022-10-09 07:25:31 +02:00
// Give levels of NeuroFluxGovernor for Source-File 12. Must be done here before Augmentations are recalculated
2024-07-14 23:30:30 +02:00
if (Player.activeSourceFileLvl(12) > 0) {
2021-09-05 01:09:30 +02:00
Player.augmentations.push({
name: AugmentationName.NeuroFluxGovernor,
2024-07-14 23:30:30 +02:00
level: Player.activeSourceFileLvl(12),
2021-09-05 01:09:30 +02:00
});
}
2023-06-26 04:53:35 +02:00
initCircadianModulator();
Player.reapplyAllAugmentations();
2021-09-05 01:09:30 +02:00
Player.reapplyAllSourceFiles();
2024-07-14 23:30:30 +02:00
if (canAccessBitNodeFeature(5)) {
homeComp.pushProgram(CompletedProgramName.formulas);
2021-10-28 05:41:47 +02:00
}
2021-09-05 01:09:30 +02:00
// BitNode 3: Corporatocracy
if (Player.bitNodeN === 3) {
FILES: Path rework & typesafety (#479) * Added new types for various file paths, all in the Paths folder. * TypeSafety and other helper functions related to these types * Added basic globbing support with * and ?. Currently only implemented for Script/Text, on nano and download terminal commands * Enforcing the new types throughout the codebase, plus whatever rewrites happened along the way * Server.textFiles is now a map * TextFile no longer uses a fn property, now it is filename * Added a shared ContentFile interface for shared functionality between TextFile and Script. * related to ContentFile change above, the player is now allowed to move a text file to a script file and vice versa. * File paths no longer conditionally start with slashes, and all directory names other than root have ending slashes. The player is still able to provide paths starting with / but this now indicates that the player is specifying an absolute path instead of one relative to root. * Singularized the MessageFilename and LiteratureName enums * Because they now only accept correct types, server.writeToXFile functions now always succeed (the only reasons they could fail before were invalid filepath). * Fix several issues with tab completion, which included pretty much a complete rewrite * Changed the autocomplete display options so there's less chance it clips outside the display area. * Turned CompletedProgramName into an enum. * Got rid of programsMetadata, and programs and DarkWebItems are now initialized immediately instead of relying on initializers called from the engine. * For any executable (program, cct, or script file) pathing can be used directly to execute without using the run command (previously the command had to start with ./ and it wasn't actually using pathing).
2023-04-24 16:26:57 +02:00
// Easiest way to comply with type constraint, instead of revalidating the enum member's file path
homeComp.messages.push(LiteratureName.CorporationManagementHandbook);
delayedDialog(
"You received a copy of the Corporation Management Handbook on your home computer. It's a short introduction for " +
"managing Corporation.\n\nYou should check the in-game Corporation documentation in the Documentation tab " +
"(Documentation -> Advanced Mechanics -> Corporation). It's the most useful and up-to-date resource for managing Corporation.",
2021-09-05 01:09:30 +02:00
);
}
// BitNode 6: Bladeburners and BitNode 7: Bladeburners 2079
if (Player.bitNodeN === 6 || Player.bitNodeN === 7) {
delayedDialog(`The ${CompanyName.NSA} would like to have a word with you once you're ready.`);
}
2021-09-05 01:09:30 +02:00
// BitNode 8: Ghost of Wall Street
if (Player.bitNodeN === 8) {
2021-11-12 03:35:26 +01:00
Player.money = BitNode8StartingMoney;
2021-09-05 01:09:30 +02:00
}
2024-07-14 23:30:30 +02:00
if (Player.bitNodeN === 8 || Player.activeSourceFileLvl(8) > 0) {
2021-09-05 01:09:30 +02:00
Player.hasWseAccount = true;
Player.hasTixApiAccess = true;
}
// BitNode 10: Digital Carbon
2021-09-05 01:09:30 +02:00
if (Player.bitNodeN === 10) {
delayedDialog(
`Seek out ${FactionName.TheCovenant} if you'd like to purchase a new sleeve or two! And see what ${CompanyName.VitaLife} in ${CityName.NewTokyo} has to offer for you`,
);
}
2023-12-19 11:21:05 +01:00
// BitNode 12: The Recursion
2024-07-14 23:30:30 +02:00
if (Player.bitNodeN === 12 && Player.activeSourceFileLvl(12) > 100) {
delayedDialog("Saynt_Garmo is watching you");
2021-09-05 01:09:30 +02:00
}
2021-10-07 07:36:59 +02:00
if (Player.bitNodeN === 13) {
delayedDialog(`Trouble is brewing in ${CityName.Chongqing}`);
2021-10-07 07:36:59 +02:00
}
2021-09-05 01:09:30 +02:00
// Reset Stock market, gang, and corporation
if (Player.hasWseAccount) {
initStockMarket();
} else {
deleteStockMarket();
}
resetIndustryResearchTrees();
// Source-File 9 (level 3) effect
// also now applies when entering bn9 until install
2024-07-14 23:30:30 +02:00
if ((Player.activeSourceFileLvl(9) >= 3 || Player.bitNodeN === 9) && !Player.bitNodeOptions.disableHacknetServer) {
2021-09-05 01:09:30 +02:00
const hserver = Player.createHacknetServer();
hserver.level = 100;
hserver.cores = 10;
hserver.cpuCores = 10;
2021-09-05 01:09:30 +02:00
hserver.cache = 5;
2022-07-15 00:43:33 +02:00
hserver.updateHashRate(Player.mults.hacknet_node_money);
2021-09-05 01:09:30 +02:00
hserver.updateHashCapacity();
2022-09-06 15:07:12 +02:00
updateHashManagerCapacity();
2021-09-05 01:09:30 +02:00
}
2021-11-14 04:44:17 +01:00
if (Player.bitNodeN === 13) {
Player.money = CONSTANTS.TravelCost;
}
2021-10-17 03:38:03 +02:00
staneksGift.prestigeSourceFile();
2021-09-05 01:09:30 +02:00
// Gain int exp
2024-07-14 23:30:30 +02:00
if (Player.activeSourceFileLvl(5) !== 0 && !isFlume) {
Player.gainIntelligenceExp(300);
}
2021-09-05 01:09:30 +02:00
// Clear recent scripts
recentScripts.splice(0, recentScripts.length);
2021-09-05 01:09:30 +02:00
resetPidCounter();
setInitialExpForPlayer();
if (!isFlume && Player.sourceFiles.size === 1 && Player.sourceFileLvl(1) === 1) {
delayedDialog(
"Congratulations on destroying your first BitNode! Make sure to check the Documentation tab. Many pages are unlocked now.",
);
}
2017-08-13 07:01:33 +02:00
}