diff --git a/doc/source/v2.0.0_migration.rst b/doc/source/v2.0.0_migration.rst
index e8bba2d80..97777cfe4 100644
--- a/doc/source/v2.0.0_migration.rst
+++ b/doc/source/v2.0.0_migration.rst
@@ -95,10 +95,10 @@ Singularity
This means calls like 'ns.connect' need to be changed to 'ns.singularity.connect'
-stock.buy and stock.sell
-------------------------
+stock.buy, stock.sell, stock.short
+----------------------------------
- These 2 functions were renamed to stock.buyStock and stock.sellStock because 'buy' and 'sell'
+ These functions were renamed to stock.buyStock, stock.sellStock, and stock.buyShort because 'buy', 'sell', and 'short'
are very common tokens that would trick the ram calculation.
corporation.bribe
diff --git a/src/Bladeburner/Bladeburner.tsx b/src/Bladeburner/Bladeburner.tsx
index 73b6c21b1..2b76fdde2 100644
--- a/src/Bladeburner/Bladeburner.tsx
+++ b/src/Bladeburner/Bladeburner.tsx
@@ -1452,7 +1452,7 @@ export class Bladeburner implements IBladeburner {
}
}
} catch (e: unknown) {
- exceptionAlert(e);
+ exceptionAlert(String(e));
}
break;
}
diff --git a/src/Bladeburner/data/GeneralActions.tsx b/src/Bladeburner/data/GeneralActions.tsx
index 3cc393612..1725b21cf 100644
--- a/src/Bladeburner/data/GeneralActions.tsx
+++ b/src/Bladeburner/data/GeneralActions.tsx
@@ -1,11 +1,13 @@
import React from "react";
+import { newWorkStats, WorkStats } from "../../Work/WorkStats";
-interface IContract {
+interface IGeneral {
desc: JSX.Element;
+ exp: WorkStats;
}
export const GeneralActions: {
- [key: string]: IContract | undefined;
+ [key: string]: IGeneral | undefined;
} = {
Training: {
desc: (
@@ -14,6 +16,12 @@ export const GeneralActions: {
all combat stats and also increases your max stamina.
>
),
+ exp: newWorkStats({
+ strExp: 30,
+ defExp: 30,
+ dexExp: 30,
+ agiExp: 30,
+ }),
},
"Field Analysis": {
@@ -27,6 +35,10 @@ export const GeneralActions: {
Does NOT require stamina.
>
),
+ exp: newWorkStats({
+ hackExp: 20,
+ chaExp: 20,
+ }),
},
Recruitment: {
@@ -38,6 +50,9 @@ export const GeneralActions: {
Does NOT require stamina.
>
),
+ exp: newWorkStats({
+ chaExp: 120,
+ }),
},
Diplomacy: {
@@ -50,6 +65,9 @@ export const GeneralActions: {
Does NOT require stamina.
>
),
+ exp: newWorkStats({
+ chaExp: 120,
+ }),
},
"Hyperbolic Regeneration Chamber": {
@@ -61,6 +79,7 @@ export const GeneralActions: {
>
),
+ exp: newWorkStats(),
},
"Incite Violence": {
desc: (
@@ -69,5 +88,12 @@ export const GeneralActions: {
additional contracts and operations, at the cost of increased Chaos.
>
),
+ exp: newWorkStats({
+ strExp: 10,
+ defExp: 10,
+ dexExp: 10,
+ agiExp: 10,
+ chaExp: 10,
+ }),
},
};
diff --git a/src/Crime/Crimes.ts b/src/Crime/Crimes.ts
index 66d100d62..407eb85ad 100644
--- a/src/Crime/Crimes.ts
+++ b/src/Crime/Crimes.ts
@@ -6,7 +6,7 @@ import { IMap } from "../types";
import { CrimeType } from "../utils/WorkType";
export const Crimes: IMap = {
- Shoplift: new Crime("Shoplift", CrimeType.Shoplift, 2e3, 15e3, 1 / 20, 0.1, {
+ Shoplift: new Crime("Shoplift", CrimeType.SHOPLIFT, 2e3, 15e3, 1 / 20, 0.1, {
dexterity_success_weight: 1,
agility_success_weight: 1,
@@ -14,7 +14,7 @@ export const Crimes: IMap = {
agility_exp: 2,
}),
- RobStore: new Crime("Rob Store", CrimeType.RobStore, 60e3, 400e3, 1 / 5, 0.5, {
+ RobStore: new Crime("Rob Store", CrimeType.ROB_STORE, 60e3, 400e3, 1 / 5, 0.5, {
hacking_exp: 30,
dexterity_exp: 45,
agility_exp: 45,
@@ -26,7 +26,7 @@ export const Crimes: IMap = {
intelligence_exp: 7.5 * CONSTANTS.IntelligenceCrimeBaseExpGain,
}),
- Mug: new Crime("Mug", CrimeType.Mug, 4e3, 36e3, 1 / 5, 0.25, {
+ Mug: new Crime("Mug", CrimeType.MUG, 4e3, 36e3, 1 / 5, 0.25, {
strength_exp: 3,
defense_exp: 3,
dexterity_exp: 3,
@@ -38,7 +38,7 @@ export const Crimes: IMap = {
agility_success_weight: 0.5,
}),
- Larceny: new Crime("Larceny", CrimeType.Larceny, 90e3, 800e3, 1 / 3, 1.5, {
+ Larceny: new Crime("Larceny", CrimeType.LARCENY, 90e3, 800e3, 1 / 3, 1.5, {
hacking_exp: 45,
dexterity_exp: 60,
agility_exp: 60,
@@ -50,7 +50,7 @@ export const Crimes: IMap = {
intelligence_exp: 15 * CONSTANTS.IntelligenceCrimeBaseExpGain,
}),
- DealDrugs: new Crime("Deal Drugs", CrimeType.Drugs, 10e3, 120e3, 1, 0.5, {
+ DealDrugs: new Crime("Deal Drugs", CrimeType.DRUGS, 10e3, 120e3, 1, 0.5, {
dexterity_exp: 5,
agility_exp: 5,
charisma_exp: 10,
@@ -60,7 +60,7 @@ export const Crimes: IMap = {
agility_success_weight: 1,
}),
- BondForgery: new Crime("Bond Forgery", CrimeType.BondForgery, 300e3, 4.5e6, 1 / 2, 0.1, {
+ BondForgery: new Crime("Bond Forgery", CrimeType.BOND_FORGERY, 300e3, 4.5e6, 1 / 2, 0.1, {
hacking_exp: 100,
dexterity_exp: 150,
charisma_exp: 15,
@@ -71,7 +71,7 @@ export const Crimes: IMap = {
intelligence_exp: 60 * CONSTANTS.IntelligenceCrimeBaseExpGain,
}),
- TraffickArms: new Crime("Traffick Arms", CrimeType.TraffickArms, 40e3, 600e3, 2, 1, {
+ TraffickArms: new Crime("Traffick Arms", CrimeType.TRAFFIC_ARMS, 40e3, 600e3, 2, 1, {
strength_exp: 20,
defense_exp: 20,
dexterity_exp: 20,
@@ -85,7 +85,7 @@ export const Crimes: IMap = {
agility_success_weight: 1,
}),
- Homicide: new Crime("Homicide", CrimeType.Homicide, 3e3, 45e3, 1, 3, {
+ Homicide: new Crime("Homicide", CrimeType.HOMICIDE, 3e3, 45e3, 1, 3, {
strength_exp: 2,
defense_exp: 2,
dexterity_exp: 2,
@@ -99,7 +99,7 @@ export const Crimes: IMap = {
kills: 1,
}),
- GrandTheftAuto: new Crime("Grand Theft Auto", CrimeType.GrandTheftAuto, 80e3, 1.6e6, 8, 5, {
+ GrandTheftAuto: new Crime("Grand Theft Auto", CrimeType.GRAND_THEFT_AUTO, 80e3, 1.6e6, 8, 5, {
strength_exp: 20,
defense_exp: 20,
dexterity_exp: 20,
@@ -115,7 +115,7 @@ export const Crimes: IMap = {
intelligence_exp: 16 * CONSTANTS.IntelligenceCrimeBaseExpGain,
}),
- Kidnap: new Crime("Kidnap", CrimeType.Kidnap, 120e3, 3.6e6, 5, 6, {
+ Kidnap: new Crime("Kidnap", CrimeType.KIDNAP, 120e3, 3.6e6, 5, 6, {
strength_exp: 80,
defense_exp: 80,
dexterity_exp: 80,
@@ -130,7 +130,7 @@ export const Crimes: IMap = {
intelligence_exp: 26 * CONSTANTS.IntelligenceCrimeBaseExpGain,
}),
- Assassination: new Crime("Assassination", CrimeType.Assassination, 300e3, 12e6, 8, 10, {
+ Assassination: new Crime("Assassination", CrimeType.ASSASSINATION, 300e3, 12e6, 8, 10, {
strength_exp: 300,
defense_exp: 300,
dexterity_exp: 300,
@@ -145,7 +145,7 @@ export const Crimes: IMap = {
kills: 1,
}),
- Heist: new Crime("Heist", CrimeType.Heist, 600e3, 120e6, 18, 15, {
+ Heist: new Crime("Heist", CrimeType.HEIST, 600e3, 120e6, 18, 15, {
hacking_exp: 450,
strength_exp: 450,
defense_exp: 450,
diff --git a/src/Netscript/RamCostGenerator.ts b/src/Netscript/RamCostGenerator.ts
index aac166b3e..80a854886 100644
--- a/src/Netscript/RamCostGenerator.ts
+++ b/src/Netscript/RamCostGenerator.ts
@@ -136,7 +136,7 @@ const stock = {
getSaleGain: RamCostConstants.ScriptGetStockRamCost,
buyStock: RamCostConstants.ScriptBuySellStockRamCost,
sellStock: RamCostConstants.ScriptBuySellStockRamCost,
- short: RamCostConstants.ScriptBuySellStockRamCost,
+ buyShort: RamCostConstants.ScriptBuySellStockRamCost,
sellShort: RamCostConstants.ScriptBuySellStockRamCost,
placeOrder: RamCostConstants.ScriptBuySellStockRamCost,
cancelOrder: RamCostConstants.ScriptBuySellStockRamCost,
diff --git a/src/NetscriptFunctions/Sleeve.ts b/src/NetscriptFunctions/Sleeve.ts
index a6b88e580..001fb863c 100644
--- a/src/NetscriptFunctions/Sleeve.ts
+++ b/src/NetscriptFunctions/Sleeve.ts
@@ -180,20 +180,14 @@ export function NetscriptSleeve(player: IPlayer): InternalAPI {
},
getTask:
(ctx: NetscriptContext) =>
- (_sleeveNumber: unknown): SleeveTask => {
+ (_sleeveNumber: unknown): SleeveTask | null => {
const sleeveNumber = ctx.helper.number("sleeveNumber", _sleeveNumber);
checkSleeveAPIAccess(ctx);
checkSleeveNumber(ctx, sleeveNumber);
const sl = player.sleeves[sleeveNumber];
- return {
- task: SleeveTaskType[sl.currentTask],
- crime: sl.crimeType,
- location: sl.currentTaskLocation,
- gymStatType: sl.gymStatType,
- factionWorkType: FactionWorkType[sl.factionWorkType],
- className: sl.className,
- };
+ if (sl.currentWork === null) return null;
+ return sl.currentWork.APICopy();
},
getInformation:
(ctx: NetscriptContext) =>
diff --git a/src/NetscriptFunctions/StockMarket.ts b/src/NetscriptFunctions/StockMarket.ts
index 26ab02e37..041450038 100644
--- a/src/NetscriptFunctions/StockMarket.ts
+++ b/src/NetscriptFunctions/StockMarket.ts
@@ -165,7 +165,7 @@ export function NetscriptStockMarket(player: IPlayer, workerScript: WorkerScript
return res ? stock.getBidPrice() : 0;
},
- short:
+ buyShort:
(ctx: NetscriptContext) =>
(_symbol: unknown, _shares: unknown): number => {
const symbol = ctx.helper.string("symbol", _symbol);
diff --git a/src/PersonObjects/Sleeve/Sleeve.ts b/src/PersonObjects/Sleeve/Sleeve.ts
index 0088a7acc..879d8593e 100644
--- a/src/PersonObjects/Sleeve/Sleeve.ts
+++ b/src/PersonObjects/Sleeve/Sleeve.ts
@@ -35,7 +35,7 @@ import { LocationName } from "../../Locations/data/LocationNames";
import { Generic_fromJSON, Generic_toJSON, IReviverValue, Reviver } from "../../utils/JSONReviver";
import { BladeburnerConstants } from "../../Bladeburner/data/Constants";
import { numeralWrapper } from "../../ui/numeralFormat";
-import { capitalizeFirstLetter, capitalizeEachWord } from "../../utils/StringHelperFunctions";
+import { capitalizeFirstLetter } from "../../utils/StringHelperFunctions";
import { FactionWorkType } from "../../Work/data/FactionWorkType";
import { Work } from "./Work/Work";
import { SleeveClassWork } from "./Work/SleeveClassWork";
@@ -44,8 +44,10 @@ import { SleeveSynchroWork } from "./Work/SleeveSynchroWork";
import { SleeveRecoveryWork } from "./Work/SleeveRecoveryWork";
import { SleeveFactionWork } from "./Work/SleeveFactionWork";
import { SleeveCompanyWork } from "./Work/SleeveCompanyWork";
-import { SleeveBladeburnerGeneralWork } from "./Work/SleeveBladeburnerGeneralActionWork";
import { SleeveInfiltrateWork } from "./Work/SleeveInfiltrateWork";
+import { SleeveSupportWork } from "./Work/SleeveSupportWork";
+import { SleeveBladeburnerWork } from "./Work/SleeveBladeburnerWork";
+import { SleeveCrimeWork } from "./Work/SleeveCrimeWork";
export class Sleeve extends Person {
currentWork: Work | null = null;
@@ -166,6 +168,16 @@ export class Sleeve extends Person {
return this.sync / 100;
}
+ startWork(player: IPlayer, w: Work): void {
+ if (this.currentWork) this.currentWork.finish(player);
+ this.currentWork = w;
+ }
+
+ stopWork(player: IPlayer): void {
+ if (this.currentWork) this.currentWork.finish(player);
+ this.currentWork = null;
+ }
+
/**
* Commit crimes
*/
@@ -175,26 +187,13 @@ export class Sleeve extends Person {
return false;
}
- if (this.currentTask !== SleeveTaskType.Idle) {
+ if (this.currentTask !== SleeveTaskType.Idle || this.currentWork === null) {
this.finishTask(p);
} else {
this.resetTaskStatus(p);
}
- this.gainRatesForTask.hack = crime.hacking_exp * this.mults.hacking_exp * BitNodeMultipliers.CrimeExpGain;
- this.gainRatesForTask.str = crime.strength_exp * this.mults.strength_exp * BitNodeMultipliers.CrimeExpGain;
- this.gainRatesForTask.def = crime.defense_exp * this.mults.defense_exp * BitNodeMultipliers.CrimeExpGain;
- this.gainRatesForTask.dex = crime.dexterity_exp * this.mults.dexterity_exp * BitNodeMultipliers.CrimeExpGain;
- this.gainRatesForTask.agi = crime.agility_exp * this.mults.agility_exp * BitNodeMultipliers.CrimeExpGain;
- this.gainRatesForTask.cha = crime.charisma_exp * this.mults.charisma_exp * BitNodeMultipliers.CrimeExpGain;
- this.gainRatesForTask.int = crime.intelligence_exp;
- this.gainRatesForTask.money = crime.money * this.mults.crime_money * BitNodeMultipliers.CrimeMoney;
-
- this.currentTaskLocation = String(this.gainRatesForTask.money);
-
- this.crimeType = crime.name;
- this.currentTaskMaxTime = crime.time;
- this.currentTask = SleeveTaskType.Crime;
+ this.startWork(p, new SleeveCrimeWork(crime.type));
return true;
}
@@ -202,89 +201,7 @@ export class Sleeve extends Person {
* Called to stop the current task
*/
finishTask(p: IPlayer): void {
- this.currentWork = null;
- if (this.currentTask === SleeveTaskType.Crime) {
- // For crimes, all experience and money is gained at the end
- if (this.currentTaskTime >= this.currentTaskMaxTime) {
- const crime: Crime | undefined = Object.values(Crimes).find((crime) => crime.name === this.crimeType);
- if (!crime) {
- console.error(`Invalid data stored in sleeve.crimeType: ${this.crimeType}`);
- this.resetTaskStatus(p);
- return;
- }
- if (Math.random() < crime.successRate(this)) {
- // Success
- const successGainRates: ITaskTracker = createTaskTracker();
-
- const keysForIteration: (keyof ITaskTracker)[] = Object.keys(successGainRates) as (keyof ITaskTracker)[];
- for (let i = 0; i < keysForIteration.length; ++i) {
- const key = keysForIteration[i];
- successGainRates[key] = this.gainRatesForTask[key] * 2;
- }
- this.gainExperience(p, successGainRates);
- this.gainMoney(p, this.gainRatesForTask);
-
- p.karma -= crime.karma * (this.sync / 100);
- } else {
- this.gainExperience(p, this.gainRatesForTask);
- }
-
- // Do not reset task to IDLE
- this.currentTaskTime = 0;
- return;
- }
- } else if (this.currentTask === SleeveTaskType.Bladeburner) {
- if (this.currentTaskMaxTime === 0) {
- this.currentTaskTime = 0;
- return;
- }
- // For bladeburner, all experience and money is gained at the end
- const bb = p.bladeburner;
- if (bb === null) {
- const errorLogText = `bladeburner is null`;
- console.error(`Function: sleeves.finishTask; Message: '${errorLogText}'`);
- this.resetTaskStatus(p);
- return;
- }
-
- if (this.currentTaskTime >= this.currentTaskMaxTime) {
- if (this.bbAction === "Infiltrate synthoids") {
- bb.infiltrateSynthoidCommunities(p);
- this.currentTaskTime = 0;
- return;
- }
- let type: string;
- let name: string;
- if (this.bbAction === "Take on contracts") {
- type = "Contracts";
- name = this.bbContract;
- } else {
- type = "General";
- name = this.bbAction;
- }
-
- const actionIdent = bb.getActionIdFromTypeAndName(type, name);
- if (actionIdent === null) {
- const errorLogText = `Invalid action: type='${type}' name='${name}'`;
- console.error(`Function: sleeves.finishTask; Message: '${errorLogText}'`);
- this.resetTaskStatus(p);
- return;
- }
-
- const action = bb.getActionObject(actionIdent);
- if ((action?.count ?? 0) > 0) {
- const bbRetValue = bb.completeAction(p, this, actionIdent, false);
- if (bbRetValue) {
- this.gainExperience(p, bbRetValue);
- this.gainMoney(p, bbRetValue);
-
- // Do not reset task to IDLE
- this.currentTaskTime = 0;
- return;
- }
- }
- }
- }
+ this.stopWork(p);
this.resetTaskStatus(p);
@@ -557,30 +474,6 @@ export class Sleeve extends Person {
// Shock gradually goes towards 100
this.shock = Math.min(100, this.shock + 0.0001 * cyclesUsed);
- switch (this.currentTask) {
- case SleeveTaskType.Company: {
- this.gainExperience(p, this.gainRatesForTask, cyclesUsed);
- this.gainMoney(p, this.gainRatesForTask, cyclesUsed);
-
- const company: Company = Companies[this.currentTaskLocation];
- if (!(company instanceof Company)) {
- console.error(`Invalid company for Sleeve task: ${this.currentTaskLocation}`);
- break;
- }
-
- company.playerReputation += this.getRepGain(p) * cyclesUsed;
- break;
- }
- }
-
- if (this.currentTaskMaxTime !== 0 && this.currentTaskTime >= this.currentTaskMaxTime) {
- if (this.currentTask === SleeveTaskType.Crime || this.currentTask === SleeveTaskType.Bladeburner) {
- this.finishTask(p);
- } else {
- this.finishTask(p);
- }
- }
-
this.updateStatLevels();
this.storedCycles -= cyclesUsed;
@@ -592,7 +485,7 @@ export class Sleeve extends Person {
* Resets all parameters used to keep information about the current task
*/
resetTaskStatus(p: IPlayer): void {
- this.currentWork = null;
+ this.stopWork(p);
if (this.bbAction == "Support main sleeve") {
p.bladeburner?.sleeveSupport(false);
}
@@ -616,7 +509,7 @@ export class Sleeve extends Person {
} else {
this.resetTaskStatus(p);
}
- this.currentWork = new SleeveRecoveryWork();
+ this.startWork(p, new SleeveRecoveryWork());
return true;
}
@@ -626,7 +519,7 @@ export class Sleeve extends Person {
} else {
this.resetTaskStatus(p);
}
- this.currentWork = new SleeveSynchroWork();
+ this.startWork(p, new SleeveSynchroWork());
return true;
}
@@ -686,10 +579,13 @@ export class Sleeve extends Person {
}
if (!classType) return false;
- this.currentWork = new SleeveClassWork({
- classType: classType,
- location: loc,
- });
+ this.startWork(
+ p,
+ new SleeveClassWork({
+ classType: classType,
+ location: loc,
+ }),
+ );
return true;
}
@@ -747,7 +643,7 @@ export class Sleeve extends Person {
if (company == null) return false;
if (companyPosition == null) return false;
- this.currentWork = new SleeveCompanyWork({ companyName: companyName });
+ this.startWork(p, new SleeveCompanyWork({ companyName: companyName }));
return true;
}
@@ -786,10 +682,13 @@ export class Sleeve extends Person {
return false;
}
- this.currentWork = new SleeveFactionWork({
- factionWorkType: factionWorkType,
- factionName: faction.name,
- });
+ this.startWork(
+ p,
+ new SleeveFactionWork({
+ factionWorkType: factionWorkType,
+ factionName: faction.name,
+ }),
+ );
return true;
}
@@ -856,10 +755,13 @@ export class Sleeve extends Person {
// if stat is still equals its default value, then validation has failed.
if (!classType) return false;
- this.currentWork = new SleeveClassWork({
- classType: classType,
- location: loc,
- });
+ this.startWork(
+ p,
+ new SleeveClassWork({
+ classType: classType,
+ location: loc,
+ }),
+ );
return true;
}
@@ -883,7 +785,7 @@ export class Sleeve extends Person {
this.gainRatesForTask.money = 0;
this.currentTaskLocation = "";
- let time = 0;
+ const time = 0;
this.bbContract = "------";
switch (action) {
@@ -891,7 +793,7 @@ export class Sleeve extends Person {
// time = this.getBladeburnerActionTime(p, "General", action);
// this.gainRatesForTask.hack = 20 * this.mults.hacking_exp;
// this.gainRatesForTask.cha = 20 * this.mults.charisma_exp;
- this.currentWork = new SleeveBladeburnerGeneralWork("Field analysis");
+ this.startWork(p, new SleeveBladeburnerWork({ type: "General", name: "Field Analysis" }));
return true;
case "Recruitment":
// time = this.getBladeburnerActionTime(p, "General", action);
@@ -900,25 +802,26 @@ export class Sleeve extends Person {
// this.currentTaskLocation = `(Success Rate: ${numeralWrapper.formatPercentage(
// this.recruitmentSuccessChance(p),
// )})`;
- this.currentWork = new SleeveBladeburnerGeneralWork("Recruitment");
- break;
+ this.startWork(p, new SleeveBladeburnerWork({ type: "General", name: "Recruitment" }));
+ return true;
case "Diplomacy":
// time = this.getBladeburnerActionTime(p, "General", action);
- this.currentWork = new SleeveBladeburnerGeneralWork("Diplomacy");
- break;
+ this.startWork(p, new SleeveBladeburnerWork({ type: "General", name: "Diplomacy" }));
+ return true;
case "Infiltrate synthoids":
- this.currentWork = new SleeveInfiltrateWork();
- break;
+ this.startWork(p, new SleeveInfiltrateWork());
+ return true;
case "Support main sleeve":
- p.bladeburner?.sleeveSupport(true);
- time = 0;
- break;
+ this.startWork(p, new SleeveSupportWork(p));
+ return true;
case "Take on contracts":
- time = this.getBladeburnerActionTime(p, "Contracts", contract);
- this.contractGainRates(p, "Contracts", contract);
- this.currentTaskLocation = this.contractSuccessChance(p, "Contracts", contract);
- this.bbContract = capitalizeEachWord(contract.toLowerCase());
- break;
+ this.startWork(p, new SleeveBladeburnerWork({ type: "Contracts", name: contract }));
+ return true;
+ // time = this.getBladeburnerActionTime(p, "Contracts", contract);
+ // this.contractGainRates(p, "Contracts", contract);
+ // this.currentTaskLocation = this.contractSuccessChance(p, "Contracts", contract);
+ // this.bbContract = capitalizeEachWord(contract.toLowerCase());
+ // break;
}
this.bbAction = capitalizeFirstLetter(action.toLowerCase());
diff --git a/src/PersonObjects/Sleeve/Work/SleeveBladeburnerGeneralActionWork.ts b/src/PersonObjects/Sleeve/Work/SleeveBladeburnerGeneralActionWork.ts
deleted file mode 100644
index 7297a3455..000000000
--- a/src/PersonObjects/Sleeve/Work/SleeveBladeburnerGeneralActionWork.ts
+++ /dev/null
@@ -1,59 +0,0 @@
-import { IPlayer } from "../../IPlayer";
-import { Generic_fromJSON, Generic_toJSON, IReviverValue, Reviver } from "../../../utils/JSONReviver";
-import { Sleeve } from "../Sleeve";
-import { Work, WorkType } from "./Work";
-import { CONSTANTS } from "../../../Constants";
-
-export const isSleeveBladeburnerGeneralWork = (w: Work | null): w is SleeveBladeburnerGeneralWork =>
- w !== null && w.type === WorkType.BLADEBURNER_GENERAL;
-
-export class SleeveBladeburnerGeneralWork extends Work {
- cyclesWorked = 0;
- action: string;
-
- constructor(action?: string) {
- super(WorkType.BLADEBURNER_GENERAL);
- this.action = action ?? "Field analysis";
- }
-
- cyclesNeeded(player: IPlayer, sleeve: Sleeve): number {
- const ret = player.bladeburner?.getActionTimeNetscriptFn(sleeve, "General", this.action);
- if (!ret || typeof ret === "string") throw new Error(`Error querying ${this.action} time`);
- return ret / CONSTANTS._idleSpeed;
- }
-
- process(player: IPlayer, sleeve: Sleeve, cycles: number): number {
- if (!player.bladeburner) throw new Error("sleeve doing blade work without being a member");
- this.cyclesWorked += cycles;
- while (this.cyclesWorked > this.cyclesNeeded(player, sleeve)) {
- const actionIdent = player.bladeburner.getActionIdFromTypeAndName("General", this.action);
- if (!actionIdent) throw new Error(`Error getting ${this.action} action`);
- player.bladeburner.completeAction(player, sleeve, actionIdent, false);
- this.cyclesWorked -= this.cyclesNeeded(player, sleeve);
- }
- return 0;
- }
-
- APICopy(): Record {
- return {
- type: this.type,
- action: this.action,
- };
- }
-
- /**
- * Serialize the current object to a JSON save state.
- */
- toJSON(): IReviverValue {
- return Generic_toJSON("SleeveBladeburnerGeneralWork", this);
- }
-
- /**
- * Initiatizes a BladeburnerWork object from a JSON save state.
- */
- static fromJSON(value: IReviverValue): SleeveBladeburnerGeneralWork {
- return Generic_fromJSON(SleeveBladeburnerGeneralWork, value.data);
- }
-}
-
-Reviver.constructors.SleeveBladeburnerGeneralWork = SleeveBladeburnerGeneralWork;
diff --git a/src/PersonObjects/Sleeve/Work/SleeveBladeburnerWork.ts b/src/PersonObjects/Sleeve/Work/SleeveBladeburnerWork.ts
new file mode 100644
index 000000000..62b74d908
--- /dev/null
+++ b/src/PersonObjects/Sleeve/Work/SleeveBladeburnerWork.ts
@@ -0,0 +1,75 @@
+import { IPlayer } from "../../IPlayer";
+import { Generic_fromJSON, Generic_toJSON, IReviverValue, Reviver } from "../../../utils/JSONReviver";
+import { Sleeve } from "../Sleeve";
+import { Work, WorkType } from "./Work";
+import { CONSTANTS } from "../../../Constants";
+import { GeneralActions } from "../../../Bladeburner/data/GeneralActions";
+import { applyWorkStatsExp, WorkStats } from "../../../Work/WorkStats";
+import { Contracts } from "src/Bladeburner/data/Contracts";
+
+interface SleeveBladeburnerWorkParams {
+ type: string;
+ name: string;
+}
+
+export const isSleeveBladeburnerWork = (w: Work | null): w is SleeveBladeburnerWork =>
+ w !== null && w.type === WorkType.BLADEBURNER;
+
+export class SleeveBladeburnerWork extends Work {
+ cyclesWorked = 0;
+ actionType: string;
+ actionName: string;
+
+ constructor(params?: SleeveBladeburnerWorkParams) {
+ super(WorkType.BLADEBURNER);
+ this.actionType = params?.type ?? "General";
+ this.actionName = params?.name ?? "Field analysis";
+ }
+
+ cyclesNeeded(player: IPlayer, sleeve: Sleeve): number {
+ const ret = player.bladeburner?.getActionTimeNetscriptFn(sleeve, this.actionType, this.actionName);
+ if (!ret || typeof ret === "string") throw new Error(`Error querying ${this.actionName} time`);
+ return ret / CONSTANTS._idleSpeed;
+ }
+
+ process(player: IPlayer, sleeve: Sleeve, cycles: number): number {
+ if (!player.bladeburner) throw new Error("sleeve doing blade work without being a member");
+ this.cyclesWorked += cycles;
+ while (this.cyclesWorked > this.cyclesNeeded(player, sleeve)) {
+ const actionIdent = player.bladeburner.getActionIdFromTypeAndName(this.actionType, this.actionName);
+ if (!actionIdent) throw new Error(`Error getting ${this.actionName} action`);
+ player.bladeburner.completeAction(player, sleeve, actionIdent, false);
+ let exp: WorkStats | undefined;
+ if (this.actionType === "General") {
+ exp = GeneralActions[this.actionName]?.exp;
+ if (!exp) throw new Error(`Somehow there was no exp for action ${this.actionType} ${this.actionName}`);
+ applyWorkStatsExp(sleeve, exp, 1);
+ }
+ this.cyclesWorked -= this.cyclesNeeded(player, sleeve);
+ }
+ return 0;
+ }
+
+ APICopy(): Record {
+ return {
+ actionType: this.actionType,
+ actionName: this.actionName,
+ };
+ }
+
+ /**
+ * Serialize the current object to a JSON save state.
+ */
+ toJSON(): IReviverValue {
+ return Generic_toJSON("SleeveBladeburnerWork", this);
+ }
+
+ /**
+ * Initiatizes a BladeburnerWork object from a JSON save state.
+ */
+ static fromJSON(value: IReviverValue): SleeveBladeburnerWork {
+ return Generic_fromJSON(SleeveBladeburnerWork, value.data);
+ }
+}
+
+Reviver.constructors.SleeveBladeburnerWork = SleeveBladeburnerWork;
diff --git a/src/PersonObjects/Sleeve/Work/SleeveCrimeWork.ts b/src/PersonObjects/Sleeve/Work/SleeveCrimeWork.ts
new file mode 100644
index 000000000..e86e7ab5d
--- /dev/null
+++ b/src/PersonObjects/Sleeve/Work/SleeveCrimeWork.ts
@@ -0,0 +1,80 @@
+import { IPlayer } from "../../IPlayer";
+import { Generic_fromJSON, Generic_toJSON, IReviverValue, Reviver } from "../../../utils/JSONReviver";
+import { Sleeve } from "../Sleeve";
+import { Work, WorkType } from "./Work";
+import { CrimeType } from "../../../utils/WorkType";
+import { Crimes } from "../../../Crime/Crimes";
+import { Crime } from "../../../Crime/Crime";
+import { applyWorkStats, newWorkStats, scaleWorkStats, WorkStats } from "../../../Work/WorkStats";
+import { CONSTANTS } from "../../../Constants";
+
+export const isSleeveCrimeWork = (w: Work | null): w is SleeveCrimeWork => w !== null && w.type === WorkType.CRIME;
+
+export class SleeveCrimeWork extends Work {
+ crimeType: CrimeType;
+ cyclesWorked = 0;
+ constructor(crimeType?: CrimeType) {
+ super(WorkType.CRIME);
+ this.crimeType = crimeType ?? CrimeType.SHOPLIFT;
+ }
+
+ getCrime(): Crime {
+ const crime = Object.values(Crimes).find((crime) => crime.type === this.crimeType);
+ if (!crime) throw new Error("crime should not be undefined");
+ return crime;
+ }
+
+ getExp(): WorkStats {
+ const crime = this.getCrime();
+ return newWorkStats({
+ money: crime.money,
+ hackExp: crime.hacking_exp,
+ strExp: crime.strength_exp,
+ defExp: crime.defense_exp,
+ dexExp: crime.dexterity_exp,
+ agiExp: crime.agility_exp,
+ chaExp: crime.charisma_exp,
+ intExp: crime.intelligence_exp,
+ });
+ }
+
+ process(player: IPlayer, sleeve: Sleeve, cycles: number): number {
+ this.cyclesWorked += cycles;
+
+ const crime = this.getCrime();
+ const gains = this.getExp();
+ if (this.cyclesWorked >= crime.time / CONSTANTS._idleSpeed) {
+ if (Math.random() < crime.successRate(sleeve)) {
+ applyWorkStats(player, sleeve, gains, 1, "sleeves");
+
+ player.karma -= crime.karma * sleeve.syncBonus();
+ } else {
+ applyWorkStats(player, sleeve, scaleWorkStats(gains, 0.25), 1, "sleeves");
+ }
+ this.cyclesWorked -= crime.time / CONSTANTS._idleSpeed;
+ }
+ return 0;
+ }
+
+ APICopy(): Record {
+ return {
+ type: this.type,
+ };
+ }
+
+ /**
+ * Serialize the current object to a JSON save state.
+ */
+ toJSON(): IReviverValue {
+ return Generic_toJSON("SleeveCrimeWork", this);
+ }
+
+ /**
+ * Initiatizes a RecoveryWork object from a JSON save state.
+ */
+ static fromJSON(value: IReviverValue): SleeveCrimeWork {
+ return Generic_fromJSON(SleeveCrimeWork, value.data);
+ }
+}
+
+Reviver.constructors.SleeveCrimeWork = SleeveCrimeWork;
diff --git a/src/PersonObjects/Sleeve/Work/SleeveFactionWork.ts b/src/PersonObjects/Sleeve/Work/SleeveFactionWork.ts
index a372c3aaa..ec732cdb5 100644
--- a/src/PersonObjects/Sleeve/Work/SleeveFactionWork.ts
+++ b/src/PersonObjects/Sleeve/Work/SleeveFactionWork.ts
@@ -55,7 +55,7 @@ export class SleeveFactionWork extends Work {
process(player: IPlayer, sleeve: Sleeve, cycles: number): number {
if (player.gang) {
if (this.factionName === player.gang.facName) {
- sleeve.currentWork = null;
+ sleeve.stopWork(player);
return 0;
}
}
diff --git a/src/PersonObjects/Sleeve/Work/SleeveRecoveryWork.ts b/src/PersonObjects/Sleeve/Work/SleeveRecoveryWork.ts
index db5a08a93..5f0de0a5d 100644
--- a/src/PersonObjects/Sleeve/Work/SleeveRecoveryWork.ts
+++ b/src/PersonObjects/Sleeve/Work/SleeveRecoveryWork.ts
@@ -13,7 +13,7 @@ export class SleeveRecoveryWork extends Work {
process(player: IPlayer, sleeve: Sleeve, cycles: number): number {
sleeve.shock = Math.min(100, sleeve.shock + 0.0002 * cycles);
- if (sleeve.shock >= 100) sleeve.currentWork = null;
+ if (sleeve.shock >= 100) sleeve.stopWork(player);
return 0;
}
diff --git a/src/PersonObjects/Sleeve/Work/SleeveSupportWork.ts b/src/PersonObjects/Sleeve/Work/SleeveSupportWork.ts
new file mode 100644
index 000000000..5dfa02b7c
--- /dev/null
+++ b/src/PersonObjects/Sleeve/Work/SleeveSupportWork.ts
@@ -0,0 +1,43 @@
+import { IPlayer } from "../../../PersonObjects/IPlayer";
+import { Generic_fromJSON, Generic_toJSON, IReviverValue, Reviver } from "../../../utils/JSONReviver";
+import { Work, WorkType } from "./Work";
+
+export const isSleeveSupportWork = (w: Work | null): w is SleeveSupportWork =>
+ w !== null && w.type === WorkType.SUPPORT;
+
+export class SleeveSupportWork extends Work {
+ constructor(player?: IPlayer) {
+ super(WorkType.SUPPORT);
+ if (player) player.bladeburner?.sleeveSupport(true);
+ }
+
+ process(): number {
+ return 0;
+ }
+
+ finish(player: IPlayer): void {
+ player.bladeburner?.sleeveSupport(false);
+ }
+
+ APICopy(): Record {
+ return {
+ type: this.type,
+ };
+ }
+
+ /**
+ * Serialize the current object to a JSON save state.
+ */
+ toJSON(): IReviverValue {
+ return Generic_toJSON("SleeveSupportWork", this);
+ }
+
+ /**
+ * Initiatizes a BladeburnerWork object from a JSON save state.
+ */
+ static fromJSON(value: IReviverValue): SleeveSupportWork {
+ return Generic_fromJSON(SleeveSupportWork, value.data);
+ }
+}
+
+Reviver.constructors.SleeveSupportWork = SleeveSupportWork;
diff --git a/src/PersonObjects/Sleeve/Work/SleeveSynchroWork.ts b/src/PersonObjects/Sleeve/Work/SleeveSynchroWork.ts
index b70665401..09b5584d3 100644
--- a/src/PersonObjects/Sleeve/Work/SleeveSynchroWork.ts
+++ b/src/PersonObjects/Sleeve/Work/SleeveSynchroWork.ts
@@ -13,7 +13,7 @@ export class SleeveSynchroWork extends Work {
process(player: IPlayer, sleeve: Sleeve, cycles: number): number {
sleeve.sync = Math.min(100, sleeve.sync + player.getIntelligenceBonus(0.5) * 0.0002 * cycles);
- if (sleeve.sync >= 100) sleeve.currentWork = null;
+ if (sleeve.sync >= 100) sleeve.stopWork(player);
return 0;
}
diff --git a/src/PersonObjects/Sleeve/Work/Work.ts b/src/PersonObjects/Sleeve/Work/Work.ts
index 89bb26d14..37703df1a 100644
--- a/src/PersonObjects/Sleeve/Work/Work.ts
+++ b/src/PersonObjects/Sleeve/Work/Work.ts
@@ -12,6 +12,9 @@ export abstract class Work {
abstract process(player: IPlayer, sleeve: Sleeve, cycles: number): number;
abstract APICopy(): Record;
abstract toJSON(): IReviverValue;
+ finish(_player: IPlayer): void {
+ /* left for children to implement */
+ }
}
export enum WorkType {
@@ -21,8 +24,7 @@ export enum WorkType {
CLASS = "CLASS",
RECOVERY = "RECOVERY",
SYNCHRO = "SYNCHRO",
- BLADEBURNER_GENERAL = "BLADEBURNER_GENERAL",
+ BLADEBURNER = "BLADEBURNER",
INFILTRATE = "INFILTRATE",
- BLADEBURNER_SUPPORT = "SUPPORT",
- BLADEBURNER_CONTRACTS = "CONTRACTS",
+ SUPPORT = "SUPPORT",
}
diff --git a/src/PersonObjects/Sleeve/ui/SleeveElem.tsx b/src/PersonObjects/Sleeve/ui/SleeveElem.tsx
index 1f961f5a8..de0bfd4d7 100644
--- a/src/PersonObjects/Sleeve/ui/SleeveElem.tsx
+++ b/src/PersonObjects/Sleeve/ui/SleeveElem.tsx
@@ -19,8 +19,10 @@ import { isSleeveSynchroWork } from "../Work/SleeveSynchroWork";
import { isSleeveRecoveryWork } from "../Work/SleeveRecoveryWork";
import { isSleeveFactionWork } from "../Work/SleeveFactionWork";
import { isSleeveCompanyWork } from "../Work/SleeveCompanyWork";
-import { isSleeveBladeburnerGeneralWork } from "../Work/SleeveBladeburnerGeneralActionWork";
import { isSleeveInfiltrateWork } from "../Work/SleeveInfiltrateWork";
+import { isSleeveSupportWork } from "../Work/SleeveSupportWork";
+import { isSleeveBladeburnerWork } from "../Work/SleeveBladeburnerWork";
+import { isSleeveCrimeWork } from "../Work/SleeveCrimeWork";
interface IProps {
sleeve: Sleeve;
@@ -71,42 +73,17 @@ export function SleeveElem(props: IProps): React.ReactElement {
props.rerender();
}
- let desc = <>>;
- switch (props.sleeve.currentTask) {
- case SleeveTaskType.Idle:
- desc = <>This sleeve is currently idle>;
- break;
- case SleeveTaskType.Crime: {
- const crime = Object.values(Crimes).find((crime) => crime.name === props.sleeve.crimeType);
- if (!crime) throw new Error("crime should not be undefined");
- desc = (
- <>
- This sleeve is currently attempting to {crime.type} (Success Rate:{" "}
- {numeralWrapper.formatPercentage(crime.successRate(props.sleeve))}).
- >
- );
- break;
- }
- case SleeveTaskType.Class:
- desc = <>This sleeve is currently studying/taking a course at {props.sleeve.currentTaskLocation}.>;
- break;
- case SleeveTaskType.Bladeburner: {
- let message = "";
- if (props.sleeve.bbContract !== "------") {
- message = ` - ${props.sleeve.bbContract} (Success Rate: ${props.sleeve.currentTaskLocation})`;
- } else if (props.sleeve.currentTaskLocation !== "") {
- message = props.sleeve.currentTaskLocation;
- }
- desc = (
- <>
- This sleeve is currently attempting to {props.sleeve.bbAction}. {message}
- >
- );
- break;
- }
+ let desc = <>This sleeve is currently idle>;
- default:
- console.error(`Invalid/Unrecognized taskValue in updateSleeveTaskDescription(): ${abc[0]}`);
+ if (isSleeveCrimeWork(props.sleeve.currentWork)) {
+ const w = props.sleeve.currentWork;
+ const crime = w.getCrime();
+ desc = (
+ <>
+ This sleeve is currently attempting to {crime.type} (Success Rate:{" "}
+ {numeralWrapper.formatPercentage(crime.successRate(props.sleeve))}).
+ >
+ );
}
if (isSleeveClassWork(props.sleeve.currentWork)) {
@@ -153,11 +130,11 @@ export function SleeveElem(props: IProps): React.ReactElement {
desc = <>This sleeve is currently working your job at {props.sleeve.currentWork.companyName}.>;
}
- if (isSleeveBladeburnerGeneralWork(props.sleeve.currentWork)) {
+ if (isSleeveBladeburnerWork(props.sleeve.currentWork)) {
const w = props.sleeve.currentWork;
desc = (
<>
- This sleeve is currently attempting to perform {w.action}. (
+ This sleeve is currently attempting to perform {w.actionName}. (
{((100 * w.cyclesWorked) / w.cyclesNeeded(player, props.sleeve)).toFixed(2)}%)
>
);
@@ -173,6 +150,10 @@ export function SleeveElem(props: IProps): React.ReactElement {
);
}
+ if (isSleeveSupportWork(props.sleeve.currentWork)) {
+ desc = <>This sleeve is currently supporting you in your bladeburner activities.>;
+ }
+
return (
<>
diff --git a/src/PersonObjects/Sleeve/ui/StatsElement.tsx b/src/PersonObjects/Sleeve/ui/StatsElement.tsx
index 8f5e6edac..4000a8348 100644
--- a/src/PersonObjects/Sleeve/ui/StatsElement.tsx
+++ b/src/PersonObjects/Sleeve/ui/StatsElement.tsx
@@ -16,6 +16,7 @@ import { SleeveTaskType } from "../SleeveTaskTypesEnum";
import { isSleeveClassWork } from "../Work/SleeveClassWork";
import { isSleeveFactionWork } from "../Work/SleeveFactionWork";
import { isSleeveCompanyWork } from "../Work/SleeveCompanyWork";
+import { isSleeveCrimeWork } from "../Work/SleeveCrimeWork";
interface IProps {
sleeve: Sleeve;
@@ -97,35 +98,17 @@ export function EarningsElement(props: IProps): React.ReactElement {
const player = use.Player();
let data: (string | JSX.Element)[][] = [];
- if (props.sleeve.currentTask === SleeveTaskType.Crime) {
+ if (isSleeveCrimeWork(props.sleeve.currentWork)) {
+ const gains = props.sleeve.currentWork.getExp();
data = [
- [
- `Money`,
- <>
- (on success)
- >,
- ],
- [`Hacking Exp`, `${numeralWrapper.formatExp(props.sleeve.gainRatesForTask.hack)} (2x on success)`],
- [`Strength Exp`, `${numeralWrapper.formatExp(props.sleeve.gainRatesForTask.str)} (2x on success)`],
- [`Defense Exp`, `${numeralWrapper.formatExp(props.sleeve.gainRatesForTask.def)} (2x on success)`],
- [`Dexterity Exp`, `${numeralWrapper.formatExp(props.sleeve.gainRatesForTask.dex)} (2x on success)`],
- [`Agility Exp`, `${numeralWrapper.formatExp(props.sleeve.gainRatesForTask.agi)} (2x on success)`],
- [`Charisma Exp`, `${numeralWrapper.formatExp(props.sleeve.gainRatesForTask.cha)} (2x on success)`],
+ [`Money:`, ],
+ [`Hacking Exp:`, `${numeralWrapper.formatExp(5 * gains.hackExp)}`],
+ [`Strength Exp:`, `${numeralWrapper.formatExp(5 * gains.strExp)}`],
+ [`Defense Exp:`, `${numeralWrapper.formatExp(5 * gains.defExp)}`],
+ [`Dexterity Exp:`, `${numeralWrapper.formatExp(5 * gains.dexExp)}`],
+ [`Agility Exp:`, `${numeralWrapper.formatExp(5 * gains.agiExp)}`],
+ [`Charisma Exp:`, `${numeralWrapper.formatExp(5 * gains.chaExp)}`],
];
- } else {
- data = [
- [`Money:`, ],
- [`Hacking Exp:`, `${numeralWrapper.formatExp(5 * props.sleeve.gainRatesForTask.hack)} / sec`],
- [`Strength Exp:`, `${numeralWrapper.formatExp(5 * props.sleeve.gainRatesForTask.str)} / sec`],
- [`Defense Exp:`, `${numeralWrapper.formatExp(5 * props.sleeve.gainRatesForTask.def)} / sec`],
- [`Dexterity Exp:`, `${numeralWrapper.formatExp(5 * props.sleeve.gainRatesForTask.dex)} / sec`],
- [`Agility Exp:`, `${numeralWrapper.formatExp(5 * props.sleeve.gainRatesForTask.agi)} / sec`],
- [`Charisma Exp:`, `${numeralWrapper.formatExp(5 * props.sleeve.gainRatesForTask.cha)} / sec`],
- ];
- if (props.sleeve.currentTask === SleeveTaskType.Company || props.sleeve.currentTask === SleeveTaskType.Faction) {
- const repGain: number = props.sleeve.getRepGain(player);
- data.push([`Reputation:`, ]);
- }
}
if (isSleeveClassWork(props.sleeve.currentWork)) {
const rates = props.sleeve.currentWork.calculateRates(player, props.sleeve);
diff --git a/src/ScriptEditor/NetscriptDefinitions.d.ts b/src/ScriptEditor/NetscriptDefinitions.d.ts
index 65cc2b00d..b94170d26 100644
--- a/src/ScriptEditor/NetscriptDefinitions.d.ts
+++ b/src/ScriptEditor/NetscriptDefinitions.d.ts
@@ -1016,36 +1016,13 @@ export interface SleeveInformation {
tor: boolean;
/** Sleeve multipliers */
mult: CharacterMult;
- /** Time spent on the current task in milliseconds */
- timeWorked: number;
- /** Earnings synchronized to other sleeves */
- earningsForSleeves: SleeveWorkGains;
- /** Earnings synchronized to the player */
- earningsForPlayer: SleeveWorkGains;
- /** Earnings for this sleeve */
- earningsForTask: SleeveWorkGains;
- /** Faction or company reputation gained for the current task */
- workRepGain: number;
}
/**
* Object representing a sleeve current task.
* @public
*/
-export interface SleeveTask {
- /** Task type */
- task: string;
- /** Crime currently attempting, if any */
- crime: string;
- /** Location of the task, if any */
- location: string;
- /** Stat being trained at the gym, if any */
- gymStatType: string;
- /** Faction work type being performed, if any */
- factionWorkType: string;
- /** Class being taken at university, if any */
- className: string;
-}
+export interface SleeveTask = any;
/**
* Object representing a port. A port is a serialized queue.
@@ -1310,7 +1287,7 @@ export interface TIX {
* @param shares - Number of shares to short. Must be positive. Will be rounded to nearest integer.
* @returns The stock price at which each share was purchased, otherwise 0 if the shares weren't purchased.
*/
- short(sym: string, shares: number): number;
+ buyShort(sym: string, shares: number): number;
/**
* Sell short stock.
diff --git a/src/Work/CrimeWork.ts b/src/Work/CrimeWork.ts
index 356d932e1..3c7bc8933 100644
--- a/src/Work/CrimeWork.ts
+++ b/src/Work/CrimeWork.ts
@@ -26,29 +26,29 @@ enum newCrimeType {
const convertCrimeType = (crimeType: CrimeType): newCrimeType => {
switch (crimeType) {
- case CrimeType.Shoplift:
+ case CrimeType.SHOPLIFT:
return newCrimeType.SHOPLIFT;
- case CrimeType.RobStore:
+ case CrimeType.ROB_STORE:
return newCrimeType.ROBSTORE;
- case CrimeType.Mug:
+ case CrimeType.MUG:
return newCrimeType.MUG;
- case CrimeType.Larceny:
+ case CrimeType.LARCENY:
return newCrimeType.LARCENY;
- case CrimeType.Drugs:
+ case CrimeType.DRUGS:
return newCrimeType.DRUGS;
- case CrimeType.BondForgery:
+ case CrimeType.BOND_FORGERY:
return newCrimeType.BONDFORGERY;
- case CrimeType.TraffickArms:
+ case CrimeType.TRAFFIC_ARMS:
return newCrimeType.TRAFFICKARMS;
- case CrimeType.Homicide:
+ case CrimeType.HOMICIDE:
return newCrimeType.HOMICIDE;
- case CrimeType.GrandTheftAuto:
+ case CrimeType.GRAND_THEFT_AUTO:
return newCrimeType.GRANDTHEFTAUTO;
- case CrimeType.Kidnap:
+ case CrimeType.KIDNAP:
return newCrimeType.KIDNAP;
- case CrimeType.Assassination:
+ case CrimeType.ASSASSINATION:
return newCrimeType.ASSASSINATION;
- case CrimeType.Heist:
+ case CrimeType.HEIST:
return newCrimeType.HEIST;
}
return newCrimeType.SHOPLIFT;
@@ -67,7 +67,7 @@ export class CrimeWork extends Work {
constructor(params?: CrimeWorkParams) {
super(WorkType.CRIME, params?.singularity ?? true);
- this.crimeType = params?.crimeType ?? CrimeType.Shoplift;
+ this.crimeType = params?.crimeType ?? CrimeType.SHOPLIFT;
this.unitCompleted = 0;
}
diff --git a/src/utils/WorkType.ts b/src/utils/WorkType.ts
index 58c003fd7..f4cd1a285 100644
--- a/src/utils/WorkType.ts
+++ b/src/utils/WorkType.ts
@@ -1,15 +1,15 @@
export enum CrimeType {
None = "",
- Shoplift = "shoplift",
- RobStore = "rob a store",
- Mug = "mug someone",
- Larceny = "commit larceny",
- Drugs = "deal drugs",
- BondForgery = "forge corporate bonds",
- TraffickArms = "traffick illegal arms",
- Homicide = "commit homicide",
- GrandTheftAuto = "commit grand theft auto",
- Kidnap = "kidnap someone for ransom",
- Assassination = "assassinate a high-profile target",
- Heist = "pull off the ultimate heist",
+ SHOPLIFT = "SHOPLIFT", //"shoplift",
+ ROB_STORE = "ROBSTORE", //"rob a store",
+ MUG = "MUG", //"mug someone",
+ LARCENY = "LARCENY", //"commit larceny",
+ DRUGS = "DRUGS", //"deal drugs",
+ BOND_FORGERY = "BONDFORGERY", //"forge corporate bonds",
+ TRAFFIC_ARMS = "TRAFFICKARMS", //"traffick illegal arms",
+ HOMICIDE = "HOMICIDE", //"commit homicide",
+ GRAND_THEFT_AUTO = "GRANDTHEFTAUTO", //"commit grand theft auto",
+ KIDNAP = "KIDNAP", //"kidnap someone for ransom",
+ ASSASSINATION = "ASSASSINATION", //"assassinate a high-profile target",
+ HEIST = "HEIST", //"pull off the ultimate heist",
}
diff --git a/src/utils/v2APIBreak.ts b/src/utils/v2APIBreak.ts
index 4285dd7ef..41a41abe6 100644
--- a/src/utils/v2APIBreak.ts
+++ b/src/utils/v2APIBreak.ts
@@ -185,6 +185,12 @@ export const v2APIBreak = () => {
reason: "sell is a very common word so in order to avoid ram costs it was renamed ns.stock.sellStock",
offenders: [],
},
+ {
+ matchJS: /ns\.stock\.short/g,
+ matchScript: /stock\.short/g,
+ reason: "short is a very common word so in order to avoid ram costs it was renamed ns.stock.buyShort",
+ offenders: [],
+ },
{
matchJS: /ns\.corporation\.bribe/g,
matchScript: /corporation\.bribe/g,