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.gainAgilityExp(unweightedGain * action.weights.agi * player.agility_exp_mult * skillMult);
player.gainCharismaExp(unweightedGain * action.weights.cha * player.charisma_exp_mult * skillMult);
let intExp = unweightedIntGain * action.weights.int * skillMult;
if (intExp > 1) {
intExp = Math.pow(intExp, 0.8);
}
player.gainIntelligenceExp(intExp);
player.gainIntelligenceExp(unweightedIntGain * action.weights.int * skillMult);
}
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:
</Typography>
<TextField autoFocus={true} placeholder="Corporation Name" onChange={onChange} value={name} />
<Button onClick={seed} disabled={name == ""}>
Use seed money
</Button>
{player.bitNodeN === 3 && (
<Button onClick={seed} disabled={name == ""}>
Use seed money
</Button>
)}
<Button onClick={selfFund} disabled={name == "" || !canSelfFund}>
Self-Fund (<Money money={150e9} player={player} />)
</Button>

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

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

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

@ -12,7 +12,7 @@ import { IPlayer } from "../../PersonObjects/IPlayer";
import ButtonGroup from "@mui/material/ButtonGroup";
// 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 {
player: IPlayer;

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

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

@ -87,7 +87,6 @@ export function prestigeAugmentation(this: PlayerObject): void {
this.currentServer = SpecialServers.Home;
this.numPeopleKilled = 0;
this.karma = 0;
//Reset stats
this.hacking = 1;
@ -183,6 +182,7 @@ export function prestigeAugmentation(this: PlayerObject): void {
export function prestigeSourceFile(this: IPlayer): void {
this.prestigeAugmentation();
this.karma = 0;
// 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) {
if (this.sleeves[i] instanceof Sleeve) {
@ -671,12 +671,36 @@ export function finishWork(this: IPlayer, cancelled: boolean, sing = false): str
<Money money={this.workMoneyGained} />
<br />
<Reputation reputation={this.workRepGained} /> reputation for the company <br />
{this.workHackExpGained > 0 && <>{numeralWrapper.formatExp(this.workHackExpGained)} hacking 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 /></>}
{this.workHackExpGained > 0 && (
<>
{numeralWrapper.formatExp(this.workHackExpGained)} hacking 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 />
</>
);
@ -1273,11 +1297,15 @@ export function startCreateProgramWork(
}
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
const reqLvl = this.createProgramReqLvl;
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 *= focusBonus;
//Skill multiplier directly applied to "time worked"
this.timeWorked += CONSTANTS._idleSpeed * numCycles;
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 {
const achievement = achievements[achievementId];
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() });
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) {
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;
}
if (server.openPortCount >= server.numOpenPortsRequired) {
server.hasAdminRights = true;
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;
}

@ -1294,15 +1294,15 @@ export interface TIX {
/**
* Singularity API
* @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
*/
export interface Singularity {
/**
* SF4.1 - Take university class.
* Take university class.
*
* @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.
@ -1320,10 +1320,10 @@ export interface Singularity {
universityCourse(universityName: string, courseName: string): boolean;
/**
* SF4.1 - Workout at the gym.
* Workout at the gym.
*
* @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
@ -1341,9 +1341,9 @@ export interface Singularity {
gymWorkout(gymName: string, stat: string): boolean;
/**
* SF4.1 - Travel to another city.
* Travel to another city.
* @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
@ -1355,9 +1355,9 @@ export interface Singularity {
travelToCity(city: string): boolean;
/**
* SF4.1 - Purchase the TOR router.
* Purchase the TOR router.
* @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
@ -1369,9 +1369,9 @@ export interface Singularity {
purchaseTor(): boolean;
/**
* SF4.1 - Purchase a program from the dark web.
* Purchase a program from the dark web.
* @remarks
* RAM cost: 2 GB
* RAM cost: 2 GB * 16/4/1
*
*
* This function allows you to automatically purchase programs. You MUST have a
@ -1395,9 +1395,9 @@ export interface Singularity {
purchaseProgram(programName: string): boolean;
/**
* SF4.1 - Check if the player is busy.
* Check if the player is busy.
* @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
@ -1409,9 +1409,9 @@ export interface Singularity {
isBusy(): boolean;
/**
* SF4.1 - Stop the current action.
* Stop the current action.
* @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.
@ -1432,9 +1432,9 @@ export interface Singularity {
stopAction(): boolean;
/**
* SF4.2 - Upgrade home computer RAM.
* Upgrade home computer RAM.
* @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
@ -1447,9 +1447,9 @@ export interface Singularity {
upgradeHomeRam(): boolean;
/**
* SF4.2 - Upgrade home computer cores.
* Upgrade home computer cores.
* @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
@ -1462,9 +1462,9 @@ export interface Singularity {
upgradeHomeCores(): boolean;
/**
* SF4.2 - Get the price of upgrading home RAM.
* Get the price of upgrading home RAM.
* @remarks
* RAM cost: 1.5 GB
* RAM cost: 1.5 GB * 16/4/1
*
*
* Returns the cost of upgrading the players home computer RAM.
@ -1474,9 +1474,9 @@ export interface Singularity {
getUpgradeHomeRamCost(): number;
/**
* SF4.2 - Get the price of upgrading home cores.
* Get the price of upgrading home cores.
* @remarks
* RAM cost: 1.5 GB
* RAM cost: 1.5 GB * 16/4/1
*
*
* Returns the cost of upgrading the players home computer cores.
@ -1486,9 +1486,9 @@ export interface Singularity {
getUpgradeHomeCoresCost(): number;
/**
* SF4.2 - Work for a company.
* Work for a company.
* @remarks
* RAM cost: 3 GB
* RAM cost: 3 GB * 16/4/1
*
*
* 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;
/**
* SF4.2 - Apply for a job at a company.
* Apply for a job at a company.
* @remarks
* RAM cost: 3 GB
* RAM cost: 3 GB * 16/4/1
*
*
* This function will automatically try to apply to the specified company
@ -1549,9 +1549,9 @@ export interface Singularity {
applyToCompany(companyName: string, field: string): boolean;
/**
* SF4.2 - Get company reputation.
* Get company reputation.
* @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.
@ -1563,9 +1563,9 @@ export interface Singularity {
getCompanyRep(companyName: string): number;
/**
* SF4.2 - Get company favor.
* Get company favor.
* @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.
@ -1577,9 +1577,9 @@ export interface Singularity {
getCompanyFavor(companyName: string): number;
/**
* SF4.2 - Get company favor gain.
* Get company favor gain.
* @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
@ -1591,9 +1591,9 @@ export interface Singularity {
getCompanyFavorGain(companyName: string): number;
/**
* SF4.2 - List all current faction invitations.
* List all current faction invitations.
* @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.
@ -1603,9 +1603,9 @@ export interface Singularity {
checkFactionInvitations(): string[];
/**
* SF4.2 - Join a faction.
* Join a faction.
* @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.
@ -1616,9 +1616,9 @@ export interface Singularity {
joinFaction(faction: string): boolean;
/**
* SF4.2 - Work for a faction.
* Work for a faction.
* @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.
@ -1659,9 +1659,9 @@ export interface Singularity {
workForFaction(faction: string, workType: string, focus?: boolean): boolean;
/**
* SF4.2 - Get faction reputation.
* Get faction reputation.
* @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.
@ -1672,9 +1672,9 @@ export interface Singularity {
getFactionRep(faction: string): number;
/**
* SF4.2 - Get faction favor.
* Get faction favor.
* @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.
@ -1685,9 +1685,9 @@ export interface Singularity {
getFactionFavor(faction: string): number;
/**
* SF4.2 - Get faction favor gain.
* Get faction favor gain.
* @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
@ -1699,9 +1699,9 @@ export interface Singularity {
getFactionFavorGain(faction: string): number;
/**
* SF4.3 - Donate to a faction.
* Donate to a faction.
* @remarks
* RAM cost: 5 GB
* RAM cost: 5 GB * 16/4/1
*
*
* 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;
/**
* SF4.3 - Create a program.
* Create a program.
* @remarks
* RAM cost: 5 GB
* RAM cost: 5 GB * 16/4/1
*
*
* This function will automatically set you to start working on creating the
@ -1754,9 +1754,9 @@ export interface Singularity {
createProgram(program: string): boolean;
/**
* SF4.3 - Commit a crime.
* Commit a crime.
* @remarks
* RAM cost: 5 GB
* RAM cost: 5 GB * 16/4/1
*
*
* This function is used to automatically attempt to commit crimes.
@ -1781,9 +1781,9 @@ export interface Singularity {
commitCrime(crime: string): number;
/**
* SF4.3 - Get chance to successfully commit a crime.
* Get chance to successfully commit a crime.
* @remarks
* RAM cost: 5 GB
* RAM cost: 5 GB * 16/4/1
*
*
* This function returns your chance of success at commiting the specified crime.
@ -1794,9 +1794,9 @@ export interface Singularity {
getCrimeChance(crime: string): number;
/**
* SF4.3 - Get stats related to a crime.
* Get stats related to a crime.
* @remarks
* RAM cost: 5 GB
* RAM cost: 5 GB * 16/4/1
*
*
* Returns the stats of the crime.
@ -1807,9 +1807,9 @@ export interface Singularity {
getCrimeStats(crime: string): CrimeStats;
/**
* SF4.3 - Get a list of owned augmentation.
* Get a list of owned augmentation.
* @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.
@ -1820,9 +1820,9 @@ export interface Singularity {
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
* RAM cost: 5 GB
* RAM cost: 5 GB * 16/4/1
*
*
* Returns an array containing the names (as strings) of all Augmentations
@ -1834,9 +1834,9 @@ export interface Singularity {
getAugmentationsFromFaction(faction: string): string[];
/**
* SF4.3 - Get the pre-requisite of an augmentation.
* Get the pre-requisite of an augmentation.
* @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.
@ -1848,10 +1848,10 @@ export interface Singularity {
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
* @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
@ -1868,9 +1868,9 @@ export interface Singularity {
getAugmentationCost(augName: string): [number, number];
/**
* SF4.3 - Get price of an augmentation.
* Get price of an augmentation.
* @remarks
* RAM cost: 2.5 GB
* RAM cost: 2.5 GB * 16/4/1
*
*
* @param augName - Name of Augmentation.
@ -1879,9 +1879,9 @@ export interface Singularity {
getAugmentationPrice(augName: string): number;
/**
* SF4.3 - Get reputation requirement of an augmentation.
* Get reputation requirement of an augmentation.
* @remarks
* RAM cost: 2.5 GB
* RAM cost: 2.5 GB * 16/4/1
*
*
* @param augName - Name of Augmentation.
@ -1890,9 +1890,9 @@ export interface Singularity {
getAugmentationRepReq(augName: string): number;
/**
* SF4.3 - Purchase an augmentation
* Purchase an augmentation
* @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.
@ -1906,9 +1906,9 @@ export interface Singularity {
purchaseAugmentation(faction: string, augmentation: string): boolean;
/**
* SF4.3 - Get the stats of an augmentation.
* Get the stats of an augmentation.
* @remarks
* RAM cost: 5 GB
* RAM cost: 5 GB * 16/4/1
*
*
* This function returns augmentation stats.
@ -1919,9 +1919,9 @@ export interface Singularity {
getAugmentationStats(name: string): AugmentationStats;
/**
* SF4.3 - Install your purchased augmentations.
* Install your purchased augmentations.
* @remarks
* RAM cost: 5 GB
* RAM cost: 5 GB * 16/4/1
*
*
* This function will automatically install your Augmentations, resetting the game as usual.
@ -1931,11 +1931,11 @@ export interface Singularity {
installAugmentations(cbScript?: string): void;
/**
* SF4.1 - Returns an object with the Players stats.
* Returns an object with the Players stats.
* @deprecated use getPlayer
*
* @remarks
* RAM cost: 0.5 GB
* RAM cost: 0.5 GB * 16/4/1
*
*
* @example
@ -1948,11 +1948,11 @@ export interface Singularity {
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
*
* @remarks
* RAM cost: 0.5 GB
* RAM cost: 0.5 GB * 16/4/1
*
*
* @returns Object with various information about your character.
@ -1960,9 +1960,9 @@ export interface Singularity {
getCharacterInformation(): CharacterInfo;
/**
* SF4.1 - Hospitalize the player.
* Hospitalize the player.
* @remarks
* RAM cost: 0.25 GB
* RAM cost: 0.25 GB * 16/4/1
*
*
* @returns The cost of the hospitalization.
@ -1970,9 +1970,9 @@ export interface Singularity {
hospitalize(): number;
/**
* SF4.3 - Soft reset the game.
* Soft reset the game.
* @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.
@ -1982,9 +1982,9 @@ export interface Singularity {
softReset(cbScript: string): void;
/**
* SF4.3 - Go to a location.
* Go to a location.
* @remarks
* RAM cost: 5 GB
* RAM cost: 5 GB * 16/4/1
*
*
* Move the player to a specific location.
@ -1995,9 +1995,9 @@ export interface Singularity {
goToLocation(locationName: string): boolean;
/**
* SF4.1 - Get the current server.
* Get the current server.
* @remarks
* RAM cost: 2 GB
* RAM cost: 2 GB * 16/4/1
*
*
* @returns Name of the current server.
@ -2005,9 +2005,9 @@ export interface Singularity {
getCurrentServer(): string;
/**
* SF4.1 - Connect to a server.
* Connect to a server.
* @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.
@ -2017,9 +2017,9 @@ export interface Singularity {
connect(hostname: string): boolean;
/**
* SF4.1 - Run the hack command in the terminal.
* Run the hack command in the terminal.
* @remarks
* RAM cost: 2 GB
* RAM cost: 2 GB * 16/4/1
*
*
* @returns Amount of money stolen by manual hacking.
@ -2027,19 +2027,19 @@ export interface Singularity {
manualHack(): Promise<number>;
/**
* SF4.1 - Run the backdoor command in the terminal.
* Run the backdoor command in the terminal.
* @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>;
/**
* SF4.2 - Check if the player is focused.
* Check if the player is focused.
* @remarks
* RAM cost: 0.1 GB
* RAM cost: 0.1 GB * 16/4/1
*
*
* @returns True if the player is focused.
@ -2047,9 +2047,9 @@ export interface Singularity {
isFocused(): boolean;
/**
* SF4.2 - Set the players focus.
* Set the players focus.
* @remarks
* RAM cost: 0.1 GB
* RAM cost: 0.1 GB * 16/4/1
*
* @returns True if the focus was changed.
*/

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

@ -85,6 +85,9 @@ export function runScript(
terminal.print(
`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) {
LogBoxEvents.emit(runningScript);
}

@ -79,6 +79,68 @@ function Work(): React.ReactElement {
const router = use.Router();
const classes = useStyles();
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 (
<>
<TableRow>
@ -158,17 +220,29 @@ export function CharacterOverview({ save, killScripts }: IProps): React.ReactEle
const theme = useTheme();
const hackingProgress = player.calculateSkillProgress(
player.hacking_exp, player.hacking_mult * BitNodeMultipliers.HackingLevelMultiplier);
player.hacking_exp,
player.hacking_mult * BitNodeMultipliers.HackingLevelMultiplier,
);
const strengthProgress = player.calculateSkillProgress(
player.strength_exp, player.strength_mult * BitNodeMultipliers.StrengthLevelMultiplier);
player.strength_exp,
player.strength_mult * BitNodeMultipliers.StrengthLevelMultiplier,
);
const defenseProgress = player.calculateSkillProgress(
player.defense_exp, player.defense_mult * BitNodeMultipliers.DefenseLevelMultiplier);
player.defense_exp,
player.defense_mult * BitNodeMultipliers.DefenseLevelMultiplier,
);
const dexterityProgress = player.calculateSkillProgress(
player.dexterity_exp, player.dexterity_mult * BitNodeMultipliers.DexterityLevelMultiplier);
player.dexterity_exp,
player.dexterity_mult * BitNodeMultipliers.DexterityLevelMultiplier,
);
const agilityProgress = player.calculateSkillProgress(
player.agility_exp, player.agility_mult * BitNodeMultipliers.AgilityLevelMultiplier);
player.agility_exp,
player.agility_mult * BitNodeMultipliers.AgilityLevelMultiplier,
);
const charismaProgress = player.calculateSkillProgress(
player.charisma_exp, player.charisma_mult * BitNodeMultipliers.CharismaLevelMultiplier);
player.charisma_exp,
player.charisma_mult * BitNodeMultipliers.CharismaLevelMultiplier,
);
return (
<>
@ -216,7 +290,7 @@ export function CharacterOverview({ save, killScripts }: IProps): React.ReactEle
<StatsProgressOverviewCell progress={hackingProgress} color={theme.colors.hack} />
</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>
</TableCell>
<TableCell align="right" classes={{ root: classes.cell }}>

@ -62,14 +62,44 @@ export function WorkInProgressRoot(): React.ReactElement {
<Reputation reputation={player.workRepGained} /> (
<ReputationRate reputation={player.workRepGainRate * CYCLES_PER_SEC} />) reputation for this faction <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 />
{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.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 />
</>
)}
<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 />
You will automatically finish after working for 20 hours. You can cancel earlier if you wish.
<br />
@ -93,6 +123,12 @@ export function WorkInProgressRoot(): React.ReactElement {
router.toCity();
}
function unfocus(): void {
router.toFaction(faction);
router.toCity();
player.stopFocusing();
}
let stopText = "";
if (
className == CONSTANTS.ClassGymStrength ||
@ -117,17 +153,50 @@ export function WorkInProgressRoot(): React.ReactElement {
<br />
<br />
You have gained: <br />
{player.workHackExpGained > 0 && <>{numeralWrapper.formatExp(player.workHackExpGained)} ({numeralWrapper.formatExp(player.workHackExpGainRate * CYCLES_PER_SEC)} / sec) hacking 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 /></>}
{player.workHackExpGained > 0 && (
<>
{numeralWrapper.formatExp(player.workHackExpGained)} (
{numeralWrapper.formatExp(player.workHackExpGainRate * CYCLES_PER_SEC)} / sec) hacking 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
</Typography>
</Grid>
<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>
);
@ -173,26 +242,50 @@ export function WorkInProgressRoot(): React.ReactElement {
<Reputation reputation={player.workRepGained} /> (
<ReputationRate reputation={player.workRepGainRate * CYCLES_PER_SEC} />) reputation for this company <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 />
{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.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 />
</>
)}
<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 />
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.
@ -244,26 +337,50 @@ export function WorkInProgressRoot(): React.ReactElement {
<ReputationRate reputation={player.workRepGainRate * CYCLES_PER_SEC} />
) reputation for this company <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 />
{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.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 />
</>
)}
<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 />
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.
@ -321,6 +438,14 @@ export function WorkInProgressRoot(): React.ReactElement {
}
if (player.createProgramName !== "") {
function cancel(): void {
player.finishCreateProgramWork(true);
router.toTerminal();
}
function unfocus(): void {
router.toTerminal();
player.stopFocusing();
}
return (
<Grid container direction="column" justifyContent="center" alignItems="center" style={{ minHeight: "100vh" }}>
<Grid item>
@ -336,14 +461,10 @@ export function WorkInProgressRoot(): React.ReactElement {
</Typography>
</Grid>
<Grid item>
<Button
onClick={() => {
player.finishCreateProgramWork(true);
router.toTerminal();
}}
>
<Button sx={{ mx: 2 }} onClick={cancel}>
Cancel work on creating program
</Button>
<Button onClick={unfocus}>Do something else simultaneously</Button>
</Grid>
</Grid>
);