many fixes

This commit is contained in:
Olivier Gagnon 2022-01-09 15:22:23 -05:00
parent ab15481cd6
commit d8a5f5b03c
18 changed files with 448 additions and 225 deletions

24
dist/vendor.bundle.js vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -1028,11 +1028,7 @@ export class Bladeburner implements IBladeburner {
player.gainDexterityExp(unweightedGain * action.weights.dex * player.dexterity_exp_mult * skillMult); player.gainDexterityExp(unweightedGain * action.weights.dex * player.dexterity_exp_mult * skillMult);
player.gainAgilityExp(unweightedGain * action.weights.agi * player.agility_exp_mult * skillMult); player.gainAgilityExp(unweightedGain * action.weights.agi * player.agility_exp_mult * skillMult);
player.gainCharismaExp(unweightedGain * action.weights.cha * player.charisma_exp_mult * skillMult); player.gainCharismaExp(unweightedGain * action.weights.cha * player.charisma_exp_mult * skillMult);
let intExp = unweightedIntGain * action.weights.int * skillMult; player.gainIntelligenceExp(unweightedIntGain * action.weights.int * skillMult);
if (intExp > 1) {
intExp = Math.pow(intExp, 0.8);
}
player.gainIntelligenceExp(intExp);
} }
getDiplomacyEffectiveness(player: IPlayer): number { getDiplomacyEffectiveness(player: IPlayer): number {

@ -64,9 +64,11 @@ export function CreateCorporationModal(props: IProps): React.ReactElement {
If you would like to start one, please enter a name for your corporation below: If you would like to start one, please enter a name for your corporation below:
</Typography> </Typography>
<TextField autoFocus={true} placeholder="Corporation Name" onChange={onChange} value={name} /> <TextField autoFocus={true} placeholder="Corporation Name" onChange={onChange} value={name} />
<Button onClick={seed} disabled={name == ""}> {player.bitNodeN === 3 && (
Use seed money <Button onClick={seed} disabled={name == ""}>
</Button> Use seed money
</Button>
)}
<Button onClick={selfFund} disabled={name == "" || !canSelfFund}> <Button onClick={selfFund} disabled={name == "" || !canSelfFund}>
Self-Fund (<Money money={150e9} player={player} />) Self-Fund (<Money money={150e9} player={player} />)
</Button> </Button>

@ -201,7 +201,7 @@ export function FragmentById(id: number): Fragment | null {
21, // id 21, // id
Shapes.O, Shapes.O,
FragmentType.HacknetCost, // type FragmentType.HacknetCost, // type
-1, // power 2, // power
1, // limit 1, // limit
), ),
); );

