bitburner-src/src/Work/CreateProgramWork.ts

123 lines
4.4 KiB
TypeScript
Raw Normal View History

2022-07-10 07:37:36 +02:00
import { dialogBoxCreate } from "../ui/React/DialogBox";
import { Reviver, Generic_toJSON, Generic_fromJSON, IReviverValue } from "../utils/JSONReviver";
2022-07-10 07:37:36 +02:00
import { AugmentationNames } from "../Augmentation/data/AugmentationNames";
import { CONSTANTS } from "../Constants";
import { Player } from "@player";
2022-07-10 07:37:36 +02:00
import { Programs } from "../Programs/Programs";
import { Work, WorkType } from "./Work";
import { Program } from "../Programs/Program";
NETSCRIPT: ns.sleeve.getSleeve added. getPlayer and getSleeve can both be used for formulas. (#200) * BREAKING CHANGE: Removed getSleeveStats and getSleeveInformation because this info is provided by getSleeve in a more usable form. * BREAKING CHANGE: Removed tor, inBladeburner, and hasCorporation fields from ns.getPlayer. Functionality still exists via added functions ns.hasTorRouter, ns.corporation.hasCorporation, and ns.bladeburner.inBladeburner. * Separated ns definitions for Person, Sleeve, and Player interfaces with both Player and Sleeve just extending Person. Added getSleeve, which provides a Sleeve object similar to getPlayer. * Renamed the sleeve ns layer's interface as sleeve lowercase because of name conflict. todo: May move all the ns layers interface names to lowercase for consistency * Added ns.formulas.work.crimeSuccessChance and reworked to allow both sleeve and player calculations. * Removed internal Person.getIntelligenceBonus function which was just a wrapper for calculateIntelligenceBonus. Any use of the former in formulas creates a conflict where ns-provided Person objects throw an error. * Renamed helpers.player to helpers.person for netscript person validation. Reduced number of fields validated due to Person being a smaller interface. * Fixed bug in bladeburner where Player multipliers and int were being used no matter which person was performing the task * Fixed leak of Player.jobs at ns.getPlayer * Person / Player / Sleeve classes now implement the netscript equivalent interfaces. Netscript helper for person no longer asserts that it's a real Person class member, only that it's a Person interface. Functions that use netscript persons have been changed to expect just a person interface to prevent needing this incorrect type assertion.
2022-11-09 13:26:26 +01:00
import { calculateIntelligenceBonus } from "../PersonObjects/formulas/intelligence";
2022-07-10 07:37:36 +02:00
export const isCreateProgramWork = (w: Work | null): w is CreateProgramWork =>
w !== null && w.type === WorkType.CREATE_PROGRAM;
interface CreateProgramWorkParams {
programName: string;
singularity: boolean;
}
export class CreateProgramWork extends Work {
programName: string;
// amount of effective work completed on the program (time boosted by skills).
unitCompleted: number;
constructor(params?: CreateProgramWorkParams) {
super(WorkType.CREATE_PROGRAM, params?.singularity ?? true);
2022-07-10 07:37:36 +02:00
this.unitCompleted = 0;
this.programName = params?.programName ?? "";
2022-09-06 15:07:12 +02:00
if (params) {
for (let i = 0; i < Player.getHomeComputer().programs.length; ++i) {
const programFile = Player.getHomeComputer().programs[i];
2022-07-10 07:37:36 +02:00
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();
2022-09-06 15:07:12 +02:00
Player.getHomeComputer().programs.splice(i, 1);
2022-07-10 07:37:36 +02:00
}
}
}
}
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;
}
2022-09-06 15:07:12 +02:00
process(cycles: number): boolean {
2022-07-10 07:37:36 +02:00
let focusBonus = 1;
2022-09-06 15:07:12 +02:00
if (!Player.hasAugmentation(AugmentationNames.NeuroreceptorManager, true)) {
focusBonus = Player.focus ? 1 : CONSTANTS.BaseFocusBonus;
2022-07-10 07:37:36 +02:00
}
//Higher hacking skill will allow you to create programs faster
const reqLvl = this.getProgram().create?.level ?? 0;
NETSCRIPT: ns.sleeve.getSleeve added. getPlayer and getSleeve can both be used for formulas. (#200) * BREAKING CHANGE: Removed getSleeveStats and getSleeveInformation because this info is provided by getSleeve in a more usable form. * BREAKING CHANGE: Removed tor, inBladeburner, and hasCorporation fields from ns.getPlayer. Functionality still exists via added functions ns.hasTorRouter, ns.corporation.hasCorporation, and ns.bladeburner.inBladeburner. * Separated ns definitions for Person, Sleeve, and Player interfaces with both Player and Sleeve just extending Person. Added getSleeve, which provides a Sleeve object similar to getPlayer. * Renamed the sleeve ns layer's interface as sleeve lowercase because of name conflict. todo: May move all the ns layers interface names to lowercase for consistency * Added ns.formulas.work.crimeSuccessChance and reworked to allow both sleeve and player calculations. * Removed internal Person.getIntelligenceBonus function which was just a wrapper for calculateIntelligenceBonus. Any use of the former in formulas creates a conflict where ns-provided Person objects throw an error. * Renamed helpers.player to helpers.person for netscript person validation. Reduced number of fields validated due to Person being a smaller interface. * Fixed bug in bladeburner where Player multipliers and int were being used no matter which person was performing the task * Fixed leak of Player.jobs at ns.getPlayer * Person / Player / Sleeve classes now implement the netscript equivalent interfaces. Netscript helper for person no longer asserts that it's a real Person class member, only that it's a Person interface. Functions that use netscript persons have been changed to expect just a person interface to prevent needing this incorrect type assertion.
2022-11-09 13:26:26 +01:00
let skillMult = (Player.skills.hacking / reqLvl) * calculateIntelligenceBonus(Player.skills.intelligence, 3); //This should always be greater than 1;
2022-07-10 07:37:36 +02:00
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;
}
2022-09-06 15:07:12 +02:00
finish(cancelled: boolean): void {
2022-07-10 07:37:36 +02:00
const programName = this.programName;
if (!cancelled) {
//Complete case
2022-09-06 15:07:12 +02:00
Player.gainIntelligenceExp(
2022-07-10 07:37:36 +02:00
(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("\n"));
2022-07-10 07:37:36 +02:00
}
2022-09-06 15:07:12 +02:00
if (!Player.getHomeComputer().programs.includes(programName)) {
Player.getHomeComputer().programs.push(programName);
2022-07-10 07:37:36 +02:00
}
2022-09-06 15:07:12 +02:00
} else if (!Player.getHomeComputer().programs.includes(programName)) {
2022-07-10 07:37:36 +02:00
//Incomplete case
const perc = ((100 * this.unitCompleted) / this.unitNeeded()).toFixed(2);
const incompleteName = programName + "-" + perc + "%-INC";
2022-09-06 15:07:12 +02:00
Player.getHomeComputer().programs.push(incompleteName);
2022-07-10 07:37:36 +02:00
}
}
2022-07-26 21:30:12 +02:00
APICopy(): Record<string, unknown> {
return {
type: this.type,
cyclesWorked: this.cyclesWorked,
programName: this.programName,
};
}
/** Serialize the current object to a JSON save state. */
toJSON(): IReviverValue {
2022-07-10 07:37:36 +02:00
return Generic_toJSON("CreateProgramWork", this);
}
2022-10-09 07:25:31 +02:00
/** Initializes a CreateProgramWork object from a JSON save state. */
static fromJSON(value: IReviverValue): CreateProgramWork {
2022-07-10 07:37:36 +02:00
return Generic_fromJSON(CreateProgramWork, value.data);
}
}
Reviver.constructors.CreateProgramWork = CreateProgramWork;