mirror of
https://github.com/bitburner-official/bitburner-src.git
synced 2024-12-29 17:37:34 +01:00
create program and grafting done
This commit is contained in:
parent
647392626e
commit
606f1bf6c4
@ -7,6 +7,7 @@ import { SpecialServers } from "../Server/data/SpecialServers";
|
|||||||
import { numeralWrapper } from "../ui/numeralFormat";
|
import { numeralWrapper } from "../ui/numeralFormat";
|
||||||
import { Money } from "../ui/React/Money";
|
import { Money } from "../ui/React/Money";
|
||||||
import { DarkWebItem } from "./DarkWebItem";
|
import { DarkWebItem } from "./DarkWebItem";
|
||||||
|
import { isCreateProgramWork } from "../Work/CreateProgramWork";
|
||||||
|
|
||||||
//Posts a "help" message if connected to DarkWeb
|
//Posts a "help" message if connected to DarkWeb
|
||||||
export function checkIfConnectedToDarkweb(): void {
|
export function checkIfConnectedToDarkweb(): void {
|
||||||
@ -74,7 +75,7 @@ export function buyDarkwebItem(itemName: string): void {
|
|||||||
|
|
||||||
Player.getHomeComputer().pushProgram(item.program);
|
Player.getHomeComputer().pushProgram(item.program);
|
||||||
// Cancel if the program is in progress of writing
|
// Cancel if the program is in progress of writing
|
||||||
if (Player.createProgramName === item.program) {
|
if (isCreateProgramWork(Player.currentWork) && Player.currentWork.programName === item.program) {
|
||||||
Player.isWorking = false;
|
Player.isWorking = false;
|
||||||
Player.resetWorkStatus();
|
Player.resetWorkStatus();
|
||||||
}
|
}
|
||||||
|
@ -38,7 +38,6 @@ export function SaveFile(): React.ReactElement {
|
|||||||
|
|
||||||
function doRestore(): void {
|
function doRestore(): void {
|
||||||
const save = JSON.parse(saveFile);
|
const save = JSON.parse(saveFile);
|
||||||
console.log(Object.keys(save));
|
|
||||||
// TODO: Continue here.
|
// TODO: Continue here.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -150,7 +150,7 @@ function initSaveFunctions(): void {
|
|||||||
try {
|
try {
|
||||||
saveObject.exportGame();
|
saveObject.exportGame();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(error);
|
console.error(error);
|
||||||
SnackbarEvents.emit("Could not export game.", ToastVariant.ERROR, 2000);
|
SnackbarEvents.emit("Could not export game.", ToastVariant.ERROR, 2000);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -199,7 +199,7 @@ function initElectronBridge(): void {
|
|||||||
bridge.send("save-completed");
|
bridge.send("save-completed");
|
||||||
})
|
})
|
||||||
.catch((error: unknown) => {
|
.catch((error: unknown) => {
|
||||||
console.log(error);
|
console.error(error);
|
||||||
SnackbarEvents.emit("Could not save game.", ToastVariant.ERROR, 2000);
|
SnackbarEvents.emit("Could not save game.", ToastVariant.ERROR, 2000);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -207,7 +207,7 @@ function initElectronBridge(): void {
|
|||||||
try {
|
try {
|
||||||
window.appSaveFns.triggerGameExport();
|
window.appSaveFns.triggerGameExport();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(error);
|
console.error(error);
|
||||||
SnackbarEvents.emit("Could not export game.", ToastVariant.ERROR, 2000);
|
SnackbarEvents.emit("Could not export game.", ToastVariant.ERROR, 2000);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -215,7 +215,7 @@ function initElectronBridge(): void {
|
|||||||
try {
|
try {
|
||||||
window.appSaveFns.triggerScriptsExport();
|
window.appSaveFns.triggerScriptsExport();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(error);
|
console.error(error);
|
||||||
SnackbarEvents.emit("Could not export scripts.", ToastVariant.ERROR, 2000);
|
SnackbarEvents.emit("Could not export scripts.", ToastVariant.ERROR, 2000);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -252,7 +252,6 @@ export class Gang implements IGang {
|
|||||||
const total = Object.values(AllGangs)
|
const total = Object.values(AllGangs)
|
||||||
.map((g) => g.territory)
|
.map((g) => g.territory)
|
||||||
.reduce((p, c) => p + c, 0);
|
.reduce((p, c) => p + c, 0);
|
||||||
console.log(total);
|
|
||||||
Object.values(AllGangs).forEach((g) => (g.territory /= total));
|
Object.values(AllGangs).forEach((g) => (g.territory /= total));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2418,8 +2418,6 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
|
|||||||
workChaExpGained: Player.workChaExpGained,
|
workChaExpGained: Player.workChaExpGained,
|
||||||
workRepGained: Player.workRepGained,
|
workRepGained: Player.workRepGained,
|
||||||
workMoneyGained: Player.workMoneyGained,
|
workMoneyGained: Player.workMoneyGained,
|
||||||
createProgramName: Player.createProgramName,
|
|
||||||
createProgramReqLvl: Player.createProgramReqLvl,
|
|
||||||
work_money_mult: Player.work_money_mult,
|
work_money_mult: Player.work_money_mult,
|
||||||
hacknet_node_money_mult: Player.hacknet_node_money_mult,
|
hacknet_node_money_mult: Player.hacknet_node_money_mult,
|
||||||
hacknet_node_purchase_cost_mult: Player.hacknet_node_purchase_cost_mult,
|
hacknet_node_purchase_cost_mult: Player.hacknet_node_purchase_cost_mult,
|
||||||
|
@ -7,6 +7,7 @@ import { getGraftingAvailableAugs, calculateGraftingTimeWithBonus } from "../Per
|
|||||||
import { IPlayer } from "../PersonObjects/IPlayer";
|
import { IPlayer } from "../PersonObjects/IPlayer";
|
||||||
import { Grafting as IGrafting } from "../ScriptEditor/NetscriptDefinitions";
|
import { Grafting as IGrafting } from "../ScriptEditor/NetscriptDefinitions";
|
||||||
import { Router } from "../ui/GameRoot";
|
import { Router } from "../ui/GameRoot";
|
||||||
|
import { GraftingWork } from "../Work/GraftingWork";
|
||||||
|
|
||||||
export function NetscriptGrafting(player: IPlayer): InternalAPI<IGrafting> {
|
export function NetscriptGrafting(player: IPlayer): InternalAPI<IGrafting> {
|
||||||
const checkGraftingAPIAccess = (ctx: NetscriptContext): void => {
|
const checkGraftingAPIAccess = (ctx: NetscriptContext): void => {
|
||||||
@ -79,8 +80,13 @@ export function NetscriptGrafting(player: IPlayer): InternalAPI<IGrafting> {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
player.loseMoney(craftableAug.cost, "augmentations");
|
player.startNEWWork(
|
||||||
player.startGraftAugmentationWork(augName, craftableAug.time);
|
new GraftingWork({
|
||||||
|
singularity: true,
|
||||||
|
augmentation: augName,
|
||||||
|
player: player,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
if (focus) {
|
if (focus) {
|
||||||
player.startFocusing();
|
player.startFocusing();
|
||||||
|
@ -51,6 +51,7 @@ import { enterBitNode } from "../RedPill";
|
|||||||
import { FactionNames } from "../Faction/data/FactionNames";
|
import { FactionNames } from "../Faction/data/FactionNames";
|
||||||
import { WorkType } from "../utils/WorkType";
|
import { WorkType } from "../utils/WorkType";
|
||||||
import { ClassWork, ClassType } from "../Work/ClassWork";
|
import { ClassWork, ClassType } from "../Work/ClassWork";
|
||||||
|
import { CreateProgramWork, isCreateProgramWork } from "../Work/CreateProgramWork";
|
||||||
|
|
||||||
export function NetscriptSingularity(player: IPlayer, workerScript: WorkerScript): InternalAPI<ISingularity> {
|
export function NetscriptSingularity(player: IPlayer, workerScript: WorkerScript): InternalAPI<ISingularity> {
|
||||||
const getAugmentation = function (_ctx: NetscriptContext, name: string): Augmentation {
|
const getAugmentation = function (_ctx: NetscriptContext, name: string): Augmentation {
|
||||||
@ -528,7 +529,7 @@ export function NetscriptSingularity(player: IPlayer, workerScript: WorkerScript
|
|||||||
|
|
||||||
player.getHomeComputer().pushProgram(item.program);
|
player.getHomeComputer().pushProgram(item.program);
|
||||||
// Cancel if the program is in progress of writing
|
// Cancel if the program is in progress of writing
|
||||||
if (player.createProgramName === item.program) {
|
if (isCreateProgramWork(player.currentWork) && player.currentWork.programName === item.program) {
|
||||||
player.isWorking = false;
|
player.isWorking = false;
|
||||||
player.resetWorkStatus();
|
player.resetWorkStatus();
|
||||||
}
|
}
|
||||||
@ -1182,7 +1183,13 @@ export function NetscriptSingularity(player: IPlayer, workerScript: WorkerScript
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
player.startCreateProgramWork(p.name, create.time, create.level);
|
player.startNEWWork(
|
||||||
|
new CreateProgramWork({
|
||||||
|
programName: p.name,
|
||||||
|
singularity: true,
|
||||||
|
player: player,
|
||||||
|
}),
|
||||||
|
);
|
||||||
if (focus) {
|
if (focus) {
|
||||||
player.startFocusing();
|
player.startFocusing();
|
||||||
Router.toWork();
|
Router.toWork();
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { CheckBox, CheckBoxOutlineBlank, Construction } from "@mui/icons-material";
|
import { CheckBox, CheckBoxOutlineBlank, Construction } from "@mui/icons-material";
|
||||||
import { Box, Button, Container, List, ListItemButton, Paper, Typography } from "@mui/material";
|
import { Box, Button, Container, List, ListItemButton, Paper, Typography } from "@mui/material";
|
||||||
import React, { useEffect, useState } from "react";
|
import React, { useEffect, useState } from "react";
|
||||||
|
import { GraftingWork } from "../../../Work/GraftingWork";
|
||||||
import { Augmentation } from "../../../Augmentation/Augmentation";
|
import { Augmentation } from "../../../Augmentation/Augmentation";
|
||||||
import { AugmentationNames } from "../../../Augmentation/data/AugmentationNames";
|
import { AugmentationNames } from "../../../Augmentation/data/AugmentationNames";
|
||||||
import { StaticAugmentations } from "../../../Augmentation/StaticAugmentations";
|
import { StaticAugmentations } from "../../../Augmentation/StaticAugmentations";
|
||||||
@ -19,7 +20,7 @@ import { IPlayer } from "../../IPlayer";
|
|||||||
import { GraftableAugmentation } from "../GraftableAugmentation";
|
import { GraftableAugmentation } from "../GraftableAugmentation";
|
||||||
import { calculateGraftingTimeWithBonus, getGraftingAvailableAugs } from "../GraftingHelpers";
|
import { calculateGraftingTimeWithBonus, getGraftingAvailableAugs } from "../GraftingHelpers";
|
||||||
|
|
||||||
const GraftableAugmentations: IMap<GraftableAugmentation> = {};
|
export const GraftableAugmentations: IMap<GraftableAugmentation> = {};
|
||||||
|
|
||||||
const canGraft = (player: IPlayer, aug: GraftableAugmentation): boolean => {
|
const canGraft = (player: IPlayer, aug: GraftableAugmentation): boolean => {
|
||||||
if (player.money < aug.cost) {
|
if (player.money < aug.cost) {
|
||||||
@ -154,9 +155,13 @@ export const GraftingRoot = (): React.ReactElement => {
|
|||||||
open={graftOpen}
|
open={graftOpen}
|
||||||
onClose={() => setGraftOpen(false)}
|
onClose={() => setGraftOpen(false)}
|
||||||
onConfirm={() => {
|
onConfirm={() => {
|
||||||
const graftableAug = GraftableAugmentations[selectedAug];
|
player.startNEWWork(
|
||||||
player.loseMoney(graftableAug.cost, "augmentations");
|
new GraftingWork({
|
||||||
player.startGraftAugmentationWork(selectedAug, graftableAug.time);
|
augmentation: selectedAug,
|
||||||
|
singularity: false,
|
||||||
|
player: player,
|
||||||
|
}),
|
||||||
|
);
|
||||||
player.startFocusing();
|
player.startFocusing();
|
||||||
router.toWork();
|
router.toWork();
|
||||||
}}
|
}}
|
||||||
|
@ -126,12 +126,7 @@ export interface IPlayer extends IPerson {
|
|||||||
bladeburner_success_chance_mult: number;
|
bladeburner_success_chance_mult: number;
|
||||||
|
|
||||||
currentWork: Work | null;
|
currentWork: Work | null;
|
||||||
createProgramReqLvl: number;
|
|
||||||
factionWorkType: string;
|
factionWorkType: string;
|
||||||
createProgramName: string;
|
|
||||||
timeWorkedCreateProgram: number;
|
|
||||||
graftAugmentationName: string;
|
|
||||||
timeWorkedGraftAugmentation: number;
|
|
||||||
timeNeededToCompleteWork: number;
|
timeNeededToCompleteWork: number;
|
||||||
focus: boolean;
|
focus: boolean;
|
||||||
currentWorkFactionName: string;
|
currentWorkFactionName: string;
|
||||||
@ -227,7 +222,6 @@ export interface IPlayer extends IPerson {
|
|||||||
quitJob(company: string, sing?: boolean): void;
|
quitJob(company: string, sing?: boolean): void;
|
||||||
hasJob(): boolean;
|
hasJob(): boolean;
|
||||||
createHacknetServer(): HacknetServer;
|
createHacknetServer(): HacknetServer;
|
||||||
startCreateProgramWork(programName: string, time: number, reqLevel: number): void;
|
|
||||||
queueAugmentation(augmentationName: string): void;
|
queueAugmentation(augmentationName: string): void;
|
||||||
receiveInvite(factionName: string): void;
|
receiveInvite(factionName: string): void;
|
||||||
updateSkillLevels(): void;
|
updateSkillLevels(): void;
|
||||||
@ -237,7 +231,6 @@ export interface IPlayer extends IPerson {
|
|||||||
finishWork(cancelled: boolean, sing?: boolean): string;
|
finishWork(cancelled: boolean, sing?: boolean): string;
|
||||||
cancelationPenalty(): number;
|
cancelationPenalty(): number;
|
||||||
finishWorkPartTime(sing?: boolean): string;
|
finishWorkPartTime(sing?: boolean): string;
|
||||||
finishCreateProgramWork(cancelled: boolean): string;
|
|
||||||
resetMultipliers(): void;
|
resetMultipliers(): void;
|
||||||
prestigeAugmentation(): void;
|
prestigeAugmentation(): void;
|
||||||
prestigeSourceFile(): void;
|
prestigeSourceFile(): void;
|
||||||
@ -253,15 +246,11 @@ export interface IPlayer extends IPerson {
|
|||||||
getWorkMoneyGain(): number;
|
getWorkMoneyGain(): number;
|
||||||
processWorkEarnings(cycles: number): void;
|
processWorkEarnings(cycles: number): void;
|
||||||
hospitalize(): void;
|
hospitalize(): void;
|
||||||
createProgramWork(numCycles: number): boolean;
|
|
||||||
checkForFactionInvitations(): Faction[];
|
checkForFactionInvitations(): Faction[];
|
||||||
setBitNodeNumber(n: number): void;
|
setBitNodeNumber(n: number): void;
|
||||||
getMult(name: string): number;
|
getMult(name: string): number;
|
||||||
setMult(name: string, mult: number): void;
|
setMult(name: string, mult: number): void;
|
||||||
canAccessCotMG(): boolean;
|
canAccessCotMG(): boolean;
|
||||||
sourceFileLvl(n: number): number;
|
sourceFileLvl(n: number): number;
|
||||||
startGraftAugmentationWork(augmentationName: string, time: number): void;
|
|
||||||
graftAugmentationWork(numCycles: number): boolean;
|
|
||||||
finishGraftAugmentationWork(cancelled: boolean, singularity?: boolean): string;
|
|
||||||
applyEntropy(stacks?: number): void;
|
applyEntropy(stacks?: number): void;
|
||||||
}
|
}
|
||||||
|
@ -138,12 +138,7 @@ export class PlayerObject implements IPlayer {
|
|||||||
bladeburner_success_chance_mult: number;
|
bladeburner_success_chance_mult: number;
|
||||||
|
|
||||||
currentWork: Work | null;
|
currentWork: Work | null;
|
||||||
createProgramReqLvl: number;
|
|
||||||
factionWorkType: PlayerFactionWorkType;
|
factionWorkType: PlayerFactionWorkType;
|
||||||
createProgramName: string;
|
|
||||||
timeWorkedCreateProgram: number;
|
|
||||||
graftAugmentationName: string;
|
|
||||||
timeWorkedGraftAugmentation: number;
|
|
||||||
timeNeededToCompleteWork: number;
|
timeNeededToCompleteWork: number;
|
||||||
focus: boolean;
|
focus: boolean;
|
||||||
currentWorkFactionName: string;
|
currentWorkFactionName: string;
|
||||||
@ -252,7 +247,6 @@ export class PlayerObject implements IPlayer {
|
|||||||
hasJob: () => boolean;
|
hasJob: () => boolean;
|
||||||
process: (router: IRouter, numCycles?: number) => void;
|
process: (router: IRouter, numCycles?: number) => void;
|
||||||
createHacknetServer: () => HacknetServer;
|
createHacknetServer: () => HacknetServer;
|
||||||
startCreateProgramWork: (programName: string, time: number, reqLevel: number) => void;
|
|
||||||
queueAugmentation: (augmentationName: string) => void;
|
queueAugmentation: (augmentationName: string) => void;
|
||||||
receiveInvite: (factionName: string) => void;
|
receiveInvite: (factionName: string) => void;
|
||||||
updateSkillLevels: () => void;
|
updateSkillLevels: () => void;
|
||||||
@ -262,7 +256,6 @@ export class PlayerObject implements IPlayer {
|
|||||||
finishWork: (cancelled: boolean, sing?: boolean) => string;
|
finishWork: (cancelled: boolean, sing?: boolean) => string;
|
||||||
cancelationPenalty: () => number;
|
cancelationPenalty: () => number;
|
||||||
finishWorkPartTime: (sing?: boolean) => string;
|
finishWorkPartTime: (sing?: boolean) => string;
|
||||||
finishCreateProgramWork: (cancelled: boolean) => string;
|
|
||||||
resetMultipliers: () => void;
|
resetMultipliers: () => void;
|
||||||
prestigeAugmentation: () => void;
|
prestigeAugmentation: () => void;
|
||||||
prestigeSourceFile: () => void;
|
prestigeSourceFile: () => void;
|
||||||
@ -279,16 +272,12 @@ export class PlayerObject implements IPlayer {
|
|||||||
getWorkMoneyGain: () => number;
|
getWorkMoneyGain: () => number;
|
||||||
processWorkEarnings: (cycles: number) => void;
|
processWorkEarnings: (cycles: number) => void;
|
||||||
hospitalize: () => void;
|
hospitalize: () => void;
|
||||||
createProgramWork: (numCycles: number) => boolean;
|
|
||||||
checkForFactionInvitations: () => Faction[];
|
checkForFactionInvitations: () => Faction[];
|
||||||
setBitNodeNumber: (n: number) => void;
|
setBitNodeNumber: (n: number) => void;
|
||||||
getMult: (name: string) => number;
|
getMult: (name: string) => number;
|
||||||
setMult: (name: string, mult: number) => void;
|
setMult: (name: string, mult: number) => void;
|
||||||
canAccessCotMG: () => boolean;
|
canAccessCotMG: () => boolean;
|
||||||
sourceFileLvl: (n: number) => number;
|
sourceFileLvl: (n: number) => number;
|
||||||
startGraftAugmentationWork: (augmentationName: string, time: number) => void;
|
|
||||||
graftAugmentationWork: (numCycles: number) => boolean;
|
|
||||||
finishGraftAugmentationWork: (cancelled: boolean, singularity?: boolean) => string;
|
|
||||||
applyEntropy: (stacks?: number) => void;
|
applyEntropy: (stacks?: number) => void;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
@ -410,14 +399,7 @@ export class PlayerObject implements IPlayer {
|
|||||||
this.workRepGained = 0;
|
this.workRepGained = 0;
|
||||||
this.workMoneyGained = 0;
|
this.workMoneyGained = 0;
|
||||||
|
|
||||||
this.createProgramName = "";
|
|
||||||
this.createProgramReqLvl = 0;
|
|
||||||
|
|
||||||
this.graftAugmentationName = "";
|
|
||||||
this.timeWorkedGraftAugmentation = 0;
|
|
||||||
|
|
||||||
this.timeWorked = 0; //in m;
|
this.timeWorked = 0; //in m;
|
||||||
this.timeWorkedCreateProgram = 0;
|
|
||||||
this.timeNeededToCompleteWork = 0;
|
this.timeNeededToCompleteWork = 0;
|
||||||
|
|
||||||
this.work_money_mult = 1;
|
this.work_money_mult = 1;
|
||||||
@ -538,12 +520,6 @@ export class PlayerObject implements IPlayer {
|
|||||||
this.getWorkChaExpGain = generalMethods.getWorkChaExpGain;
|
this.getWorkChaExpGain = generalMethods.getWorkChaExpGain;
|
||||||
this.getWorkRepGain = generalMethods.getWorkRepGain;
|
this.getWorkRepGain = generalMethods.getWorkRepGain;
|
||||||
this.process = generalMethods.process;
|
this.process = generalMethods.process;
|
||||||
this.startCreateProgramWork = generalMethods.startCreateProgramWork;
|
|
||||||
this.createProgramWork = generalMethods.createProgramWork;
|
|
||||||
this.finishCreateProgramWork = generalMethods.finishCreateProgramWork;
|
|
||||||
this.startGraftAugmentationWork = generalMethods.startGraftAugmentationWork;
|
|
||||||
this.graftAugmentationWork = generalMethods.craftAugmentationWork;
|
|
||||||
this.finishGraftAugmentationWork = generalMethods.finishGraftAugmentationWork;
|
|
||||||
this.singularityStopWork = generalMethods.singularityStopWork;
|
this.singularityStopWork = generalMethods.singularityStopWork;
|
||||||
this.takeDamage = generalMethods.takeDamage;
|
this.takeDamage = generalMethods.takeDamage;
|
||||||
this.regenerateHp = generalMethods.regenerateHp;
|
this.regenerateHp = generalMethods.regenerateHp;
|
||||||
|
@ -66,9 +66,8 @@ import { FactionNames } from "../../Faction/data/FactionNames";
|
|||||||
import { ITaskTracker } from "../ITaskTracker";
|
import { ITaskTracker } from "../ITaskTracker";
|
||||||
import { IPerson } from "../IPerson";
|
import { IPerson } from "../IPerson";
|
||||||
import { Player } from "../../Player";
|
import { Player } from "../../Player";
|
||||||
import { graftingIntBonus } from "../Grafting/GraftingHelpers";
|
|
||||||
|
|
||||||
import { WorkType, PlayerFactionWorkType, ClassType, CrimeType } from "../../utils/WorkType";
|
import { WorkType, PlayerFactionWorkType } from "../../utils/WorkType";
|
||||||
|
|
||||||
export function init(this: IPlayer): void {
|
export function init(this: IPlayer): void {
|
||||||
/* Initialize Player's home computer */
|
/* Initialize Player's home computer */
|
||||||
@ -143,7 +142,6 @@ export function prestigeAugmentation(this: PlayerObject): void {
|
|||||||
this.isWorking = false;
|
this.isWorking = false;
|
||||||
this.currentWorkFactionName = "";
|
this.currentWorkFactionName = "";
|
||||||
this.currentWorkFactionDescription = "";
|
this.currentWorkFactionDescription = "";
|
||||||
this.createProgramName = "";
|
|
||||||
|
|
||||||
this.workHackExpGainRate = 0;
|
this.workHackExpGainRate = 0;
|
||||||
this.workStrExpGainRate = 0;
|
this.workStrExpGainRate = 0;
|
||||||
@ -537,13 +535,9 @@ export function resetWorkStatus(this: IPlayer, generalType?: WorkType, group?: s
|
|||||||
this.workMoneyGained = 0;
|
this.workMoneyGained = 0;
|
||||||
|
|
||||||
this.timeWorked = 0;
|
this.timeWorked = 0;
|
||||||
this.timeWorkedCreateProgram = 0;
|
|
||||||
this.timeWorkedGraftAugmentation = 0;
|
|
||||||
|
|
||||||
this.currentWorkFactionName = "";
|
this.currentWorkFactionName = "";
|
||||||
this.currentWorkFactionDescription = "";
|
this.currentWorkFactionDescription = "";
|
||||||
this.createProgramName = "";
|
|
||||||
this.graftAugmentationName = "";
|
|
||||||
this.workType = WorkType.None;
|
this.workType = WorkType.None;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -603,18 +597,10 @@ export function process(this: IPlayer, router: IRouter, numCycles = 1): void {
|
|||||||
if (this.workForFaction(numCycles)) {
|
if (this.workForFaction(numCycles)) {
|
||||||
router.toFaction(Factions[this.currentWorkFactionName]);
|
router.toFaction(Factions[this.currentWorkFactionName]);
|
||||||
}
|
}
|
||||||
} else if (this.workType === WorkType.CreateProgram) {
|
|
||||||
if (this.createProgramWork(numCycles)) {
|
|
||||||
router.toTerminal();
|
|
||||||
}
|
|
||||||
} else if (this.workType === WorkType.CompanyPartTime) {
|
} else if (this.workType === WorkType.CompanyPartTime) {
|
||||||
if (this.workPartTime(numCycles)) {
|
if (this.workPartTime(numCycles)) {
|
||||||
router.toCity();
|
router.toCity();
|
||||||
}
|
}
|
||||||
} else if (this.workType === WorkType.GraftAugmentation) {
|
|
||||||
if (this.graftAugmentationWork(numCycles)) {
|
|
||||||
router.toGrafting();
|
|
||||||
}
|
|
||||||
} else if (this.work(numCycles)) {
|
} else if (this.work(numCycles)) {
|
||||||
router.toCity();
|
router.toCity();
|
||||||
}
|
}
|
||||||
@ -1257,143 +1243,6 @@ export function getWorkRepGain(this: IPlayer): number {
|
|||||||
// return t * this.faction_rep_mult;
|
// return t * this.faction_rep_mult;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
/* Creating a Program */
|
|
||||||
export function startCreateProgramWork(this: IPlayer, programName: string, time: number, reqLevel: number): void {
|
|
||||||
this.resetWorkStatus();
|
|
||||||
this.isWorking = true;
|
|
||||||
this.workType = WorkType.CreateProgram;
|
|
||||||
|
|
||||||
//Time needed to complete work affected by hacking skill (linearly based on
|
|
||||||
//ratio of (your skill - required level) to MAX skill)
|
|
||||||
//var timeMultiplier = (CONSTANTS.MaxSkillLevel - (this.hacking - reqLevel)) / CONSTANTS.MaxSkillLevel;
|
|
||||||
//if (timeMultiplier > 1) {timeMultiplier = 1;}
|
|
||||||
//if (timeMultiplier < 0.01) {timeMultiplier = 0.01;}
|
|
||||||
this.createProgramReqLvl = reqLevel;
|
|
||||||
|
|
||||||
this.timeNeededToCompleteWork = time;
|
|
||||||
//Check for incomplete program
|
|
||||||
for (let i = 0; i < this.getHomeComputer().programs.length; ++i) {
|
|
||||||
const programFile = this.getHomeComputer().programs[i];
|
|
||||||
if (programFile.startsWith(programName) && programFile.endsWith("%-INC")) {
|
|
||||||
const res = programFile.split("-");
|
|
||||||
if (res.length != 3) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
const percComplete = Number(res[1].slice(0, -1));
|
|
||||||
if (isNaN(percComplete) || percComplete < 0 || percComplete >= 100) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
this.timeWorkedCreateProgram = (percComplete / 100) * this.timeNeededToCompleteWork;
|
|
||||||
this.getHomeComputer().programs.splice(i, 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this.createProgramName = programName;
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
if (this.timeWorkedCreateProgram >= this.timeNeededToCompleteWork) {
|
|
||||||
this.finishCreateProgramWork(false);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function finishCreateProgramWork(this: IPlayer, cancelled: boolean): string {
|
|
||||||
const programName = this.createProgramName;
|
|
||||||
let message = "";
|
|
||||||
if (!cancelled) {
|
|
||||||
//Complete case
|
|
||||||
this.gainIntelligenceExp((CONSTANTS.IntelligenceProgramBaseExpGain * this.timeWorked) / 1000);
|
|
||||||
const lines = [`You've finished creating ${programName}!`, "The new program can be found on your home computer."];
|
|
||||||
dialogBoxCreate(lines.join("<br>"));
|
|
||||||
message = lines.join(" ");
|
|
||||||
|
|
||||||
if (!this.getHomeComputer().programs.includes(programName)) {
|
|
||||||
this.getHomeComputer().programs.push(programName);
|
|
||||||
}
|
|
||||||
} else if (!this.getHomeComputer().programs.includes(programName)) {
|
|
||||||
//Incomplete case
|
|
||||||
const perc = (Math.floor((this.timeWorkedCreateProgram / this.timeNeededToCompleteWork) * 10000) / 100).toString();
|
|
||||||
const incompleteName = programName + "-" + perc + "%-INC";
|
|
||||||
this.getHomeComputer().programs.push(incompleteName);
|
|
||||||
message = `Cancelled creating program: ${programName} (${perc}% complete)`;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.isWorking = false;
|
|
||||||
this.resetWorkStatus();
|
|
||||||
return message;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function startGraftAugmentationWork(this: IPlayer, augmentationName: string, time: number): void {
|
|
||||||
this.resetWorkStatus();
|
|
||||||
this.isWorking = true;
|
|
||||||
this.workType = WorkType.GraftAugmentation;
|
|
||||||
|
|
||||||
this.timeNeededToCompleteWork = time;
|
|
||||||
this.graftAugmentationName = augmentationName;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function craftAugmentationWork(this: IPlayer, numCycles: number): boolean {
|
|
||||||
let focusBonus = 1;
|
|
||||||
if (!this.hasAugmentation(AugmentationNames.NeuroreceptorManager)) {
|
|
||||||
focusBonus = this.focus ? 1 : CONSTANTS.BaseFocusBonus;
|
|
||||||
}
|
|
||||||
|
|
||||||
let skillMult = graftingIntBonus(this);
|
|
||||||
skillMult *= focusBonus;
|
|
||||||
|
|
||||||
this.timeWorked += CONSTANTS._idleSpeed * numCycles;
|
|
||||||
this.timeWorkedGraftAugmentation += CONSTANTS._idleSpeed * numCycles * skillMult;
|
|
||||||
|
|
||||||
if (this.timeWorkedGraftAugmentation >= this.timeNeededToCompleteWork) {
|
|
||||||
this.finishGraftAugmentationWork(false);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function finishGraftAugmentationWork(this: IPlayer, cancelled: boolean, singularity = false): string {
|
|
||||||
const augName = this.graftAugmentationName;
|
|
||||||
if (cancelled === false) {
|
|
||||||
applyAugmentation({ name: augName, level: 1 });
|
|
||||||
|
|
||||||
if (!this.hasAugmentation(AugmentationNames.CongruityImplant)) {
|
|
||||||
this.entropy += 1;
|
|
||||||
this.applyEntropy(this.entropy);
|
|
||||||
}
|
|
||||||
|
|
||||||
dialogBoxCreate(
|
|
||||||
`You've finished grafting ${augName}.<br>The augmentation has been applied to your body` +
|
|
||||||
(this.hasAugmentation(AugmentationNames.CongruityImplant) ? "." : ", but you feel a bit off."),
|
|
||||||
);
|
|
||||||
} else if (cancelled && singularity === false) {
|
|
||||||
dialogBoxCreate(`You cancelled the grafting of ${augName}.<br>Your money was not returned to you.`);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Intelligence gain
|
|
||||||
if (!cancelled) {
|
|
||||||
this.gainIntelligenceExp((CONSTANTS.IntelligenceGraftBaseExpGain * this.timeWorked) / 10000);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.isWorking = false;
|
|
||||||
this.resetWorkStatus();
|
|
||||||
return `Grafting of ${augName} has ended.`;
|
|
||||||
}
|
|
||||||
|
|
||||||
//Cancels the player's current "work" assignment and gives the proper rewards
|
//Cancels the player's current "work" assignment and gives the proper rewards
|
||||||
//Used only for Singularity functions, so no popups are created
|
//Used only for Singularity functions, so no popups are created
|
||||||
export function singularityStopWork(this: IPlayer): string {
|
export function singularityStopWork(this: IPlayer): string {
|
||||||
@ -1414,12 +1263,6 @@ export function singularityStopWork(this: IPlayer): string {
|
|||||||
case WorkType.Faction:
|
case WorkType.Faction:
|
||||||
res = this.finishFactionWork(true, true);
|
res = this.finishFactionWork(true, true);
|
||||||
break;
|
break;
|
||||||
case WorkType.CreateProgram:
|
|
||||||
res = this.finishCreateProgramWork(true);
|
|
||||||
break;
|
|
||||||
case WorkType.GraftAugmentation:
|
|
||||||
res = this.finishGraftAugmentationWork(true, true);
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
console.error(`Unrecognized work type (${this.workType})`);
|
console.error(`Unrecognized work type (${this.workType})`);
|
||||||
return "";
|
return "";
|
||||||
|
@ -8,6 +8,7 @@ import { use } from "../../ui/Context";
|
|||||||
import { Settings } from "../../Settings/Settings";
|
import { Settings } from "../../Settings/Settings";
|
||||||
|
|
||||||
import { Programs } from "../Programs";
|
import { Programs } from "../Programs";
|
||||||
|
import { CreateProgramWork } from "../../Work/CreateProgramWork";
|
||||||
|
|
||||||
export const ProgramsSeen: string[] = [];
|
export const ProgramsSeen: string[] = [];
|
||||||
|
|
||||||
@ -96,7 +97,9 @@ export function ProgramsRoot(): React.ReactElement {
|
|||||||
sx={{ my: 1, width: "100%" }}
|
sx={{ my: 1, width: "100%" }}
|
||||||
onClick={(event) => {
|
onClick={(event) => {
|
||||||
if (!event.isTrusted) return;
|
if (!event.isTrusted) return;
|
||||||
player.startCreateProgramWork(program.name, create.time, create.level);
|
player.startNEWWork(
|
||||||
|
new CreateProgramWork({ player: player, singularity: false, programName: program.name }),
|
||||||
|
);
|
||||||
player.startFocusing();
|
player.startFocusing();
|
||||||
router.toWork();
|
router.toWork();
|
||||||
}}
|
}}
|
||||||
|
@ -199,7 +199,7 @@ class BitburnerSaveObject {
|
|||||||
try {
|
try {
|
||||||
parsedSave = JSON.parse(newSave);
|
parsedSave = JSON.parse(newSave);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(error); // We'll handle below
|
console.error(error); // We'll handle below
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!parsedSave || parsedSave.ctor !== "BitburnerSaveObject" || !parsedSave.data) {
|
if (!parsedSave || parsedSave.ctor !== "BitburnerSaveObject" || !parsedSave.data) {
|
||||||
|
2
src/ScriptEditor/NetscriptDefinitions.d.ts
vendored
2
src/ScriptEditor/NetscriptDefinitions.d.ts
vendored
@ -68,8 +68,6 @@ interface Player {
|
|||||||
workChaExpGained: number;
|
workChaExpGained: number;
|
||||||
workRepGained: number;
|
workRepGained: number;
|
||||||
workMoneyGained: number;
|
workMoneyGained: number;
|
||||||
createProgramName: string;
|
|
||||||
createProgramReqLvl: number;
|
|
||||||
work_money_mult: number;
|
work_money_mult: number;
|
||||||
hacknet_node_money_mult: number;
|
hacknet_node_money_mult: number;
|
||||||
hacknet_node_purchase_cost_mult: number;
|
hacknet_node_purchase_cost_mult: number;
|
||||||
|
@ -46,7 +46,6 @@ export function GetServer(s: string): BaseServer | null {
|
|||||||
const server = AllServers[s];
|
const server = AllServers[s];
|
||||||
if (server) return server;
|
if (server) return server;
|
||||||
}
|
}
|
||||||
console.log(AllServers);
|
|
||||||
|
|
||||||
if (!isValidIPAddress(s)) {
|
if (!isValidIPAddress(s)) {
|
||||||
return GetServerByHostname(s);
|
return GetServerByHostname(s);
|
||||||
|
@ -126,8 +126,6 @@ interface ClassWorkParams {
|
|||||||
export const isClassWork = (w: Work | null): w is ClassWork => w !== null && w.type === WorkType.CLASS;
|
export const isClassWork = (w: Work | null): w is ClassWork => w !== null && w.type === WorkType.CLASS;
|
||||||
|
|
||||||
export class ClassWork extends Work {
|
export class ClassWork extends Work {
|
||||||
type = WorkType.CLASS;
|
|
||||||
|
|
||||||
classType: ClassType;
|
classType: ClassType;
|
||||||
location: LocationName;
|
location: LocationName;
|
||||||
cyclesWorked: number;
|
cyclesWorked: number;
|
||||||
@ -135,7 +133,7 @@ export class ClassWork extends Work {
|
|||||||
earnings = newWorkStats();
|
earnings = newWorkStats();
|
||||||
|
|
||||||
constructor(params?: ClassWorkParams) {
|
constructor(params?: ClassWorkParams) {
|
||||||
super();
|
super(WorkType.CLASS);
|
||||||
this.classType = params?.classType ?? ClassType.StudyComputerScience;
|
this.classType = params?.classType ?? ClassType.StudyComputerScience;
|
||||||
this.location = params?.location ?? LocationName.Sector12RothmanUniversity;
|
this.location = params?.location ?? LocationName.Sector12RothmanUniversity;
|
||||||
this.singularity = params?.singularity ?? false;
|
this.singularity = params?.singularity ?? false;
|
||||||
|
125
src/Work/CreateProgramWork.ts
Normal file
125
src/Work/CreateProgramWork.ts
Normal file
@ -0,0 +1,125 @@
|
|||||||
|
import { dialogBoxCreate } from "../ui/React/DialogBox";
|
||||||
|
import { Reviver, Generic_toJSON, Generic_fromJSON } from "../utils/JSONReviver";
|
||||||
|
import { AugmentationNames } from "../Augmentation/data/AugmentationNames";
|
||||||
|
import { CONSTANTS } from "../Constants";
|
||||||
|
import { IPlayer } from "../PersonObjects/IPlayer";
|
||||||
|
import { Programs } from "../Programs/Programs";
|
||||||
|
import { Work, WorkType } from "./Work";
|
||||||
|
import { Program } from "../Programs/Program";
|
||||||
|
|
||||||
|
export const isCreateProgramWork = (w: Work | null): w is CreateProgramWork =>
|
||||||
|
w !== null && w.type === WorkType.CREATE_PROGRAM;
|
||||||
|
|
||||||
|
interface CreateProgramWorkParams {
|
||||||
|
programName: string;
|
||||||
|
singularity: boolean;
|
||||||
|
player: IPlayer;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class CreateProgramWork extends Work {
|
||||||
|
programName: string;
|
||||||
|
// amount of cycles spent doing this task
|
||||||
|
cyclesWorked: number;
|
||||||
|
singularity: boolean;
|
||||||
|
// amount of effective work completed on the program (time boosted by skills).
|
||||||
|
unitCompleted: number;
|
||||||
|
|
||||||
|
constructor(params?: CreateProgramWorkParams) {
|
||||||
|
super(WorkType.CREATE_PROGRAM);
|
||||||
|
this.cyclesWorked = 0;
|
||||||
|
this.unitCompleted = 0;
|
||||||
|
this.programName = params?.programName ?? "";
|
||||||
|
this.singularity = params?.singularity ?? false;
|
||||||
|
|
||||||
|
if (params?.player) {
|
||||||
|
const player = params.player;
|
||||||
|
for (let i = 0; i < player.getHomeComputer().programs.length; ++i) {
|
||||||
|
const programFile = player.getHomeComputer().programs[i];
|
||||||
|
if (programFile.startsWith(this.programName) && programFile.endsWith("%-INC")) {
|
||||||
|
const res = programFile.split("-");
|
||||||
|
if (res.length != 3) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
const percComplete = Number(res[1].slice(0, -1));
|
||||||
|
if (isNaN(percComplete) || percComplete < 0 || percComplete >= 100) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
this.unitCompleted = (percComplete / 100) * this.unitNeeded();
|
||||||
|
player.getHomeComputer().programs.splice(i, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unitNeeded(): number {
|
||||||
|
return this.getProgram().create?.time ?? 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
getProgram(): Program {
|
||||||
|
const p = Object.values(Programs).find((p) => p.name.toLowerCase() === this.programName.toLowerCase());
|
||||||
|
if (!p) throw new Error("Create program work started with invalid program " + this.programName);
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
process(player: IPlayer, cycles: number): boolean {
|
||||||
|
let focusBonus = 1;
|
||||||
|
if (!player.hasAugmentation(AugmentationNames["NeuroreceptorManager"])) {
|
||||||
|
focusBonus = player.focus ? 1 : CONSTANTS.BaseFocusBonus;
|
||||||
|
}
|
||||||
|
//Higher hacking skill will allow you to create programs faster
|
||||||
|
const reqLvl = this.getProgram().create?.level ?? 0;
|
||||||
|
let skillMult = (player.hacking / reqLvl) * player.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.cyclesWorked += cycles;
|
||||||
|
this.unitCompleted += CONSTANTS._idleSpeed * cycles * skillMult;
|
||||||
|
|
||||||
|
if (this.unitCompleted >= this.unitNeeded()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
finish(player: IPlayer, cancelled: boolean): void {
|
||||||
|
const programName = this.programName;
|
||||||
|
if (!cancelled) {
|
||||||
|
//Complete case
|
||||||
|
player.gainIntelligenceExp(
|
||||||
|
(CONSTANTS.IntelligenceProgramBaseExpGain * this.cyclesWorked * CONSTANTS._idleSpeed) / 1000,
|
||||||
|
);
|
||||||
|
if (!this.singularity) {
|
||||||
|
const lines = [
|
||||||
|
`You've finished creating ${programName}!`,
|
||||||
|
"The new program can be found on your home computer.",
|
||||||
|
];
|
||||||
|
dialogBoxCreate(lines.join("<br>"));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!player.getHomeComputer().programs.includes(programName)) {
|
||||||
|
player.getHomeComputer().programs.push(programName);
|
||||||
|
}
|
||||||
|
} else if (!player.getHomeComputer().programs.includes(programName)) {
|
||||||
|
//Incomplete case
|
||||||
|
const perc = ((100 * this.unitCompleted) / this.unitNeeded()).toFixed(2);
|
||||||
|
const incompleteName = programName + "-" + perc + "%-INC";
|
||||||
|
player.getHomeComputer().programs.push(incompleteName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Serialize the current object to a JSON save state.
|
||||||
|
*/
|
||||||
|
toJSON(): any {
|
||||||
|
return Generic_toJSON("CreateProgramWork", this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initiatizes a CreateProgramWork object from a JSON save state.
|
||||||
|
*/
|
||||||
|
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
||||||
|
static fromJSON(value: any): CreateProgramWork {
|
||||||
|
return Generic_fromJSON(CreateProgramWork, value.data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Reviver.constructors.CreateProgramWork = CreateProgramWork;
|
@ -19,14 +19,12 @@ interface CrimeWorkParams {
|
|||||||
export const isCrimeWork = (w: Work | null): w is CrimeWork => w !== null && w.type === WorkType.CRIME;
|
export const isCrimeWork = (w: Work | null): w is CrimeWork => w !== null && w.type === WorkType.CRIME;
|
||||||
|
|
||||||
export class CrimeWork extends Work {
|
export class CrimeWork extends Work {
|
||||||
type = WorkType.CRIME;
|
|
||||||
|
|
||||||
crimeType: CrimeType;
|
crimeType: CrimeType;
|
||||||
cyclesWorked: number;
|
cyclesWorked: number;
|
||||||
singularity: boolean;
|
singularity: boolean;
|
||||||
|
|
||||||
constructor(params?: CrimeWorkParams) {
|
constructor(params?: CrimeWorkParams) {
|
||||||
super();
|
super(WorkType.CRIME);
|
||||||
this.crimeType = params?.crimeType ?? CrimeType.Shoplift;
|
this.crimeType = params?.crimeType ?? CrimeType.Shoplift;
|
||||||
this.singularity = params?.singularity ?? false;
|
this.singularity = params?.singularity ?? false;
|
||||||
this.cyclesWorked = 0;
|
this.cyclesWorked = 0;
|
||||||
|
106
src/Work/GraftingWork.tsx
Normal file
106
src/Work/GraftingWork.tsx
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
import React from "react";
|
||||||
|
import { CONSTANTS } from "../Constants";
|
||||||
|
import { AugmentationNames } from "../Augmentation/data/AugmentationNames";
|
||||||
|
import { GraftableAugmentations } from "../PersonObjects/Grafting/ui/GraftingRoot";
|
||||||
|
import { IPlayer } from "../PersonObjects/IPlayer";
|
||||||
|
import { Work, WorkType } from "./Work";
|
||||||
|
import { graftingIntBonus } from "../PersonObjects/Grafting/GraftingHelpers";
|
||||||
|
import { applyAugmentation } from "../Augmentation/AugmentationHelpers";
|
||||||
|
import { dialogBoxCreate } from "../ui/React/DialogBox";
|
||||||
|
import { Reviver, Generic_toJSON, Generic_fromJSON } from "../utils/JSONReviver";
|
||||||
|
import { GraftableAugmentation } from "../PersonObjects/Grafting/GraftableAugmentation";
|
||||||
|
import { StaticAugmentations } from "../Augmentation/StaticAugmentations";
|
||||||
|
|
||||||
|
export const isGraftingWork = (w: Work | null): w is GraftingWork => w !== null && w.type === WorkType.GRAFTING;
|
||||||
|
|
||||||
|
interface GraftingWorkParams {
|
||||||
|
augmentation: string;
|
||||||
|
singularity: boolean;
|
||||||
|
player: IPlayer;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class GraftingWork extends Work {
|
||||||
|
augmentation: string;
|
||||||
|
singularity: boolean;
|
||||||
|
cyclesWorked: number;
|
||||||
|
unitCompleted: number;
|
||||||
|
|
||||||
|
constructor(params?: GraftingWorkParams) {
|
||||||
|
super(WorkType.GRAFTING);
|
||||||
|
this.cyclesWorked = 0;
|
||||||
|
this.unitCompleted = 0;
|
||||||
|
this.augmentation = params?.augmentation ?? AugmentationNames.Targeting1;
|
||||||
|
this.singularity = params?.singularity ?? false;
|
||||||
|
if (params?.player) params.player.loseMoney(GraftableAugmentations[this.augmentation].cost, "augmentations");
|
||||||
|
}
|
||||||
|
|
||||||
|
unitNeeded(): number {
|
||||||
|
return new GraftableAugmentation(StaticAugmentations[this.augmentation]).time;
|
||||||
|
}
|
||||||
|
|
||||||
|
process(player: IPlayer, cycles: number): boolean {
|
||||||
|
let focusBonus = 1;
|
||||||
|
if (!player.hasAugmentation(AugmentationNames.NeuroreceptorManager)) {
|
||||||
|
focusBonus = player.focus ? 1 : CONSTANTS.BaseFocusBonus;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.cyclesWorked += cycles;
|
||||||
|
this.unitCompleted += CONSTANTS._idleSpeed * cycles * graftingIntBonus(player) * focusBonus;
|
||||||
|
|
||||||
|
return this.unitCompleted >= this.unitNeeded();
|
||||||
|
}
|
||||||
|
|
||||||
|
finish(player: IPlayer, cancelled: boolean): void {
|
||||||
|
const augName = this.augmentation;
|
||||||
|
if (!cancelled) {
|
||||||
|
applyAugmentation({ name: augName, level: 1 });
|
||||||
|
|
||||||
|
if (!player.hasAugmentation(AugmentationNames.CongruityImplant)) {
|
||||||
|
player.entropy += 1;
|
||||||
|
player.applyEntropy(player.entropy);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.singularity) {
|
||||||
|
dialogBoxCreate(
|
||||||
|
<>
|
||||||
|
You've finished grafting {augName}.<br />
|
||||||
|
The augmentation has been applied to your body{" "}
|
||||||
|
{player.hasAugmentation(AugmentationNames.CongruityImplant) ? "." : ", but you feel a bit off."}
|
||||||
|
</>,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else if (cancelled && !this.singularity) {
|
||||||
|
dialogBoxCreate(
|
||||||
|
<>
|
||||||
|
You cancelled the grafting of {augName}.
|
||||||
|
<br />
|
||||||
|
Your money was not returned to you.
|
||||||
|
</>,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Intelligence gain
|
||||||
|
if (!cancelled) {
|
||||||
|
player.gainIntelligenceExp(
|
||||||
|
(CONSTANTS.IntelligenceGraftBaseExpGain * this.cyclesWorked * CONSTANTS._idleSpeed) / 10000,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Serialize the current object to a JSON save state.
|
||||||
|
*/
|
||||||
|
toJSON(): any {
|
||||||
|
return Generic_toJSON("GraftingWork", this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initiatizes a GraftingWork object from a JSON save state.
|
||||||
|
*/
|
||||||
|
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
||||||
|
static fromJSON(value: any): GraftingWork {
|
||||||
|
return Generic_fromJSON(GraftingWork, value.data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Reviver.constructors.GraftingWork = GraftingWork;
|
@ -1,13 +1,20 @@
|
|||||||
import { IPlayer } from "src/PersonObjects/IPlayer";
|
import { IPlayer } from "src/PersonObjects/IPlayer";
|
||||||
|
|
||||||
export abstract class Work {
|
export abstract class Work {
|
||||||
abstract type: WorkType;
|
type: WorkType;
|
||||||
|
|
||||||
|
constructor(type: WorkType) {
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
|
||||||
abstract process(player: IPlayer, cycles: number): boolean;
|
abstract process(player: IPlayer, cycles: number): boolean;
|
||||||
abstract finish(player: IPlayer, cancelled: boolean): void;
|
abstract finish(player: IPlayer, cancelled: boolean): void;
|
||||||
|
abstract toJSON(): any;
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum WorkType {
|
export enum WorkType {
|
||||||
CRIME = "CRIME",
|
CRIME = "CRIME",
|
||||||
CLASS = "CLASS",
|
CLASS = "CLASS",
|
||||||
|
CREATE_PROGRAM = "CREATE_PROGRAM",
|
||||||
|
GRAFTING = "GRAFTING",
|
||||||
}
|
}
|
||||||
|
@ -306,15 +306,9 @@ const Engine: {
|
|||||||
case WorkType.Faction:
|
case WorkType.Faction:
|
||||||
Player.workForFaction(numCyclesOffline);
|
Player.workForFaction(numCyclesOffline);
|
||||||
break;
|
break;
|
||||||
case WorkType.CreateProgram:
|
|
||||||
Player.createProgramWork(numCyclesOffline);
|
|
||||||
break;
|
|
||||||
case WorkType.CompanyPartTime:
|
case WorkType.CompanyPartTime:
|
||||||
Player.workPartTime(numCyclesOffline);
|
Player.workPartTime(numCyclesOffline);
|
||||||
break;
|
break;
|
||||||
case WorkType.GraftAugmentation:
|
|
||||||
Player.graftAugmentationWork(numCyclesOffline);
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
Player.work(numCyclesOffline);
|
Player.work(numCyclesOffline);
|
||||||
}
|
}
|
||||||
|
@ -294,7 +294,7 @@ export function GameRoot({ player, engine, terminal }: IProps): React.ReactEleme
|
|||||||
Router[fnName] = _wrap(Router[fnName], (func, ...args) => {
|
Router[fnName] = _wrap(Router[fnName], (func, ...args) => {
|
||||||
if (!allowRoutingCalls) {
|
if (!allowRoutingCalls) {
|
||||||
// Let's just log to console.
|
// Let's just log to console.
|
||||||
console.log(`Routing is currently disabled - Attempted router.${fnName}()`);
|
console.error(`Routing is currently disabled - Attempted router.${fnName}()`);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,7 +24,6 @@ export function AlertManager(): React.ReactElement {
|
|||||||
setAlerts((old) => {
|
setAlerts((old) => {
|
||||||
const hash = getMessageHash(text);
|
const hash = getMessageHash(text);
|
||||||
if (old.some((a) => a.hash === hash)) {
|
if (old.some((a) => a.hash === hash)) {
|
||||||
console.log("Duplicate message");
|
|
||||||
return old;
|
return old;
|
||||||
}
|
}
|
||||||
return [
|
return [
|
||||||
|
@ -29,6 +29,8 @@ import { Box, Tooltip } from "@mui/material";
|
|||||||
import { WorkType } from "../../utils/WorkType";
|
import { WorkType } from "../../utils/WorkType";
|
||||||
import { isClassWork } from "../../Work/ClassWork";
|
import { isClassWork } from "../../Work/ClassWork";
|
||||||
import { CONSTANTS } from "../../Constants";
|
import { CONSTANTS } from "../../Constants";
|
||||||
|
import { isCreateProgramWork } from "../../Work/CreateProgramWork";
|
||||||
|
import { isGraftingWork } from "../../Work/GraftingWork";
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
save: () => void;
|
save: () => void;
|
||||||
@ -150,6 +152,26 @@ function Work(): React.ReactElement {
|
|||||||
header = <>You are {player.currentWork.getClass().youAreCurrently}</>;
|
header = <>You are {player.currentWork.getClass().youAreCurrently}</>;
|
||||||
innerText = <>{convertTimeMsToTimeElapsedString(player.currentWork.cyclesWorked * CONSTANTS._idleSpeed)}</>;
|
innerText = <>{convertTimeMsToTimeElapsedString(player.currentWork.cyclesWorked * CONSTANTS._idleSpeed)}</>;
|
||||||
}
|
}
|
||||||
|
if (isCreateProgramWork(player.currentWork)) {
|
||||||
|
const create = player.currentWork;
|
||||||
|
details = <>Coding {create.programName}</>;
|
||||||
|
header = <>Creating a program</>;
|
||||||
|
innerText = (
|
||||||
|
<>
|
||||||
|
{create.programName} {((create.unitCompleted / create.unitNeeded()) * 100).toFixed(2)}%
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (isGraftingWork(player.currentWork)) {
|
||||||
|
const graft = player.currentWork;
|
||||||
|
details = <>Grafting {graft.augmentation}</>;
|
||||||
|
header = <>Grafting an Augmentation</>;
|
||||||
|
innerText = (
|
||||||
|
<>
|
||||||
|
<strong>{((graft.unitCompleted / graft.unitNeeded()) * 100).toFixed(2)}%</strong> done
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
switch (player.workType) {
|
switch (player.workType) {
|
||||||
case WorkType.CompanyPartTime:
|
case WorkType.CompanyPartTime:
|
||||||
case WorkType.Company:
|
case WorkType.Company:
|
||||||
@ -186,25 +208,6 @@ function Work(): React.ReactElement {
|
|||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
case WorkType.CreateProgram:
|
|
||||||
details = <>Coding {player.createProgramName}</>;
|
|
||||||
header = <>Creating a program</>;
|
|
||||||
innerText = (
|
|
||||||
<>
|
|
||||||
{player.createProgramName}{" "}
|
|
||||||
{((player.timeWorkedCreateProgram / player.timeNeededToCompleteWork) * 100).toFixed(2)}%
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
case WorkType.GraftAugmentation:
|
|
||||||
details = <>Grafting {player.graftAugmentationName}</>;
|
|
||||||
header = <>Grafting an Augmentation</>;
|
|
||||||
innerText = (
|
|
||||||
<>
|
|
||||||
<strong>{((player.timeWorkedGraftAugmentation / player.timeNeededToCompleteWork) * 100).toFixed(2)}%</strong>{" "}
|
|
||||||
done
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -22,7 +22,9 @@ import { StatsRow } from "./React/StatsRow";
|
|||||||
import { WorkType, ClassType } from "../utils/WorkType";
|
import { WorkType, ClassType } from "../utils/WorkType";
|
||||||
import { isCrimeWork } from "../Work/CrimeWork";
|
import { isCrimeWork } from "../Work/CrimeWork";
|
||||||
import { isClassWork } from "../Work/ClassWork";
|
import { isClassWork } from "../Work/ClassWork";
|
||||||
import { WorkStats } from "src/Work/WorkStats";
|
import { WorkStats } from "../Work/WorkStats";
|
||||||
|
import { isCreateProgramWork } from "../Work/CreateProgramWork";
|
||||||
|
import { isGraftingWork } from "../Work/GraftingWork";
|
||||||
|
|
||||||
const CYCLES_PER_SEC = 1000 / CONSTANTS.MilliPerCycle;
|
const CYCLES_PER_SEC = 1000 / CONSTANTS.MilliPerCycle;
|
||||||
|
|
||||||
@ -301,6 +303,76 @@ export function WorkInProgressRoot(): React.ReactElement {
|
|||||||
stopText: stopText,
|
stopText: stopText,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isCreateProgramWork(player.currentWork)) {
|
||||||
|
const create = player.currentWork;
|
||||||
|
function cancel(): void {
|
||||||
|
player.finishNEWWork(true);
|
||||||
|
router.toTerminal();
|
||||||
|
}
|
||||||
|
function unfocus(): void {
|
||||||
|
router.toTerminal();
|
||||||
|
player.stopFocusing();
|
||||||
|
}
|
||||||
|
|
||||||
|
const completion = (create.unitCompleted / create.unitNeeded()) * 100;
|
||||||
|
|
||||||
|
workInfo = {
|
||||||
|
buttons: {
|
||||||
|
cancel: cancel,
|
||||||
|
unfocus: unfocus,
|
||||||
|
},
|
||||||
|
title: (
|
||||||
|
<>
|
||||||
|
You are currently working on coding <b>{create.programName}</b>
|
||||||
|
</>
|
||||||
|
),
|
||||||
|
|
||||||
|
progress: {
|
||||||
|
elapsed: create.cyclesWorked * CONSTANTS._idleSpeed,
|
||||||
|
percentage: completion,
|
||||||
|
},
|
||||||
|
|
||||||
|
stopText: "Stop creating program",
|
||||||
|
stopTooltip: "Your work will be saved and you can return to complete the program later.",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isGraftingWork(player.currentWork)) {
|
||||||
|
const graft = player.currentWork;
|
||||||
|
function cancel(): void {
|
||||||
|
player.finishNEWWork(true);
|
||||||
|
router.toTerminal();
|
||||||
|
}
|
||||||
|
function unfocus(): void {
|
||||||
|
router.toTerminal();
|
||||||
|
player.stopFocusing();
|
||||||
|
}
|
||||||
|
|
||||||
|
workInfo = {
|
||||||
|
buttons: {
|
||||||
|
cancel: cancel,
|
||||||
|
unfocus: unfocus,
|
||||||
|
},
|
||||||
|
title: (
|
||||||
|
<>
|
||||||
|
You are currently working on grafting <b>{graft.augmentation}</b>
|
||||||
|
</>
|
||||||
|
),
|
||||||
|
|
||||||
|
progress: {
|
||||||
|
elapsed: graft.cyclesWorked * CONSTANTS._idleSpeed,
|
||||||
|
percentage: (graft.unitCompleted / graft.unitNeeded()) * 100,
|
||||||
|
},
|
||||||
|
|
||||||
|
stopText: "Stop grafting",
|
||||||
|
stopTooltip: (
|
||||||
|
<>
|
||||||
|
If you cancel, your work will <b>not</b> be saved, and the money you spent will <b>not</b> be returned
|
||||||
|
</>
|
||||||
|
),
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (player.workType) {
|
switch (player.workType) {
|
||||||
@ -509,80 +581,6 @@ export function WorkInProgressRoot(): React.ReactElement {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case WorkType.CreateProgram: {
|
|
||||||
function cancel(): void {
|
|
||||||
player.finishCreateProgramWork(true);
|
|
||||||
router.toTerminal();
|
|
||||||
}
|
|
||||||
function unfocus(): void {
|
|
||||||
router.toTerminal();
|
|
||||||
player.stopFocusing();
|
|
||||||
}
|
|
||||||
|
|
||||||
const completion = (player.timeWorkedCreateProgram / player.timeNeededToCompleteWork) * 100;
|
|
||||||
|
|
||||||
workInfo = {
|
|
||||||
buttons: {
|
|
||||||
cancel: cancel,
|
|
||||||
unfocus: unfocus,
|
|
||||||
},
|
|
||||||
title: (
|
|
||||||
<>
|
|
||||||
You are currently working on coding <b>{player.createProgramName}</b>
|
|
||||||
</>
|
|
||||||
),
|
|
||||||
|
|
||||||
progress: {
|
|
||||||
elapsed: player.timeWorked,
|
|
||||||
percentage: completion,
|
|
||||||
},
|
|
||||||
|
|
||||||
stopText: "Stop creating program",
|
|
||||||
stopTooltip: "Your work will be saved and you can return to complete the program later.",
|
|
||||||
};
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case WorkType.GraftAugmentation: {
|
|
||||||
function cancel(): void {
|
|
||||||
player.finishGraftAugmentationWork(true);
|
|
||||||
router.toTerminal();
|
|
||||||
}
|
|
||||||
function unfocus(): void {
|
|
||||||
router.toTerminal();
|
|
||||||
player.stopFocusing();
|
|
||||||
}
|
|
||||||
|
|
||||||
const completion = (player.timeWorkedGraftAugmentation / player.timeNeededToCompleteWork) * 100;
|
|
||||||
|
|
||||||
workInfo = {
|
|
||||||
buttons: {
|
|
||||||
cancel: cancel,
|
|
||||||
unfocus: unfocus,
|
|
||||||
},
|
|
||||||
title: (
|
|
||||||
<>
|
|
||||||
You are currently working on grafting <b>{player.graftAugmentationName}</b>
|
|
||||||
</>
|
|
||||||
),
|
|
||||||
|
|
||||||
progress: {
|
|
||||||
elapsed: player.timeWorked,
|
|
||||||
percentage: completion,
|
|
||||||
},
|
|
||||||
|
|
||||||
stopText: "Stop grafting",
|
|
||||||
stopTooltip: (
|
|
||||||
<>
|
|
||||||
If you cancel, your work will <b>not</b> be saved, and the money you spent will <b>not</b> be returned
|
|
||||||
</>
|
|
||||||
),
|
|
||||||
};
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
if (player.currentWork === null) {
|
if (player.currentWork === null) {
|
||||||
router.toTerminal();
|
router.toTerminal();
|
||||||
|
Loading…
Reference in New Issue
Block a user