@ -72,7 +72,7 @@ export function Effect(tpe: FragmentType): string {
break; break;
} }
case FragmentType.HacknetCost: { case FragmentType.HacknetCost: {
return "-x% all hacknet cost"; return "x% cheaper hacknet cost";
break; break;
} }
case FragmentType.Rep: { case FragmentType.Rep: {

@ -179,10 +179,10 @@ export class StaneksGift implements IStaneksGift {
p.hacknet_node_money_mult *= power; p.hacknet_node_money_mult *= power;
break; break;
case FragmentType.HacknetCost: case FragmentType.HacknetCost:
p.hacknet_node_purchase_cost_mult *= power; p.hacknet_node_purchase_cost_mult /= power;
p.hacknet_node_ram_cost_mult *= power; p.hacknet_node_ram_cost_mult /= power;
p.hacknet_node_core_cost_mult *= power; p.hacknet_node_core_cost_mult /= power;
p.hacknet_node_level_cost_mult *= power; p.hacknet_node_level_cost_mult /= power;
break; break;
case FragmentType.Rep: case FragmentType.Rep:
p.company_rep_mult *= power; p.company_rep_mult *= power;

@ -12,7 +12,7 @@ import { IPlayer } from "../../PersonObjects/IPlayer";
import ButtonGroup from "@mui/material/ButtonGroup"; import ButtonGroup from "@mui/material/ButtonGroup";
// Update as additional BitNodes get implemented // Update as additional BitNodes get implemented
const validSFN = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]; const validSFN = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13];
interface IProps { interface IProps {
player: IPlayer; player: IPlayer;

@ -380,8 +380,7 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
Player.scriptProdSinceLastAug += moneyGained; Player.scriptProdSinceLastAug += moneyGained;
workerScript.scriptRef.recordHack(server.hostname, moneyGained, threads); workerScript.scriptRef.recordHack(server.hostname, moneyGained, threads);
Player.gainHackingExp(expGainedOnSuccess); Player.gainHackingExp(expGainedOnSuccess);
if (manual) if (manual) Player.gainIntelligenceExp(0.005);
Player.gainIntelligenceExp(Math.pow(expGainedOnSuccess / CONSTANTS.IntelligenceTerminalHackBaseExpGain, 0.1));
workerScript.scriptRef.onlineExpGained += expGainedOnSuccess; workerScript.scriptRef.onlineExpGained += expGainedOnSuccess;
workerScript.log( workerScript.log(
"hack", "hack",

@ -209,7 +209,7 @@ export function NetscriptSingularity(
const res = purchaseAugmentation(aug, fac, true); const res = purchaseAugmentation(aug, fac, true);
workerScript.log("purchaseAugmentation", () => res); workerScript.log("purchaseAugmentation", () => res);
if (isString(res) && res.startsWith("You purchased")) { if (isString(res) && res.startsWith("You purchased")) {
player.gainIntelligenceExp(CONSTANTS.IntelligenceSingFnBaseExpGain); player.gainIntelligenceExp(CONSTANTS.IntelligenceSingFnBaseExpGain * 10);
return true; return true;
} else { } else {
return false; return false;
@ -237,7 +237,7 @@ export function NetscriptSingularity(
workerScript.log("installAugmentations", () => "You do not have any Augmentations to be installed."); workerScript.log("installAugmentations", () => "You do not have any Augmentations to be installed.");
return false; return false;
} }
player.gainIntelligenceExp(CONSTANTS.IntelligenceSingFnBaseExpGain); player.gainIntelligenceExp(CONSTANTS.IntelligenceSingFnBaseExpGain * 10);
workerScript.log( workerScript.log(
"installAugmentations", "installAugmentations",
() => "Installing Augmentations. This will cause this script to be killed", () => "Installing Augmentations. This will cause this script to be killed",
@ -264,7 +264,7 @@ export function NetscriptSingularity(
return false; return false;
} }
Router.toLocation(location); Router.toLocation(location);
player.gainIntelligenceExp(CONSTANTS.IntelligenceSingFnBaseExpGain / 100); player.gainIntelligenceExp(CONSTANTS.IntelligenceSingFnBaseExpGain / 500);
return true; return true;
}, },
universityCourse: function (universityName: any, className: any): any { universityCourse: function (universityName: any, className: any): any {
@ -499,7 +499,7 @@ export function NetscriptSingularity(
player.getHomeComputer().serversOnNetwork.push(darkweb.hostname); player.getHomeComputer().serversOnNetwork.push(darkweb.hostname);
darkweb.serversOnNetwork.push(player.getHomeComputer().hostname); darkweb.serversOnNetwork.push(player.getHomeComputer().hostname);
player.gainIntelligenceExp(CONSTANTS.IntelligenceSingFnBaseExpGain); player.gainIntelligenceExp(CONSTANTS.IntelligenceSingFnBaseExpGain / 50);
workerScript.log("purchaseTor", () => "You have purchased a Tor router!"); workerScript.log("purchaseTor", () => "You have purchased a Tor router!");
return true; return true;
}, },
@ -769,7 +769,7 @@ export function NetscriptSingularity(
homeComputer.cpuCores += 1; homeComputer.cpuCores += 1;
player.loseMoney(cost, "servers"); player.loseMoney(cost, "servers");
player.gainIntelligenceExp(CONSTANTS.IntelligenceSingFnBaseExpGain); player.gainIntelligenceExp(CONSTANTS.IntelligenceSingFnBaseExpGain * 2);
workerScript.log( workerScript.log(
"upgradeHomeCores", "upgradeHomeCores",
() => `Purchased an additional core for home computer! It now has ${homeComputer.cpuCores} cores.`, () => `Purchased an additional core for home computer! It now has ${homeComputer.cpuCores} cores.`,
@ -805,7 +805,7 @@ export function NetscriptSingularity(
homeComputer.maxRam *= 2; homeComputer.maxRam *= 2;
player.loseMoney(cost, "servers"); player.loseMoney(cost, "servers");
player.gainIntelligenceExp(CONSTANTS.IntelligenceSingFnBaseExpGain); player.gainIntelligenceExp(CONSTANTS.IntelligenceSingFnBaseExpGain * 2);
workerScript.log( workerScript.log(
"upgradeHomeRam", "upgradeHomeRam",
() => () =>
@ -988,7 +988,7 @@ export function NetscriptSingularity(
i--; i--;
} }
} }
player.gainIntelligenceExp(CONSTANTS.IntelligenceSingFnBaseExpGain); player.gainIntelligenceExp(CONSTANTS.IntelligenceSingFnBaseExpGain * 5);
workerScript.log("joinFaction", () => `Joined the '${name}' faction.`); workerScript.log("joinFaction", () => `Joined the '${name}' faction.`);
return true; return true;
}, },
@ -1178,17 +1178,11 @@ export function NetscriptSingularity(
helper.checkSingularityAccess("donateToFaction"); helper.checkSingularityAccess("donateToFaction");
const faction = getFaction("donateToFaction", name); const faction = getFaction("donateToFaction", name);
if (!player.factions.includes(faction.name)) { if (!player.factions.includes(faction.name)) {
workerScript.log( workerScript.log("donateToFaction", () => `You can't donate to '${name}' because you aren't a member`);
"donateToFaction",
() => `You can't donate to '${name}' because you aren't a member`,
);
return false; return false;
} }
if (player.inGang() && faction.name === player.getGangFaction().name) { if (player.inGang() && faction.name === player.getGangFaction().name) {
workerScript.log( workerScript.log("donateToFaction", () => `You can't donate to '${name}' because youre managing a gang for it`);
"donateToFaction",
() => `You can't donate to '${name}' because youre managing a gang for it`,
);
return false; return false;
} }
if (typeof amt !== "number" || amt <= 0 || isNaN(amt)) { if (typeof amt !== "number" || amt <= 0 || isNaN(amt)) {

@ -87,7 +87,6 @@ export function prestigeAugmentation(this: PlayerObject): void {
this.currentServer = SpecialServers.Home; this.currentServer = SpecialServers.Home;
this.numPeopleKilled = 0; this.numPeopleKilled = 0;
this.karma = 0;
//Reset stats //Reset stats
this.hacking = 1; this.hacking = 1;
@ -183,6 +182,7 @@ export function prestigeAugmentation(this: PlayerObject): void {
export function prestigeSourceFile(this: IPlayer): void { export function prestigeSourceFile(this: IPlayer): void {
this.prestigeAugmentation(); this.prestigeAugmentation();
this.karma = 0;
// Duplicate sleeves are reset to level 1 every Bit Node (but the number of sleeves you have persists) // 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) { for (let i = 0; i < this.sleeves.length; ++i) {
if (this.sleeves[i] instanceof Sleeve) { if (this.sleeves[i] instanceof Sleeve) {
@ -671,12 +671,36 @@ export function finishWork(this: IPlayer, cancelled: boolean, sing = false): str
<Money money={this.workMoneyGained} /> <Money money={this.workMoneyGained} />
<br /> <br />
<Reputation reputation={this.workRepGained} /> reputation for the company <br /> <Reputation reputation={this.workRepGained} /> reputation for the company <br />
{this.workHackExpGained > 0 && <>{numeralWrapper.formatExp(this.workHackExpGained)} hacking exp <br /></>} {this.workHackExpGained > 0 && (
{this.workStrExpGained > 0 && <>{numeralWrapper.formatExp(this.workStrExpGained)} strength exp <br /></>} <>
{this.workDefExpGained > 0 && <>{numeralWrapper.formatExp(this.workDefExpGained)} defense exp <br /></>} {numeralWrapper.formatExp(this.workHackExpGained)} hacking exp <br />
{this.workDexExpGained > 0 && <>{numeralWrapper.formatExp(this.workDexExpGained)} dexterity exp <br /></>} </>
{this.workAgiExpGained > 0 && <>{numeralWrapper.formatExp(this.workAgiExpGained)} agility exp <br /></>} )}
{this.workChaExpGained > 0 && <>{numeralWrapper.formatExp(this.workChaExpGained)} charisma exp <br /></>} {this.workStrExpGained > 0 && (
<>
{numeralWrapper.formatExp(this.workStrExpGained)} strength exp <br />
</>
)}
{this.workDefExpGained > 0 && (
<>
{numeralWrapper.formatExp(this.workDefExpGained)} defense exp <br />
</>
)}
{this.workDexExpGained > 0 && (
<>
{numeralWrapper.formatExp(this.workDexExpGained)} dexterity exp <br />
</>
)}
{this.workAgiExpGained > 0 && (
<>
{numeralWrapper.formatExp(this.workAgiExpGained)} agility exp <br />
</>
)}
{this.workChaExpGained > 0 && (
<>
{numeralWrapper.formatExp(this.workChaExpGained)} charisma exp <br />
</>
)}
<br /> <br />
</> </>
); );
@ -1273,11 +1297,15 @@ export function startCreateProgramWork(
} }
export function createProgramWork(this: IPlayer, numCycles: number): boolean { export function createProgramWork(this: IPlayer, numCycles: number): boolean {
let focusBonus = 1;
if (!this.hasAugmentation(AugmentationNames["NeuroreceptorManager"])) {
focusBonus = this.focus ? 1 : CONSTANTS.BaseFocusBonus;
}
//Higher hacking skill will allow you to create programs faster //Higher hacking skill will allow you to create programs faster
const reqLvl = this.createProgramReqLvl; const reqLvl = this.createProgramReqLvl;
let skillMult = (this.hacking / reqLvl) * this.getIntelligenceBonus(3); //This should always be greater than 1; let skillMult = (this.hacking / reqLvl) * this.getIntelligenceBonus(3); //This should always be greater than 1;
skillMult = 1 + (skillMult - 1) / 5; //The divider constant can be adjusted as necessary skillMult = 1 + (skillMult - 1) / 5; //The divider constant can be adjusted as necessary
skillMult *= focusBonus;
//Skill multiplier directly applied to "time worked" //Skill multiplier directly applied to "time worked"
this.timeWorked += CONSTANTS._idleSpeed * numCycles; this.timeWorked += CONSTANTS._idleSpeed * numCycles;
this.timeWorkedCreateProgram += CONSTANTS._idleSpeed * numCycles * skillMult; this.timeWorkedCreateProgram += CONSTANTS._idleSpeed * numCycles * skillMult;
@ -2645,9 +2673,9 @@ export function giveExploit(this: IPlayer, exploit: Exploit): void {
export function giveAchievement(this: IPlayer, achievementId: string): void { export function giveAchievement(this: IPlayer, achievementId: string): void {
const achievement = achievements[achievementId]; const achievement = achievements[achievementId];
if (!achievement) return; if (!achievement) return;
if (!this.achievements.map(a => a.ID).includes(achievementId)) { if (!this.achievements.map((a) => a.ID).includes(achievementId)) {
this.achievements.push({ ID: achievementId, unlockedOn: new Date().getTime() }); this.achievements.push({ ID: achievementId, unlockedOn: new Date().getTime() });
SnackbarEvents.emit(`Unlocked Achievement: "${achievement.Name}"`, 'success', 2000); SnackbarEvents.emit(`Unlocked Achievement: "${achievement.Name}"`, "success", 2000);
} }
} }

@ -48,12 +48,13 @@ export const programsMetadata: IProgramCreationParams[] = [
} }
if (server.hasAdminRights) { if (server.hasAdminRights) {
terminal.print("You already have root access to this computer. There is no reason to run NUKE.exe"); terminal.print("You already have root access to this computer. There is no reason to run NUKE.exe");
terminal.print("You can now run scripts on this server.");
return; return;
} }
if (server.openPortCount >= server.numOpenPortsRequired) { if (server.openPortCount >= server.numOpenPortsRequired) {
server.hasAdminRights = true; server.hasAdminRights = true;
terminal.print("NUKE successful! Gained root access to " + server.hostname); terminal.print("NUKE successful! Gained root access to " + server.hostname);
// TODO: Make this take time rather than be instant terminal.print("You can now run scripts on this server.");
return; return;
} }

@ -1294,15 +1294,15 @@ export interface TIX {
/** /**
* Singularity API * Singularity API
* @remarks * @remarks
* This API requires Source-File 4 level 1 / 2 / 3 to use. * This API requires Source-File 4 level 1 to use. The RAM cost of all these functions is multiplied by 16/4/1 based on Source-File 4 levels.
* @public * @public
*/ */
export interface Singularity { export interface Singularity {
/** /**
* SF4.1 - Take university class. * Take university class.
* *
* @remarks * @remarks
* RAM cost: 2 GB * RAM cost: 2 GB * 16/4/1
* *
* *
* This function will automatically set you to start taking a course at a university. * This function will automatically set you to start taking a course at a university.
@ -1320,10 +1320,10 @@ export interface Singularity {
universityCourse(universityName: string, courseName: string): boolean; universityCourse(universityName: string, courseName: string): boolean;
/** /**
* SF4.1 - Workout at the gym. * Workout at the gym.
* *
* @remarks * @remarks
* RAM cost: 2 GB * RAM cost: 2 GB * 16/4/1
* *
* This function will automatically set you to start working out at a gym to train * This function will automatically set you to start working out at a gym to train
@ -1341,9 +1341,9 @@ export interface Singularity {
gymWorkout(gymName: string, stat: string): boolean; gymWorkout(gymName: string, stat: string): boolean;
/** /**
* SF4.1 - Travel to another city. * Travel to another city.
* @remarks * @remarks
* RAM cost: 2 GB * RAM cost: 2 GB * 16/4/1
* *
* *
* This function allows the player to travel to any city. The cost for using this * This function allows the player to travel to any city. The cost for using this
@ -1355,9 +1355,9 @@ export interface Singularity {
travelToCity(city: string): boolean; travelToCity(city: string): boolean;
/** /**
* SF4.1 - Purchase the TOR router. * Purchase the TOR router.
* @remarks * @remarks
* RAM cost: 2 GB * RAM cost: 2 GB * 16/4/1
* *
* *
* This function allows you to automatically purchase a TOR router. The cost for * This function allows you to automatically purchase a TOR router. The cost for
@ -1369,9 +1369,9 @@ export interface Singularity {
purchaseTor(): boolean; purchaseTor(): boolean;
/** /**
* SF4.1 - Purchase a program from the dark web. * Purchase a program from the dark web.
* @remarks * @remarks
* RAM cost: 2 GB * RAM cost: 2 GB * 16/4/1
* *
* *
* This function allows you to automatically purchase programs. You MUST have a * This function allows you to automatically purchase programs. You MUST have a
@ -1395,9 +1395,9 @@ export interface Singularity {
purchaseProgram(programName: string): boolean; purchaseProgram(programName: string): boolean;
/** /**
* SF4.1 - Check if the player is busy. * Check if the player is busy.
* @remarks * @remarks
* RAM cost: 0.5 GB * RAM cost: 0.5 GB * 16/4/1
* *
* *
* Returns a boolean indicating whether or not the player is currently performing an * Returns a boolean indicating whether or not the player is currently performing an
@ -1409,9 +1409,9 @@ export interface Singularity {
isBusy(): boolean; isBusy(): boolean;
/** /**
* SF4.1 - Stop the current action. * Stop the current action.
* @remarks * @remarks
* RAM cost: 1 GB * RAM cost: 1 GB * 16/4/1
* *
* *
* This function is used to end whatever action the player is currently performing. * This function is used to end whatever action the player is currently performing.
@ -1432,9 +1432,9 @@ export interface Singularity {
stopAction(): boolean; stopAction(): boolean;
/** /**
* SF4.2 - Upgrade home computer RAM. * Upgrade home computer RAM.
* @remarks * @remarks
* RAM cost: 3 GB * RAM cost: 3 GB * 16/4/1
* *
* *
* This function will upgrade amount of RAM on the players home computer. The cost is * This function will upgrade amount of RAM on the players home computer. The cost is
@ -1447,9 +1447,9 @@ export interface Singularity {
upgradeHomeRam(): boolean; upgradeHomeRam(): boolean;
/** /**
* SF4.2 - Upgrade home computer cores. * Upgrade home computer cores.
* @remarks * @remarks
* RAM cost: 3 GB * RAM cost: 3 GB * 16/4/1
* *
* *
* This function will upgrade amount of cores on the players home computer. The cost is * This function will upgrade amount of cores on the players home computer. The cost is
@ -1462,9 +1462,9 @@ export interface Singularity {
upgradeHomeCores(): boolean; upgradeHomeCores(): boolean;
/** /**
* SF4.2 - Get the price of upgrading home RAM. * Get the price of upgrading home RAM.
* @remarks * @remarks
* RAM cost: 1.5 GB * RAM cost: 1.5 GB * 16/4/1
* *
* *
* Returns the cost of upgrading the players home computer RAM. * Returns the cost of upgrading the players home computer RAM.
@ -1474,9 +1474,9 @@ export interface Singularity {
getUpgradeHomeRamCost(): number; getUpgradeHomeRamCost(): number;
/** /**
* SF4.2 - Get the price of upgrading home cores. * Get the price of upgrading home cores.
* @remarks * @remarks
* RAM cost: 1.5 GB * RAM cost: 1.5 GB * 16/4/1
* *
* *
* Returns the cost of upgrading the players home computer cores. * Returns the cost of upgrading the players home computer cores.
@ -1486,9 +1486,9 @@ export interface Singularity {
getUpgradeHomeCoresCost(): number; getUpgradeHomeCoresCost(): number;
/** /**
* SF4.2 - Work for a company. * Work for a company.
* @remarks * @remarks
* RAM cost: 3 GB * RAM cost: 3 GB * 16/4/1
* *
* *
* This function will automatically set you to start working at the company * This function will automatically set you to start working at the company
@ -1528,9 +1528,9 @@ export interface Singularity {
workForCompany(companyName?: string, focus?: boolean): boolean; workForCompany(companyName?: string, focus?: boolean): boolean;
/** /**
* SF4.2 - Apply for a job at a company. * Apply for a job at a company.
* @remarks * @remarks
* RAM cost: 3 GB * RAM cost: 3 GB * 16/4/1
* *
* *
* This function will automatically try to apply to the specified company * This function will automatically try to apply to the specified company
@ -1549,9 +1549,9 @@ export interface Singularity {
applyToCompany(companyName: string, field: string): boolean; applyToCompany(companyName: string, field: string): boolean;
/** /**
* SF4.2 - Get company reputation. * Get company reputation.
* @remarks * @remarks
* RAM cost: 1 GB * RAM cost: 1 GB * 16/4/1
* *
* *
* This function will return the amount of reputation you have at the specified company. * This function will return the amount of reputation you have at the specified company.
@ -1563,9 +1563,9 @@ export interface Singularity {
getCompanyRep(companyName: string): number; getCompanyRep(companyName: string): number;
/** /**
* SF4.2 - Get company favor. * Get company favor.
* @remarks * @remarks
* RAM cost: 1 GB * RAM cost: 1 GB * 16/4/1
* *
* *
* This function will return the amount of favor you have at the specified company. * This function will return the amount of favor you have at the specified company.
@ -1577,9 +1577,9 @@ export interface Singularity {
getCompanyFavor(companyName: string): number; getCompanyFavor(companyName: string): number;
/** /**
* SF4.2 - Get company favor gain. * Get company favor gain.
* @remarks * @remarks
* RAM cost: 0.75 GB * RAM cost: 0.75 GB * 16/4/1
* *
* *
* This function will return the amount of favor you will gain for the specified * This function will return the amount of favor you will gain for the specified
@ -1591,9 +1591,9 @@ export interface Singularity {
getCompanyFavorGain(companyName: string): number; getCompanyFavorGain(companyName: string): number;
/** /**
* SF4.2 - List all current faction invitations. * List all current faction invitations.
* @remarks * @remarks
* RAM cost: 3 GB * RAM cost: 3 GB * 16/4/1
* *
* *
* Returns an array with the name of all Factions you currently have oustanding invitations from. * Returns an array with the name of all Factions you currently have oustanding invitations from.
@ -1603,9 +1603,9 @@ export interface Singularity {
checkFactionInvitations(): string[]; checkFactionInvitations(): string[];
/** /**
* SF4.2 - Join a faction. * Join a faction.
* @remarks * @remarks
* RAM cost: 3 GB * RAM cost: 3 GB * 16/4/1
* *
* *
* This function will automatically accept an invitation from a faction and join it. * This function will automatically accept an invitation from a faction and join it.
@ -1616,9 +1616,9 @@ export interface Singularity {
joinFaction(faction: string): boolean; joinFaction(faction: string): boolean;
/** /**
* SF4.2 - Work for a faction. * Work for a faction.
* @remarks * @remarks
* RAM cost: 3 GB * RAM cost: 3 GB * 16/4/1
* *
* *
* This function will automatically set you to start working for the specified faction. * This function will automatically set you to start working for the specified faction.
@ -1659,9 +1659,9 @@ export interface Singularity {
workForFaction(faction: string, workType: string, focus?: boolean): boolean; workForFaction(faction: string, workType: string, focus?: boolean): boolean;
/** /**
* SF4.2 - Get faction reputation. * Get faction reputation.
* @remarks * @remarks
* RAM cost: 1 GB * RAM cost: 1 GB * 16/4/1
* *
* *
* This function returns the amount of reputation you have for the specified faction. * This function returns the amount of reputation you have for the specified faction.
@ -1672,9 +1672,9 @@ export interface Singularity {
getFactionRep(faction: string): number; getFactionRep(faction: string): number;
/** /**
* SF4.2 - Get faction favor. * Get faction favor.
* @remarks * @remarks
* RAM cost: 1 GB * RAM cost: 1 GB * 16/4/1
* *
* *
* This function returns the amount of favor you have for the specified faction. * This function returns the amount of favor you have for the specified faction.
@ -1685,9 +1685,9 @@ export interface Singularity {
getFactionFavor(faction: string): number; getFactionFavor(faction: string): number;
/** /**
* SF4.2 - Get faction favor gain. * Get faction favor gain.
* @remarks * @remarks
* RAM cost: 0.75 GB * RAM cost: 0.75 GB * 16/4/1
* *
* *
* This function returns the amount of favor you will gain for the specified * This function returns the amount of favor you will gain for the specified
@ -1699,9 +1699,9 @@ export interface Singularity {
getFactionFavorGain(faction: string): number; getFactionFavorGain(faction: string): number;
/** /**
* SF4.3 - Donate to a faction. * Donate to a faction.
* @remarks * @remarks
* RAM cost: 5 GB * RAM cost: 5 GB * 16/4/1
* *
* *
* Attempts to donate money to the specified faction in exchange for reputation. * Attempts to donate money to the specified faction in exchange for reputation.
@ -1714,9 +1714,9 @@ export interface Singularity {
donateToFaction(faction: string, amount: number): boolean; donateToFaction(faction: string, amount: number): boolean;
/** /**
* SF4.3 - Create a program. * Create a program.
* @remarks * @remarks
* RAM cost: 5 GB * RAM cost: 5 GB * 16/4/1
* *
* *
* This function will automatically set you to start working on creating the * This function will automatically set you to start working on creating the
@ -1754,9 +1754,9 @@ export interface Singularity {
createProgram(program: string): boolean; createProgram(program: string): boolean;
/** /**
* SF4.3 - Commit a crime. * Commit a crime.
* @remarks * @remarks
* RAM cost: 5 GB * RAM cost: 5 GB * 16/4/1
* *
* *
* This function is used to automatically attempt to commit crimes. * This function is used to automatically attempt to commit crimes.
@ -1781,9 +1781,9 @@ export interface Singularity {
commitCrime(crime: string): number; commitCrime(crime: string): number;
/** /**
* SF4.3 - Get chance to successfully commit a crime. * Get chance to successfully commit a crime.
* @remarks * @remarks
* RAM cost: 5 GB * RAM cost: 5 GB * 16/4/1
* *
* *
* This function returns your chance of success at commiting the specified crime. * This function returns your chance of success at commiting the specified crime.
@ -1794,9 +1794,9 @@ export interface Singularity {
getCrimeChance(crime: string): number; getCrimeChance(crime: string): number;
/** /**
* SF4.3 - Get stats related to a crime. * Get stats related to a crime.
* @remarks * @remarks
* RAM cost: 5 GB * RAM cost: 5 GB * 16/4/1
* *
* *
* Returns the stats of the crime. * Returns the stats of the crime.
@ -1807,9 +1807,9 @@ export interface Singularity {
getCrimeStats(crime: string): CrimeStats; getCrimeStats(crime: string): CrimeStats;
/** /**
* SF4.3 - Get a list of owned augmentation. * Get a list of owned augmentation.
* @remarks * @remarks
* RAM cost: 5 GB * RAM cost: 5 GB * 16/4/1
* *
* *
* This function returns an array containing the names (as strings) of all Augmentations you have. * This function returns an array containing the names (as strings) of all Augmentations you have.
@ -1820,9 +1820,9 @@ export interface Singularity {
getOwnedAugmentations(purchased?: boolean): string[]; getOwnedAugmentations(purchased?: boolean): string[];
/** /**
* SF4.3 - Get a list of augmentation available from a faction. * Get a list of augmentation available from a faction.
* @remarks * @remarks
* RAM cost: 5 GB * RAM cost: 5 GB * 16/4/1
* *
* *
* Returns an array containing the names (as strings) of all Augmentations * Returns an array containing the names (as strings) of all Augmentations
@ -1834,9 +1834,9 @@ export interface Singularity {
getAugmentationsFromFaction(faction: string): string[]; getAugmentationsFromFaction(faction: string): string[];
/** /**
* SF4.3 - Get the pre-requisite of an augmentation. * Get the pre-requisite of an augmentation.
* @remarks * @remarks
* RAM cost: 5 GB * RAM cost: 5 GB * 16/4/1
* *
* *
* This function returns an array with the names of the prerequisite Augmentation(s) for the specified Augmentation. * This function returns an array with the names of the prerequisite Augmentation(s) for the specified Augmentation.
@ -1848,10 +1848,10 @@ export interface Singularity {
getAugmentationPrereq(augName: string): string[]; getAugmentationPrereq(augName: string): string[];
/** /**
* SF4.3 - Get the price and reputation of an augmentation. * Get the price and reputation of an augmentation.
* @deprecated use getAugmentationPrice getAugmentationRepCost * @deprecated use getAugmentationPrice getAugmentationRepCost
* @remarks * @remarks
* RAM cost: 5 GB * RAM cost: 5 GB * 16/4/1
* *
* *
* This function returns an array with two elements that gives the cost for * This function returns an array with two elements that gives the cost for
@ -1868,9 +1868,9 @@ export interface Singularity {
getAugmentationCost(augName: string): [number, number]; getAugmentationCost(augName: string): [number, number];
/** /**
* SF4.3 - Get price of an augmentation. * Get price of an augmentation.
* @remarks * @remarks
* RAM cost: 2.5 GB * RAM cost: 2.5 GB * 16/4/1
* *
* *
* @param augName - Name of Augmentation. * @param augName - Name of Augmentation.
@ -1879,9 +1879,9 @@ export interface Singularity {
getAugmentationPrice(augName: string): number; getAugmentationPrice(augName: string): number;
/** /**
* SF4.3 - Get reputation requirement of an augmentation. * Get reputation requirement of an augmentation.
* @remarks * @remarks
* RAM cost: 2.5 GB * RAM cost: 2.5 GB * 16/4/1
* *
* *
* @param augName - Name of Augmentation. * @param augName - Name of Augmentation.
@ -1890,9 +1890,9 @@ export interface Singularity {
getAugmentationRepReq(augName: string): number; getAugmentationRepReq(augName: string): number;
/** /**
* SF4.3 - Purchase an augmentation * Purchase an augmentation
* @remarks * @remarks
* RAM cost: 5 GB * RAM cost: 5 GB * 16/4/1
* *
* *
* This function will try to purchase the specified Augmentation through the given Faction. * This function will try to purchase the specified Augmentation through the given Faction.
@ -1906,9 +1906,9 @@ export interface Singularity {
purchaseAugmentation(faction: string, augmentation: string): boolean; purchaseAugmentation(faction: string, augmentation: string): boolean;
/** /**
* SF4.3 - Get the stats of an augmentation. * Get the stats of an augmentation.
* @remarks * @remarks
* RAM cost: 5 GB * RAM cost: 5 GB * 16/4/1
* *
* *
* This function returns augmentation stats. * This function returns augmentation stats.
@ -1919,9 +1919,9 @@ export interface Singularity {
getAugmentationStats(name: string): AugmentationStats; getAugmentationStats(name: string): AugmentationStats;
/** /**
* SF4.3 - Install your purchased augmentations. * Install your purchased augmentations.
* @remarks * @remarks
* RAM cost: 5 GB * RAM cost: 5 GB * 16/4/1
* *
* *
* This function will automatically install your Augmentations, resetting the game as usual. * This function will automatically install your Augmentations, resetting the game as usual.
@ -1931,11 +1931,11 @@ export interface Singularity {
installAugmentations(cbScript?: string): void; installAugmentations(cbScript?: string): void;
/** /**
* SF4.1 - Returns an object with the Players stats. * Returns an object with the Players stats.
* @deprecated use getPlayer * @deprecated use getPlayer
* *
* @remarks * @remarks
* RAM cost: 0.5 GB * RAM cost: 0.5 GB * 16/4/1
* *
* *
* @example * @example
@ -1948,11 +1948,11 @@ export interface Singularity {
getStats(): PlayerSkills; getStats(): PlayerSkills;
/** /**
* SF4.1 - Returns an object with various information about your character. * Returns an object with various information about your character.
* @deprecated use getPlayer * @deprecated use getPlayer
* *
* @remarks * @remarks
* RAM cost: 0.5 GB * RAM cost: 0.5 GB * 16/4/1
* *
* *
* @returns Object with various information about your character. * @returns Object with various information about your character.
@ -1960,9 +1960,9 @@ export interface Singularity {
getCharacterInformation(): CharacterInfo; getCharacterInformation(): CharacterInfo;
/** /**
* SF4.1 - Hospitalize the player. * Hospitalize the player.
* @remarks * @remarks
* RAM cost: 0.25 GB * RAM cost: 0.25 GB * 16/4/1
* *
* *
* @returns The cost of the hospitalization. * @returns The cost of the hospitalization.
@ -1970,9 +1970,9 @@ export interface Singularity {
hospitalize(): number; hospitalize(): number;
/** /**
* SF4.3 - Soft reset the game. * Soft reset the game.
* @remarks * @remarks
* RAM cost: 5 GB * RAM cost: 5 GB * 16/4/1
* *
* *
* This function will perform a reset even if you dont have any augmentation installed. * This function will perform a reset even if you dont have any augmentation installed.
@ -1982,9 +1982,9 @@ export interface Singularity {
softReset(cbScript: string): void; softReset(cbScript: string): void;
/** /**
* SF4.3 - Go to a location. * Go to a location.
* @remarks * @remarks
* RAM cost: 5 GB * RAM cost: 5 GB * 16/4/1
* *
* *
* Move the player to a specific location. * Move the player to a specific location.
@ -1995,9 +1995,9 @@ export interface Singularity {
goToLocation(locationName: string): boolean; goToLocation(locationName: string): boolean;
/** /**
* SF4.1 - Get the current server. * Get the current server.
* @remarks * @remarks
* RAM cost: 2 GB * RAM cost: 2 GB * 16/4/1
* *
* *
* @returns Name of the current server. * @returns Name of the current server.
@ -2005,9 +2005,9 @@ export interface Singularity {
getCurrentServer(): string; getCurrentServer(): string;
/** /**
* SF4.1 - Connect to a server. * Connect to a server.
* @remarks * @remarks
* RAM cost: 2 GB * RAM cost: 2 GB * 16/4/1
* *
* *
* Run the connect HOSTNAME command in the terminal. Can only connect to neighbors. * Run the connect HOSTNAME command in the terminal. Can only connect to neighbors.
@ -2017,9 +2017,9 @@ export interface Singularity {
connect(hostname: string): boolean; connect(hostname: string): boolean;
/** /**
* SF4.1 - Run the hack command in the terminal. * Run the hack command in the terminal.
* @remarks * @remarks
* RAM cost: 2 GB * RAM cost: 2 GB * 16/4/1
* *
* *
* @returns Amount of money stolen by manual hacking. * @returns Amount of money stolen by manual hacking.
@ -2027,19 +2027,19 @@ export interface Singularity {
manualHack(): Promise<number>; manualHack(): Promise<number>;
/** /**
* SF4.1 - Run the backdoor command in the terminal. * Run the backdoor command in the terminal.
* @remarks * @remarks
* RAM cost: 2 GB * RAM cost: 2 GB * 16/4/1
* *
* *
* @returns True if the installation was successful. * @returns Promise waiting for the installation to finish.
*/ */
installBackdoor(): Promise<void>; installBackdoor(): Promise<void>;
/** /**
* SF4.2 - Check if the player is focused. * Check if the player is focused.
* @remarks * @remarks
* RAM cost: 0.1 GB * RAM cost: 0.1 GB * 16/4/1
* *
* *
* @returns True if the player is focused. * @returns True if the player is focused.
@ -2047,9 +2047,9 @@ export interface Singularity {
isFocused(): boolean; isFocused(): boolean;
/** /**
* SF4.2 - Set the players focus. * Set the players focus.
* @remarks * @remarks
* RAM cost: 0.1 GB * RAM cost: 0.1 GB * 16/4/1
* *
* @returns True if the focus was changed. * @returns True if the focus was changed.
*/ */

@ -219,12 +219,14 @@ export class Terminal implements ITerminal {
const newSec = server.hackDifficulty; const newSec = server.hackDifficulty;
this.print( this.print(
`Hack successful on '${server.hostname}'! Gained ${numeralWrapper.formatMoney(moneyGained)} and ${numeralWrapper.formatExp( `Hack successful on '${server.hostname}'! Gained ${numeralWrapper.formatMoney(
expGainedOnSuccess, moneyGained,
)} hacking exp`, )} and ${numeralWrapper.formatExp(expGainedOnSuccess)} hacking exp`,
); );
this.print( this.print(
`Security increased on '${server.hostname}' from ${numeralWrapper.formatSecurity(oldSec)} to ${numeralWrapper.formatSecurity(newSec)}`, `Security increased on '${server.hostname}' from ${numeralWrapper.formatSecurity(
oldSec,
)} to ${numeralWrapper.formatSecurity(newSec)}`,
); );
} else { } else {
// Failure // Failure
@ -256,7 +258,9 @@ export class Terminal implements ITerminal {
)}. Gained ${numeralWrapper.formatExp(expGain)} hacking exp.`, )}. Gained ${numeralWrapper.formatExp(expGain)} hacking exp.`,
); );
this.print( this.print(
`Security increased on '${server.hostname}' from ${numeralWrapper.formatSecurity(oldSec)} to ${numeralWrapper.formatSecurity(newSec)}`, `Security increased on '${server.hostname}' from ${numeralWrapper.formatSecurity(
oldSec,
)} to ${numeralWrapper.formatSecurity(newSec)}`,
); );
} }
@ -275,9 +279,9 @@ export class Terminal implements ITerminal {
player.gainHackingExp(expGain); player.gainHackingExp(expGain);
this.print( this.print(
`Security decreased on '${server.hostname}' from ${numeralWrapper.formatSecurity(oldSec)} to ${numeralWrapper.formatSecurity( `Security decreased on '${server.hostname}' from ${numeralWrapper.formatSecurity(
newSec, oldSec,
)} (min: ${numeralWrapper.formatSecurity(server.minDifficulty)})` + )} to ${numeralWrapper.formatSecurity(newSec)} (min: ${numeralWrapper.formatSecurity(server.minDifficulty)})` +
` and Gained ${numeralWrapper.formatExp(expGain)} hacking exp.`, ` and Gained ${numeralWrapper.formatExp(expGain)} hacking exp.`,
); );
} }
@ -309,9 +313,10 @@ export class Terminal implements ITerminal {
this.print("Organization name: " + (!isHacknet ? org : "player")); this.print("Organization name: " + (!isHacknet ? org : "player"));
const hasAdminRights = (!isHacknet && currServ.hasAdminRights) || isHacknet; const hasAdminRights = (!isHacknet && currServ.hasAdminRights) || isHacknet;
this.print("Root Access: " + (hasAdminRights ? "YES" : "NO")); this.print("Root Access: " + (hasAdminRights ? "YES" : "NO"));
this.print("Can run scripts on this host: " + (hasAdminRights ? "YES" : "NO"));
if (currServ instanceof Server) { if (currServ instanceof Server) {
const hackingSkill = currServ.requiredHackingSkill; const hackingSkill = currServ.requiredHackingSkill;
this.print("Required hacking skill: " + (!isHacknet ? hackingSkill : "N/A")); this.print("Required hacking skill for hack() and backdoor: " + (!isHacknet ? hackingSkill : "N/A"));
const security = currServ.hackDifficulty; const security = currServ.hackDifficulty;
this.print("Server security level: " + (!isHacknet ? numeralWrapper.formatServerSecurity(security) : "N/A")); this.print("Server security level: " + (!isHacknet ? numeralWrapper.formatServerSecurity(security) : "N/A"));
const hackingChance = calculateHackingChance(currServ, player); const hackingChance = calculateHackingChance(currServ, player);

@ -85,6 +85,9 @@ export function runScript(
terminal.print( terminal.print(
`Running script with ${numThreads} thread(s), pid ${runningScript.pid} and args: ${JSON.stringify(args)}.`, `Running script with ${numThreads} thread(s), pid ${runningScript.pid} and args: ${JSON.stringify(args)}.`,
); );
if (runningScript.filename.endsWith(".ns")) {
terminal.warn(".ns files are deprecated, please rename everything to .js");
}
if (tailFlag) { if (tailFlag) {
LogBoxEvents.emit(runningScript); LogBoxEvents.emit(runningScript);
} }

@ -79,6 +79,68 @@ function Work(): React.ReactElement {
const router = use.Router(); const router = use.Router();
const classes = useStyles(); const classes = useStyles();
if (!player.isWorking || player.focus) return <></>; if (!player.isWorking || player.focus) return <></>;
if (player.className !== "") {
return (
<>
<TableRow>
<TableCell component="th" scope="row" colSpan={2} classes={{ root: classes.cellNone }}>
<Typography>Work&nbsp;in&nbsp;progress:</Typography>
</TableCell>
</TableRow>
<TableRow>
<TableCell component="th" scope="row" colSpan={2} classes={{ root: classes.cellNone }}>
<Typography>{player.className}</Typography>
</TableCell>
</TableRow>
<TableRow>
<TableCell component="th" scope="row" align="center" colSpan={2} classes={{ root: classes.cellNone }}>
<Button
onClick={() => {
player.startFocusing();
router.toWork();
}}
>
Focus
</Button>
</TableCell>
</TableRow>
</>
);
}
if (player.createProgramName !== "") {
return (
<>
<TableRow>
<TableCell component="th" scope="row" colSpan={2} classes={{ root: classes.cellNone }}>
<Typography>Work&nbsp;in&nbsp;progress:</Typography>
</TableCell>
</TableRow>
<TableRow>
<TableCell component="th" scope="row" colSpan={2} classes={{ root: classes.cellNone }}>
<Typography>
{player.createProgramName}{" "}
{((player.timeWorkedCreateProgram / player.timeNeededToCompleteWork) * 100).toFixed(2)}%
</Typography>
</TableCell>
</TableRow>
<TableRow>
<TableCell component="th" scope="row" align="center" colSpan={2} classes={{ root: classes.cellNone }}>
<Button
onClick={() => {
player.startFocusing();
router.toWork();
}}
>
Focus
</Button>
</TableCell>
</TableRow>
</>
);
}
return ( return (
<> <>
<TableRow> <TableRow>
@ -158,17 +220,29 @@ export function CharacterOverview({ save, killScripts }: IProps): React.ReactEle
const theme = useTheme(); const theme = useTheme();
const hackingProgress = player.calculateSkillProgress( const hackingProgress = player.calculateSkillProgress(
player.hacking_exp, player.hacking_mult * BitNodeMultipliers.HackingLevelMultiplier); player.hacking_exp,
player.hacking_mult * BitNodeMultipliers.HackingLevelMultiplier,
);
const strengthProgress = player.calculateSkillProgress( const strengthProgress = player.calculateSkillProgress(
player.strength_exp, player.strength_mult * BitNodeMultipliers.StrengthLevelMultiplier); player.strength_exp,
player.strength_mult * BitNodeMultipliers.StrengthLevelMultiplier,
);
const defenseProgress = player.calculateSkillProgress( const defenseProgress = player.calculateSkillProgress(
player.defense_exp, player.defense_mult * BitNodeMultipliers.DefenseLevelMultiplier); player.defense_exp,
player.defense_mult * BitNodeMultipliers.DefenseLevelMultiplier,
);
const dexterityProgress = player.calculateSkillProgress( const dexterityProgress = player.calculateSkillProgress(
player.dexterity_exp, player.dexterity_mult * BitNodeMultipliers.DexterityLevelMultiplier); player.dexterity_exp,
player.dexterity_mult * BitNodeMultipliers.DexterityLevelMultiplier,
);
const agilityProgress = player.calculateSkillProgress( const agilityProgress = player.calculateSkillProgress(
player.agility_exp, player.agility_mult * BitNodeMultipliers.AgilityLevelMultiplier); player.agility_exp,
player.agility_mult * BitNodeMultipliers.AgilityLevelMultiplier,
);
const charismaProgress = player.calculateSkillProgress( const charismaProgress = player.calculateSkillProgress(
player.charisma_exp, player.charisma_mult * BitNodeMultipliers.CharismaLevelMultiplier); player.charisma_exp,
player.charisma_mult * BitNodeMultipliers.CharismaLevelMultiplier,
);
return ( return (
<> <>
@ -216,7 +290,7 @@ export function CharacterOverview({ save, killScripts }: IProps): React.ReactEle
<StatsProgressOverviewCell progress={hackingProgress} color={theme.colors.hack} /> <StatsProgressOverviewCell progress={hackingProgress} color={theme.colors.hack} />
</TableRow> </TableRow>
<TableRow> <TableRow>
<TableCell component="th" scope="row" classes={{ root: classes.cell }}> <TableCell component="th" scope="row" classes={{ root: classes.cell }}>
<Typography classes={{ root: classes.hack }}></Typography> <Typography classes={{ root: classes.hack }}></Typography>
</TableCell> </TableCell>
<TableCell align="right" classes={{ root: classes.cell }}> <TableCell align="right" classes={{ root: classes.cell }}>

@ -62,14 +62,44 @@ export function WorkInProgressRoot(): React.ReactElement {
<Reputation reputation={player.workRepGained} /> ( <Reputation reputation={player.workRepGained} /> (
<ReputationRate reputation={player.workRepGainRate * CYCLES_PER_SEC} />) reputation for this faction <br /> <ReputationRate reputation={player.workRepGainRate * CYCLES_PER_SEC} />) reputation for this faction <br />
<br /> <br />
{player.workHackExpGained > 0 && <>{numeralWrapper.formatExp(player.workHackExpGained)} ({numeralWrapper.formatExp(player.workHackExpGainRate * CYCLES_PER_SEC)} / sec) hacking exp <br /></>} {player.workHackExpGained > 0 && (
<>
{numeralWrapper.formatExp(player.workHackExpGained)} (
{numeralWrapper.formatExp(player.workHackExpGainRate * CYCLES_PER_SEC)} / sec) hacking exp <br />
</>
)}
<br /> <br />
{player.workStrExpGained > 0 && <>{numeralWrapper.formatExp(player.workStrExpGained)} ({numeralWrapper.formatExp(player.workStrExpGainRate * CYCLES_PER_SEC)} / sec) strength exp <br /></>} {player.workStrExpGained > 0 && (
{player.workDefExpGained > 0 && <>{numeralWrapper.formatExp(player.workDefExpGained)} ({numeralWrapper.formatExp(player.workDefExpGainRate * CYCLES_PER_SEC)} / sec) defense exp <br /></>} <>
{player.workDexExpGained > 0 && <>{numeralWrapper.formatExp(player.workDexExpGained)} ({numeralWrapper.formatExp(player.workDexExpGainRate * CYCLES_PER_SEC)} / sec) dexterity exp <br /></>} {numeralWrapper.formatExp(player.workStrExpGained)} (
{player.workAgiExpGained > 0 && <>{numeralWrapper.formatExp(player.workAgiExpGained)} ({numeralWrapper.formatExp(player.workAgiExpGainRate * CYCLES_PER_SEC)} / sec) agility exp <br /></>} {numeralWrapper.formatExp(player.workStrExpGainRate * CYCLES_PER_SEC)} / sec) strength exp <br />
</>
)}
{player.workDefExpGained > 0 && (
<>
{numeralWrapper.formatExp(player.workDefExpGained)} (
{numeralWrapper.formatExp(player.workDefExpGainRate * CYCLES_PER_SEC)} / sec) defense exp <br />
</>
)}
{player.workDexExpGained > 0 && (
<>
{numeralWrapper.formatExp(player.workDexExpGained)} (
{numeralWrapper.formatExp(player.workDexExpGainRate * CYCLES_PER_SEC)} / sec) dexterity exp <br />
</>
)}
{player.workAgiExpGained > 0 && (
<>
{numeralWrapper.formatExp(player.workAgiExpGained)} (
{numeralWrapper.formatExp(player.workAgiExpGainRate * CYCLES_PER_SEC)} / sec) agility exp <br />
</>
)}
<br /> <br />
{player.workChaExpGained > 0 && <>{numeralWrapper.formatExp(player.workChaExpGained)} ({numeralWrapper.formatExp(player.workChaExpGainRate * CYCLES_PER_SEC)} / sec) charisma exp <br /></>} {player.workChaExpGained > 0 && (
<>
{numeralWrapper.formatExp(player.workChaExpGained)} (
{numeralWrapper.formatExp(player.workChaExpGainRate * CYCLES_PER_SEC)} / sec) charisma exp <br />
</>
)}
<br /> <br />
You will automatically finish after working for 20 hours. You can cancel earlier if you wish. You will automatically finish after working for 20 hours. You can cancel earlier if you wish.
<br /> <br />
@ -93,6 +123,12 @@ export function WorkInProgressRoot(): React.ReactElement {
router.toCity(); router.toCity();
} }
function unfocus(): void {
router.toFaction(faction);
router.toCity();
player.stopFocusing();
}
let stopText = ""; let stopText = "";
if ( if (
className == CONSTANTS.ClassGymStrength || className == CONSTANTS.ClassGymStrength ||
@ -117,17 +153,50 @@ export function WorkInProgressRoot(): React.ReactElement {
<br /> <br />
<br /> <br />
You have gained: <br /> You have gained: <br />
{player.workHackExpGained > 0 && <>{numeralWrapper.formatExp(player.workHackExpGained)} ({numeralWrapper.formatExp(player.workHackExpGainRate * CYCLES_PER_SEC)} / sec) hacking exp <br /></>} {player.workHackExpGained > 0 && (
{player.workStrExpGained > 0 && <>{numeralWrapper.formatExp(player.workStrExpGained)} ({numeralWrapper.formatExp(player.workStrExpGainRate * CYCLES_PER_SEC)} / sec) strength exp <br /></>} <>
{player.workDefExpGained > 0 && <>{numeralWrapper.formatExp(player.workDefExpGained)} ({numeralWrapper.formatExp(player.workDefExpGainRate * CYCLES_PER_SEC)} / sec) defense exp <br /></>} {numeralWrapper.formatExp(player.workHackExpGained)} (
{player.workDexExpGained > 0 && <>{numeralWrapper.formatExp(player.workDexExpGained)} ({numeralWrapper.formatExp(player.workDexExpGainRate * CYCLES_PER_SEC)} / sec) dexterity exp <br /></>} {numeralWrapper.formatExp(player.workHackExpGainRate * CYCLES_PER_SEC)} / sec) hacking exp <br />
{player.workAgiExpGained > 0 && <>{numeralWrapper.formatExp(player.workAgiExpGained)} ({numeralWrapper.formatExp(player.workAgiExpGainRate * CYCLES_PER_SEC)} / sec) agility exp <br /></>} </>
{player.workChaExpGained > 0 && <>{numeralWrapper.formatExp(player.workChaExpGained)} ({numeralWrapper.formatExp(player.workChaExpGainRate * CYCLES_PER_SEC)} / sec) charisma exp <br /></>} )}
{player.workStrExpGained > 0 && (
<>
{numeralWrapper.formatExp(player.workStrExpGained)} (
{numeralWrapper.formatExp(player.workStrExpGainRate * CYCLES_PER_SEC)} / sec) strength exp <br />
</>
)}
{player.workDefExpGained > 0 && (
<>
{numeralWrapper.formatExp(player.workDefExpGained)} (
{numeralWrapper.formatExp(player.workDefExpGainRate * CYCLES_PER_SEC)} / sec) defense exp <br />
</>
)}
{player.workDexExpGained > 0 && (
<>
{numeralWrapper.formatExp(player.workDexExpGained)} (
{numeralWrapper.formatExp(player.workDexExpGainRate * CYCLES_PER_SEC)} / sec) dexterity exp <br />
</>
)}
{player.workAgiExpGained > 0 && (
<>
{numeralWrapper.formatExp(player.workAgiExpGained)} (
{numeralWrapper.formatExp(player.workAgiExpGainRate * CYCLES_PER_SEC)} / sec) agility exp <br />
</>
)}
{player.workChaExpGained > 0 && (
<>
{numeralWrapper.formatExp(player.workChaExpGained)} (
{numeralWrapper.formatExp(player.workChaExpGainRate * CYCLES_PER_SEC)} / sec) charisma exp <br />
</>
)}
You may cancel at any time You may cancel at any time
</Typography> </Typography>
</Grid> </Grid>
<Grid item> <Grid item>
<Button onClick={cancel}>{stopText}</Button> <Button sx={{ mx: 2 }} onClick={cancel}>
{stopText}
</Button>
<Button onClick={unfocus}>Do something else simultaneously</Button>
</Grid> </Grid>
</Grid> </Grid>
); );
@ -173,26 +242,50 @@ export function WorkInProgressRoot(): React.ReactElement {
<Reputation reputation={player.workRepGained} /> ( <Reputation reputation={player.workRepGained} /> (
<ReputationRate reputation={player.workRepGainRate * CYCLES_PER_SEC} />) reputation for this company <br /> <ReputationRate reputation={player.workRepGainRate * CYCLES_PER_SEC} />) reputation for this company <br />
<br /> <br />
{player.workHackExpGained > 0 && <>{numeralWrapper.formatExp(player.workHackExpGained)} ( {player.workHackExpGained > 0 && (
{`${numeralWrapper.formatExp(player.workHackExpGainRate * CYCLES_PER_SEC)} / sec`} <>
) hacking exp <br /></>} {numeralWrapper.formatExp(player.workHackExpGained)} (
{`${numeralWrapper.formatExp(player.workHackExpGainRate * CYCLES_PER_SEC)} / sec`}
) hacking exp <br />
</>
)}
<br /> <br />
{player.workStrExpGained > 0 && <>{numeralWrapper.formatExp(player.workStrExpGained)} ( {player.workStrExpGained > 0 && (
{`${numeralWrapper.formatExp(player.workStrExpGainRate * CYCLES_PER_SEC)} / sec`} <>
) strength exp <br /></>} {numeralWrapper.formatExp(player.workStrExpGained)} (
{player.workDefExpGained > 0 && <>{numeralWrapper.formatExp(player.workDefExpGained)} ( {`${numeralWrapper.formatExp(player.workStrExpGainRate * CYCLES_PER_SEC)} / sec`}
{`${numeralWrapper.formatExp(player.workDefExpGainRate * CYCLES_PER_SEC)} / sec`} ) strength exp <br />
) defense exp <br /></>} </>
{player.workDexExpGained > 0 && <>{numeralWrapper.formatExp(player.workDexExpGained)} ( )}
{`${numeralWrapper.formatExp(player.workDexExpGainRate * CYCLES_PER_SEC)} / sec`} {player.workDefExpGained > 0 && (
) dexterity exp <br /></>} <>
{player.workAgiExpGained > 0 && <>{numeralWrapper.formatExp(player.workAgiExpGained)} ( {numeralWrapper.formatExp(player.workDefExpGained)} (
{`${numeralWrapper.formatExp(player.workAgiExpGainRate * CYCLES_PER_SEC)} / sec`} {`${numeralWrapper.formatExp(player.workDefExpGainRate * CYCLES_PER_SEC)} / sec`}
) agility exp <br /></>} ) defense exp <br />
</>
)}
{player.workDexExpGained > 0 && (
<>
{numeralWrapper.formatExp(player.workDexExpGained)} (
{`${numeralWrapper.formatExp(player.workDexExpGainRate * CYCLES_PER_SEC)} / sec`}
) dexterity exp <br />
</>
)}
{player.workAgiExpGained > 0 && (
<>
{numeralWrapper.formatExp(player.workAgiExpGained)} (
{`${numeralWrapper.formatExp(player.workAgiExpGainRate * CYCLES_PER_SEC)} / sec`}
) agility exp <br />
</>
)}
<br /> <br />
{player.workChaExpGained > 0 && <>{numeralWrapper.formatExp(player.workChaExpGained)} ( {player.workChaExpGained > 0 && (
{`${numeralWrapper.formatExp(player.workChaExpGainRate * CYCLES_PER_SEC)} / sec`} <>
) charisma exp <br /></>} {numeralWrapper.formatExp(player.workChaExpGained)} (
{`${numeralWrapper.formatExp(player.workChaExpGainRate * CYCLES_PER_SEC)} / sec`}
) charisma exp <br />
</>
)}
<br /> <br />
You will automatically finish after working for 8 hours. You can cancel earlier if you wish, but you will You will automatically finish after working for 8 hours. You can cancel earlier if you wish, but you will
only gain {penaltyString} of the reputation you've earned so far. only gain {penaltyString} of the reputation you've earned so far.
@ -244,26 +337,50 @@ export function WorkInProgressRoot(): React.ReactElement {
<ReputationRate reputation={player.workRepGainRate * CYCLES_PER_SEC} /> <ReputationRate reputation={player.workRepGainRate * CYCLES_PER_SEC} />
) reputation for this company <br /> ) reputation for this company <br />
<br /> <br />
{player.workHackExpGained > 0 && <>{numeralWrapper.formatExp(player.workHackExpGained)} ( {player.workHackExpGained > 0 && (
{`${numeralWrapper.formatExp(player.workHackExpGainRate * CYCLES_PER_SEC)} / sec`} <>
) hacking exp <br /></>} {numeralWrapper.formatExp(player.workHackExpGained)} (
{`${numeralWrapper.formatExp(player.workHackExpGainRate * CYCLES_PER_SEC)} / sec`}
) hacking exp <br />
</>
)}
<br /> <br />
{player.workStrExpGained > 0 && <>{numeralWrapper.formatExp(player.workStrExpGained)} ( {player.workStrExpGained > 0 && (
{`${numeralWrapper.formatExp(player.workStrExpGainRate * CYCLES_PER_SEC)} / sec`} <>
) strength exp <br /></>} {numeralWrapper.formatExp(player.workStrExpGained)} (
{player.workDefExpGained > 0 && <>{numeralWrapper.formatExp(player.workDefExpGained)} ( {`${numeralWrapper.formatExp(player.workStrExpGainRate * CYCLES_PER_SEC)} / sec`}
{`${numeralWrapper.formatExp(player.workDefExpGainRate * CYCLES_PER_SEC)} / sec`} ) strength exp <br />
) defense exp <br /></>} </>
{player.workDexExpGained > 0 && <>{numeralWrapper.formatExp(player.workDexExpGained)} ( )}
{`${numeralWrapper.formatExp(player.workDexExpGainRate * CYCLES_PER_SEC)} / sec`} {player.workDefExpGained > 0 && (
) dexterity exp <br /></>} <>
{player.workAgiExpGained > 0 && <>{numeralWrapper.formatExp(player.workAgiExpGained)} ( {numeralWrapper.formatExp(player.workDefExpGained)} (
{`${numeralWrapper.formatExp(player.workAgiExpGainRate * CYCLES_PER_SEC)} / sec`} {`${numeralWrapper.formatExp(player.workDefExpGainRate * CYCLES_PER_SEC)} / sec`}
) agility exp <br /></>} ) defense exp <br />
</>
)}
{player.workDexExpGained > 0 && (
<>
{numeralWrapper.formatExp(player.workDexExpGained)} (
{`${numeralWrapper.formatExp(player.workDexExpGainRate * CYCLES_PER_SEC)} / sec`}
) dexterity exp <br />
</>
)}
{player.workAgiExpGained > 0 && (
<>
{numeralWrapper.formatExp(player.workAgiExpGained)} (
{`${numeralWrapper.formatExp(player.workAgiExpGainRate * CYCLES_PER_SEC)} / sec`}
) agility exp <br />
</>
)}
<br /> <br />
{player.workChaExpGained > 0 && <>{numeralWrapper.formatExp(player.workChaExpGained)} ( {player.workChaExpGained > 0 && (
{`${numeralWrapper.formatExp(player.workChaExpGainRate * CYCLES_PER_SEC)} / sec`} <>
) charisma exp <br /></>} {numeralWrapper.formatExp(player.workChaExpGained)} (
{`${numeralWrapper.formatExp(player.workChaExpGainRate * CYCLES_PER_SEC)} / sec`}
) charisma exp <br />
</>
)}
<br /> <br />
You will automatically finish after working for 8 hours. You can cancel earlier if you wish, and there will You will automatically finish after working for 8 hours. You can cancel earlier if you wish, and there will
be no penalty because this is a part-time job. be no penalty because this is a part-time job.
@ -321,6 +438,14 @@ export function WorkInProgressRoot(): React.ReactElement {
} }
if (player.createProgramName !== "") { if (player.createProgramName !== "") {
function cancel(): void {
player.finishCreateProgramWork(true);
router.toTerminal();
}
function unfocus(): void {
router.toTerminal();
player.stopFocusing();
}
return ( return (
<Grid container direction="column" justifyContent="center" alignItems="center" style={{ minHeight: "100vh" }}> <Grid container direction="column" justifyContent="center" alignItems="center" style={{ minHeight: "100vh" }}>
<Grid item> <Grid item>
@ -336,14 +461,10 @@ export function WorkInProgressRoot(): React.ReactElement {
</Typography> </Typography>
</Grid> </Grid>
<Grid item> <Grid item>
<Button <Button sx={{ mx: 2 }} onClick={cancel}>
onClick={() => {
player.finishCreateProgramWork(true);
router.toTerminal();
}}
>
Cancel work on creating program Cancel work on creating program
</Button> </Button>
<Button onClick={unfocus}>Do something else simultaneously</Button>
</Grid> </Grid>
</Grid> </Grid>
); );