remove unused fields on sleeves

This commit is contained in:
Olivier Gagnon 2022-07-28 03:08:39 -04:00
parent 4549b0d467
commit 3b35b07860
9 changed files with 142 additions and 445 deletions

@ -36,6 +36,8 @@ import { joinFaction } from "../Faction/FactionHelpers";
import { WorkerScript } from "../Netscript/WorkerScript"; import { WorkerScript } from "../Netscript/WorkerScript";
import { FactionNames } from "../Faction/data/FactionNames"; import { FactionNames } from "../Faction/data/FactionNames";
import { KEY } from "../utils/helpers/keyCodes"; import { KEY } from "../utils/helpers/keyCodes";
import { isSleeveInfiltrateWork } from "../PersonObjects/Sleeve/Work/SleeveInfiltrateWork";
import { isSleeveSupportWork } from "../PersonObjects/Sleeve/Work/SleeveSupportWork";
interface BlackOpsAttempt { interface BlackOpsAttempt {
error?: string; error?: string;
@ -1124,7 +1126,7 @@ export class Bladeburner implements IBladeburner {
const losses = getRandomInt(0, max); const losses = getRandomInt(0, max);
this.teamSize -= losses; this.teamSize -= losses;
if (this.teamSize < this.sleeveSize) { if (this.teamSize < this.sleeveSize) {
const sup = player.sleeves.filter((x) => x.bbAction == "Support main sleeve"); const sup = player.sleeves.filter((x) => isSleeveSupportWork(x.currentWork));
for (let i = 0; i > this.teamSize - this.sleeveSize; i--) { for (let i = 0; i > this.teamSize - this.sleeveSize; i--) {
const r = Math.floor(Math.random() * sup.length); const r = Math.floor(Math.random() * sup.length);
sup[r].takeDamage(sup[r].hp.max); sup[r].takeDamage(sup[r].hp.max);
@ -1438,7 +1440,7 @@ export class Bladeburner implements IBladeburner {
const losses = getRandomInt(1, teamLossMax); const losses = getRandomInt(1, teamLossMax);
this.teamSize -= losses; this.teamSize -= losses;
if (this.teamSize < this.sleeveSize) { if (this.teamSize < this.sleeveSize) {
const sup = player.sleeves.filter((x) => x.bbAction == "Support main sleeve"); const sup = player.sleeves.filter((x) => isSleeveSupportWork(x.currentWork));
for (let i = 0; i > this.teamSize - this.sleeveSize; i--) { for (let i = 0; i > this.teamSize - this.sleeveSize; i--) {
const r = Math.floor(Math.random() * sup.length); const r = Math.floor(Math.random() * sup.length);
sup[r].takeDamage(sup[r].hp.max); sup[r].takeDamage(sup[r].hp.max);
@ -1602,7 +1604,7 @@ export class Bladeburner implements IBladeburner {
} }
infiltrateSynthoidCommunities(p: IPlayer): void { infiltrateSynthoidCommunities(p: IPlayer): void {
const infilSleeves = p.sleeves.filter((s) => s.bbAction === "Infiltrate synthoids").length; const infilSleeves = p.sleeves.filter((s) => isSleeveInfiltrateWork(s.currentWork)).length;
const amt = Math.pow(infilSleeves, -0.5) / 2; const amt = Math.pow(infilSleeves, -0.5) / 2;
for (const contract of Object.keys(this.contracts)) { for (const contract of Object.keys(this.contracts)) {
this.contracts[contract].count += amt; this.contracts[contract].count += amt;

@ -1,5 +1,4 @@
import { IPlayer } from "../PersonObjects/IPlayer"; import { IPlayer } from "../PersonObjects/IPlayer";
import { SleeveTaskType } from "../PersonObjects/Sleeve/SleeveTaskTypesEnum";
import { findSleevePurchasableAugs } from "../PersonObjects/Sleeve/SleeveHelpers"; import { findSleevePurchasableAugs } from "../PersonObjects/Sleeve/SleeveHelpers";
import { StaticAugmentations } from "../Augmentation/StaticAugmentations"; import { StaticAugmentations } from "../Augmentation/StaticAugmentations";
import { CityName } from "../Locations/data/CityNames"; import { CityName } from "../Locations/data/CityNames";
@ -15,7 +14,9 @@ import {
} from "../ScriptEditor/NetscriptDefinitions"; } from "../ScriptEditor/NetscriptDefinitions";
import { checkEnum } from "../utils/helpers/checkEnum"; import { checkEnum } from "../utils/helpers/checkEnum";
import { InternalAPI, NetscriptContext } from "../Netscript/APIWrapper"; import { InternalAPI, NetscriptContext } from "../Netscript/APIWrapper";
import { FactionWorkType } from "../Work/data/FactionWorkType"; import { isSleeveBladeburnerWork } from "../PersonObjects/Sleeve/Work/SleeveBladeburnerWork";
import { isSleeveFactionWork } from "../PersonObjects/Sleeve/Work/SleeveFactionWork";
import { isSleeveCompanyWork } from "../PersonObjects/Sleeve/Work/SleeveCompanyWork";
export function NetscriptSleeve(player: IPlayer): InternalAPI<ISleeve> { export function NetscriptSleeve(player: IPlayer): InternalAPI<ISleeve> {
const checkSleeveAPIAccess = function (ctx: NetscriptContext): void { const checkSleeveAPIAccess = function (ctx: NetscriptContext): void {
@ -120,7 +121,7 @@ export function NetscriptSleeve(player: IPlayer): InternalAPI<ISleeve> {
continue; continue;
} }
const other = player.sleeves[i]; const other = player.sleeves[i];
if (other.currentTask === SleeveTaskType.Company && other.currentTaskLocation === companyName) { if (isSleeveCompanyWork(other.currentWork) && other.currentWork.companyName === companyName) {
throw ctx.makeRuntimeErrorMsg( throw ctx.makeRuntimeErrorMsg(
`Sleeve ${sleeveNumber} cannot work for company ${companyName} because Sleeve ${i} is already working for them.`, `Sleeve ${sleeveNumber} cannot work for company ${companyName} because Sleeve ${i} is already working for them.`,
); );
@ -144,7 +145,7 @@ export function NetscriptSleeve(player: IPlayer): InternalAPI<ISleeve> {
continue; continue;
} }
const other = player.sleeves[i]; const other = player.sleeves[i];
if (other.currentTask === SleeveTaskType.Faction && other.currentTaskLocation === factionName) { if (isSleeveFactionWork(other.currentWork) && other.currentWork.factionName === factionName) {
throw ctx.makeRuntimeErrorMsg( throw ctx.makeRuntimeErrorMsg(
`Sleeve ${sleeveNumber} cannot work for faction ${factionName} because Sleeve ${i} is already working for them.`, `Sleeve ${sleeveNumber} cannot work for faction ${factionName} because Sleeve ${i} is already working for them.`,
); );
@ -223,36 +224,6 @@ export function NetscriptSleeve(player: IPlayer): InternalAPI<ISleeve> {
strengthExp: sl.mults.strength_exp, strengthExp: sl.mults.strength_exp,
workMoney: sl.mults.work_money, workMoney: sl.mults.work_money,
}, },
timeWorked: sl.currentTaskTime,
earningsForSleeves: {
workHackExpGain: sl.earningsForSleeves.hack,
workStrExpGain: sl.earningsForSleeves.str,
workDefExpGain: sl.earningsForSleeves.def,
workDexExpGain: sl.earningsForSleeves.dex,
workAgiExpGain: sl.earningsForSleeves.agi,
workChaExpGain: sl.earningsForSleeves.cha,
workMoneyGain: sl.earningsForSleeves.money,
},
earningsForPlayer: {
workHackExpGain: sl.earningsForPlayer.hack,
workStrExpGain: sl.earningsForPlayer.str,
workDefExpGain: sl.earningsForPlayer.def,
workDexExpGain: sl.earningsForPlayer.dex,
workAgiExpGain: sl.earningsForPlayer.agi,
workChaExpGain: sl.earningsForPlayer.cha,
workMoneyGain: sl.earningsForPlayer.money,
},
earningsForTask: {
workHackExpGain: sl.earningsForTask.hack,
workStrExpGain: sl.earningsForTask.str,
workDefExpGain: sl.earningsForTask.def,
workDexExpGain: sl.earningsForTask.dex,
workAgiExpGain: sl.earningsForTask.agi,
workChaExpGain: sl.earningsForTask.cha,
workMoneyGain: sl.earningsForTask.money,
},
workRepGain: sl.getRepGain(player),
}; };
}, },
getSleeveAugmentations: getSleeveAugmentations:
@ -343,11 +314,7 @@ export function NetscriptSleeve(player: IPlayer): InternalAPI<ISleeve> {
continue; continue;
} }
const other = player.sleeves[i]; const other = player.sleeves[i];
if ( if (isSleeveBladeburnerWork(other.currentWork) && other.currentWork.actionName === contract) {
other.currentTask === SleeveTaskType.Bladeburner &&
other.bbAction === action &&
other.bbContract === contract
) {
throw ctx.helper.makeRuntimeErrorMsg( throw ctx.helper.makeRuntimeErrorMsg(
`Sleeve ${sleeveNumber} cannot take on contracts because Sleeve ${i} is already performing that action.`, `Sleeve ${sleeveNumber} cannot take on contracts because Sleeve ${i} is already performing that action.`,
); );

@ -6,7 +6,6 @@
* *
* Sleeves are unlocked in BitNode-10. * Sleeves are unlocked in BitNode-10.
*/ */
import { SleeveTaskType } from "./SleeveTaskTypesEnum";
import { IPlayer } from "../IPlayer"; import { IPlayer } from "../IPlayer";
import { Person } from "../Person"; import { Person } from "../Person";
@ -14,8 +13,6 @@ import { ITaskTracker, createTaskTracker } from "../ITaskTracker";
import { Augmentation } from "../../Augmentation/Augmentation"; import { Augmentation } from "../../Augmentation/Augmentation";
import { BitNodeMultipliers } from "../../BitNode/BitNodeMultipliers";
import { Crime } from "../../Crime/Crime"; import { Crime } from "../../Crime/Crime";
import { Crimes } from "../../Crime/Crimes"; import { Crimes } from "../../Crime/Crimes";
@ -33,9 +30,7 @@ import { CityName } from "../../Locations/data/CityNames";
import { LocationName } from "../../Locations/data/LocationNames"; import { LocationName } from "../../Locations/data/LocationNames";
import { Generic_fromJSON, Generic_toJSON, IReviverValue, Reviver } from "../../utils/JSONReviver"; import { Generic_fromJSON, Generic_toJSON, IReviverValue, Reviver } from "../../utils/JSONReviver";
import { BladeburnerConstants } from "../../Bladeburner/data/Constants";
import { numeralWrapper } from "../../ui/numeralFormat"; import { numeralWrapper } from "../../ui/numeralFormat";
import { capitalizeFirstLetter } from "../../utils/StringHelperFunctions";
import { FactionWorkType } from "../../Work/data/FactionWorkType"; import { FactionWorkType } from "../../Work/data/FactionWorkType";
import { Work } from "./Work/Work"; import { Work } from "./Work/Work";
import { SleeveClassWork } from "./Work/SleeveClassWork"; import { SleeveClassWork } from "./Work/SleeveClassWork";
@ -51,82 +46,6 @@ import { SleeveCrimeWork } from "./Work/SleeveCrimeWork";
export class Sleeve extends Person { export class Sleeve extends Person {
currentWork: Work | null = null; currentWork: Work | null = null;
/**
* Stores the name of the class that the player is currently taking
*/
className = "";
/**
* Stores the type of crime the sleeve is currently attempting
* Must match the name of a Crime object
*/
crimeType = "";
/**
* Enum value for current task
*/
currentTask: SleeveTaskType = SleeveTaskType.Idle;
/**
* Contains details about the sleeve's current task. The info stored
* in this depends on the task type
*
* Faction/Company Work: Name of Faction/Company
* Crime: Money earned if successful
* Class/Gym: Name of university/gym
* Bladeburner: success chance
*/
currentTaskLocation = "";
/**
* Maximum amount of time (in milliseconds) that can be spent on current task.
*/
currentTaskMaxTime = 0;
/**
* Milliseconds spent on current task
*/
currentTaskTime = 0;
/**
* Keeps track of experience earned for other sleeves
*/
earningsForSleeves: ITaskTracker = createTaskTracker();
/**
* Keeps track of experience + money earned for player
*/
earningsForPlayer: ITaskTracker = createTaskTracker();
/**
* Keeps track of experienced earned in the current task/action
*/
earningsForTask: ITaskTracker = createTaskTracker();
/**
* Keeps track of what type of work sleeve is doing for faction, if applicable
*/
factionWorkType: FactionWorkType = FactionWorkType.HACKING;
/**
* Records experience gain rate for the current task
*/
gainRatesForTask: ITaskTracker = createTaskTracker();
/**
* String that stores what stat the sleeve is training at the gym
*/
gymStatType = "";
/**
* String that stores what stat the sleeve is training at the gym
*/
bbAction = "";
/**
* String that stores what stat the sleeve is training at the gym
*/
bbContract = "";
/** /**
* Clone retains 'memory' synchronization (and maybe exp?) upon prestige/installing Augs * Clone retains 'memory' synchronization (and maybe exp?) upon prestige/installing Augs
@ -187,12 +106,6 @@ export class Sleeve extends Person {
return false; return false;
} }
if (this.currentTask !== SleeveTaskType.Idle || this.currentWork === null) {
this.finishTask(p);
} else {
this.resetTaskStatus(p);
}
this.startWork(p, new SleeveCrimeWork(crime.type)); this.startWork(p, new SleeveCrimeWork(crime.type));
return true; return true;
} }
@ -259,43 +172,31 @@ export class Sleeve extends Person {
if (pHackExp > 0) { if (pHackExp > 0) {
this.gainHackingExp(pHackExp); this.gainHackingExp(pHackExp);
p.gainHackingExp(pHackExp); p.gainHackingExp(pHackExp);
this.earningsForPlayer.hack += pHackExp;
this.earningsForTask.hack += pHackExp;
} }
if (pStrExp > 0) { if (pStrExp > 0) {
this.gainStrengthExp(pStrExp); this.gainStrengthExp(pStrExp);
p.gainStrengthExp(pStrExp); p.gainStrengthExp(pStrExp);
this.earningsForPlayer.str += pStrExp;
this.earningsForTask.str += pStrExp;
} }
if (pDefExp > 0) { if (pDefExp > 0) {
this.gainDefenseExp(pDefExp); this.gainDefenseExp(pDefExp);
p.gainDefenseExp(pDefExp); p.gainDefenseExp(pDefExp);
this.earningsForPlayer.def += pDefExp;
this.earningsForTask.def += pDefExp;
} }
if (pDexExp > 0) { if (pDexExp > 0) {
this.gainDexterityExp(pDexExp); this.gainDexterityExp(pDexExp);
p.gainDexterityExp(pDexExp); p.gainDexterityExp(pDexExp);
this.earningsForPlayer.dex += pDexExp;
this.earningsForTask.dex += pDexExp;
} }
if (pAgiExp > 0) { if (pAgiExp > 0) {
this.gainAgilityExp(pAgiExp); this.gainAgilityExp(pAgiExp);
p.gainAgilityExp(pAgiExp); p.gainAgilityExp(pAgiExp);
this.earningsForPlayer.agi += pAgiExp;
this.earningsForTask.agi += pAgiExp;
} }
if (pChaExp > 0) { if (pChaExp > 0) {
this.gainCharismaExp(pChaExp); this.gainCharismaExp(pChaExp);
p.gainCharismaExp(pChaExp); p.gainCharismaExp(pChaExp);
this.earningsForPlayer.cha += pChaExp;
this.earningsForTask.cha += pChaExp;
} }
if (pIntExp > 0) { if (pIntExp > 0) {
@ -303,14 +204,6 @@ export class Sleeve extends Person {
p.gainIntelligenceExp(pIntExp); p.gainIntelligenceExp(pIntExp);
} }
// Record earnings for other sleeves
this.earningsForSleeves.hack += pHackExp * (this.sync / 100);
this.earningsForSleeves.str += pStrExp * (this.sync / 100);
this.earningsForSleeves.def += pDefExp * (this.sync / 100);
this.earningsForSleeves.dex += pDexExp * (this.sync / 100);
this.earningsForSleeves.agi += pAgiExp * (this.sync / 100);
this.earningsForSleeves.cha += pChaExp * (this.sync / 100);
// Return the experience to be gained by other sleeves // Return the experience to be gained by other sleeves
return { return {
hack: pHackExp * (this.sync / 100), hack: pHackExp * (this.sync / 100),
@ -327,12 +220,12 @@ export class Sleeve extends Person {
/** /**
* Earn money for player * Earn money for player
*/ */
gainMoney(p: IPlayer, task: ITaskTracker, numCycles = 1): void { // gainMoney(p: IPlayer, task: ITaskTracker, numCycles = 1): void {
const gain: number = task.money * numCycles; // const gain: number = task.money * numCycles;
this.earningsForTask.money += gain; // this.earningsForTask.money += gain;
this.earningsForPlayer.money += gain; // this.earningsForPlayer.money += gain;
p.gainMoney(gain, "sleeves"); // p.gainMoney(gain, "sleeves");
} // }
/** /**
* Returns the cost of upgrading this sleeve's memory by a certain amount * Returns the cost of upgrading this sleeve's memory by a certain amount
@ -363,36 +256,36 @@ export class Sleeve extends Person {
* Gets reputation gain for the current task * Gets reputation gain for the current task
* Only applicable when working for company or faction * Only applicable when working for company or faction
*/ */
getRepGain(p: IPlayer): number { // getRepGain(p: IPlayer): number {
if (this.currentTask === SleeveTaskType.Company) { // if (this.currentTask === SleeveTaskType.Company) {
const companyName: string = this.currentTaskLocation; // const companyName: string = this.currentTaskLocation;
const company: Company | null = Companies[companyName]; // const company: Company | null = Companies[companyName];
if (company == null) { // if (company == null) {
console.error(`Invalid company found when trying to calculate rep gain: ${companyName}`); // console.error(`Invalid company found when trying to calculate rep gain: ${companyName}`);
return 0; // return 0;
} // }
const companyPosition: CompanyPosition | null = CompanyPositions[p.jobs[companyName]]; // const companyPosition: CompanyPosition | null = CompanyPositions[p.jobs[companyName]];
if (companyPosition == null) { // if (companyPosition == null) {
console.error(`Invalid company position name found when trying to calculate rep gain: ${p.jobs[companyName]}`); // console.error(`Invalid company position name found when trying to calculate rep gain: ${p.jobs[companyName]}`);
return 0; // return 0;
} // }
const jobPerformance: number = companyPosition.calculateJobPerformance( // const jobPerformance: number = companyPosition.calculateJobPerformance(
this.skills.hacking, // this.skills.hacking,
this.skills.strength, // this.skills.strength,
this.skills.defense, // this.skills.defense,
this.skills.dexterity, // this.skills.dexterity,
this.skills.agility, // this.skills.agility,
this.skills.charisma, // this.skills.charisma,
); // );
const favorMult = 1 + company.favor / 100; // const favorMult = 1 + company.favor / 100;
return jobPerformance * this.mults.company_rep * favorMult; // return jobPerformance * this.mults.company_rep * favorMult;
} else { // } else {
return 0; // return 0;
} // }
} // }
installAugmentation(aug: Augmentation): void { installAugmentation(aug: Augmentation): void {
this.exp.hacking = 0; this.exp.hacking = 0;
@ -420,8 +313,6 @@ export class Sleeve extends Person {
// Reset task-related stuff // Reset task-related stuff
this.resetTaskStatus(p); this.resetTaskStatus(p);
this.earningsForSleeves = createTaskTracker();
this.earningsForPlayer = createTaskTracker();
this.shockRecovery(p); this.shockRecovery(p);
// Reset augs and multipliers // Reset augs and multipliers
@ -457,20 +348,6 @@ export class Sleeve extends Person {
return; return;
} }
let time = cyclesUsed * CONSTANTS.MilliPerCycle;
if (this.currentTaskMaxTime !== 0 && this.currentTaskTime + time > this.currentTaskMaxTime) {
time = this.currentTaskMaxTime - this.currentTaskTime;
cyclesUsed = Math.floor(time / CONSTANTS.MilliPerCycle);
if (time < 0 || cyclesUsed < 0) {
console.warn(`Sleeve.process() calculated negative cycle usage`);
time = 0;
cyclesUsed = 0;
}
}
this.currentTaskTime += time;
// Shock gradually goes towards 100 // Shock gradually goes towards 100
this.shock = Math.min(100, this.shock + 0.0001 * cyclesUsed); this.shock = Math.min(100, this.shock + 0.0001 * cyclesUsed);
@ -486,39 +363,14 @@ export class Sleeve extends Person {
*/ */
resetTaskStatus(p: IPlayer): void { resetTaskStatus(p: IPlayer): void {
this.stopWork(p); this.stopWork(p);
if (this.bbAction == "Support main sleeve") {
p.bladeburner?.sleeveSupport(false);
}
this.earningsForTask = createTaskTracker();
this.gainRatesForTask = createTaskTracker();
this.currentTask = SleeveTaskType.Idle;
this.currentTaskTime = 0;
this.currentTaskMaxTime = 0;
this.factionWorkType = FactionWorkType.HACKING;
this.crimeType = "";
this.currentTaskLocation = "";
this.gymStatType = "";
this.className = "";
this.bbAction = "";
this.bbContract = "------";
} }
shockRecovery(p: IPlayer): boolean { shockRecovery(p: IPlayer): boolean {
if (this.currentTask !== SleeveTaskType.Idle || this.currentWork === null) {
this.finishTask(p);
} else {
this.resetTaskStatus(p);
}
this.startWork(p, new SleeveRecoveryWork()); this.startWork(p, new SleeveRecoveryWork());
return true; return true;
} }
synchronize(p: IPlayer): boolean { synchronize(p: IPlayer): boolean {
if (this.currentTask !== SleeveTaskType.Idle || this.currentWork !== null) {
this.finishTask(p);
} else {
this.resetTaskStatus(p);
}
this.startWork(p, new SleeveSynchroWork()); this.startWork(p, new SleeveSynchroWork());
return true; return true;
} }
@ -527,12 +379,6 @@ export class Sleeve extends Person {
* Take a course at a university * Take a course at a university
*/ */
takeUniversityCourse(p: IPlayer, universityName: string, className: string): boolean { takeUniversityCourse(p: IPlayer, universityName: string, className: string): boolean {
if (this.currentTask !== SleeveTaskType.Idle || this.currentWork) {
this.finishTask(p);
} else {
this.resetTaskStatus(p);
}
// Set exp/money multipliers based on which university. // Set exp/money multipliers based on which university.
// Also check that the sleeve is in the right city // Also check that the sleeve is in the right city
let loc: LocationName | undefined; let loc: LocationName | undefined;
@ -632,12 +478,6 @@ export class Sleeve extends Person {
return false; return false;
} }
if (this.currentTask !== SleeveTaskType.Idle || this.currentWork !== null) {
this.finishTask(p);
} else {
this.resetTaskStatus(p);
}
const company: Company | null = Companies[companyName]; const company: Company | null = Companies[companyName];
const companyPosition: CompanyPosition | null = CompanyPositions[p.jobs[companyName]]; const companyPosition: CompanyPosition | null = CompanyPositions[p.jobs[companyName]];
if (company == null) return false; if (company == null) return false;
@ -658,12 +498,6 @@ export class Sleeve extends Person {
return false; return false;
} }
if (this.currentTask !== SleeveTaskType.Idle || this.currentWork === null) {
this.finishTask(p);
} else {
this.resetTaskStatus(p);
}
const factionInfo = faction.getInfo(); const factionInfo = faction.getInfo();
// Set type of work (hacking/field/security), and the experience gains // Set type of work (hacking/field/security), and the experience gains
@ -697,12 +531,6 @@ export class Sleeve extends Person {
* Begin a gym workout task * Begin a gym workout task
*/ */
workoutAtGym(p: IPlayer, gymName: string, stat: string): boolean { workoutAtGym(p: IPlayer, gymName: string, stat: string): boolean {
if (this.currentTask !== SleeveTaskType.Idle || this.currentWork) {
this.finishTask(p);
} else {
this.resetTaskStatus(p);
}
// Set exp/money multipliers based on which university. // Set exp/money multipliers based on which university.
// Also check that the sleeve is in the right city // Also check that the sleeve is in the right city
let loc: LocationName | undefined; let loc: LocationName | undefined;
@ -770,42 +598,14 @@ export class Sleeve extends Person {
* Begin a bladeburner task * Begin a bladeburner task
*/ */
bladeburner(p: IPlayer, action: string, contract: string): boolean { bladeburner(p: IPlayer, action: string, contract: string): boolean {
if (this.currentTask !== SleeveTaskType.Idle || this.currentWork === null) {
this.finishTask(p);
} else {
this.resetTaskStatus(p);
}
this.gainRatesForTask.hack = 0;
this.gainRatesForTask.str = 0;
this.gainRatesForTask.def = 0;
this.gainRatesForTask.dex = 0;
this.gainRatesForTask.agi = 0;
this.gainRatesForTask.cha = 0;
this.gainRatesForTask.money = 0;
this.currentTaskLocation = "";
const time = 0;
this.bbContract = "------";
switch (action) { switch (action) {
case "Field analysis": case "Field analysis":
// time = this.getBladeburnerActionTime(p, "General", action);
// this.gainRatesForTask.hack = 20 * this.mults.hacking_exp;
// this.gainRatesForTask.cha = 20 * this.mults.charisma_exp;
this.startWork(p, new SleeveBladeburnerWork({ type: "General", name: "Field Analysis" })); this.startWork(p, new SleeveBladeburnerWork({ type: "General", name: "Field Analysis" }));
return true; return true;
case "Recruitment": case "Recruitment":
// time = this.getBladeburnerActionTime(p, "General", action);
// this.gainRatesForTask.cha =
// 2 * BladeburnerConstants.BaseStatGain * (p.bladeburner?.getRecruitmentTime(this) ?? 0) * 1000;
// this.currentTaskLocation = `(Success Rate: ${numeralWrapper.formatPercentage(
// this.recruitmentSuccessChance(p),
// )})`;
this.startWork(p, new SleeveBladeburnerWork({ type: "General", name: "Recruitment" })); this.startWork(p, new SleeveBladeburnerWork({ type: "General", name: "Recruitment" }));
return true; return true;
case "Diplomacy": case "Diplomacy":
// time = this.getBladeburnerActionTime(p, "General", action);
this.startWork(p, new SleeveBladeburnerWork({ type: "General", name: "Diplomacy" })); this.startWork(p, new SleeveBladeburnerWork({ type: "General", name: "Diplomacy" }));
return true; return true;
case "Infiltrate synthoids": case "Infiltrate synthoids":
@ -817,16 +617,8 @@ export class Sleeve extends Person {
case "Take on contracts": case "Take on contracts":
this.startWork(p, new SleeveBladeburnerWork({ type: "Contracts", name: contract })); this.startWork(p, new SleeveBladeburnerWork({ type: "Contracts", name: contract }));
return true; 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());
this.currentTaskMaxTime = time;
this.currentTask = SleeveTaskType.Bladeburner;
return true; return true;
} }
@ -853,38 +645,38 @@ export class Sleeve extends Person {
} }
} }
contractGainRates(p: IPlayer, type: string, name: string): void { // contractGainRates(p: IPlayer, type: string, name: string): void {
const bb = p.bladeburner; // const bb = p.bladeburner;
if (bb === null) { // if (bb === null) {
const errorLogText = `bladeburner is null`; // const errorLogText = `bladeburner is null`;
console.error(`Function: sleeves.contractGainRates; Message: '${errorLogText}'`); // console.error(`Function: sleeves.contractGainRates; Message: '${errorLogText}'`);
return; // return;
} // }
const actionIdent = bb.getActionIdFromTypeAndName(type, name); // const actionIdent = bb.getActionIdFromTypeAndName(type, name);
if (actionIdent === null) { // if (actionIdent === null) {
const errorLogText = `Invalid action: type='${type}' name='${name}'`; // const errorLogText = `Invalid action: type='${type}' name='${name}'`;
console.error(`Function: sleeves.contractGainRates; Message: '${errorLogText}'`); // console.error(`Function: sleeves.contractGainRates; Message: '${errorLogText}'`);
this.resetTaskStatus(p); // this.resetTaskStatus(p);
return; // return;
} // }
const action = bb.getActionObject(actionIdent); // const action = bb.getActionObject(actionIdent);
if (action === null) { // if (action === null) {
const errorLogText = `Invalid action: type='${type}' name='${name}'`; // const errorLogText = `Invalid action: type='${type}' name='${name}'`;
console.error(`Function: sleeves.contractGainRates; Message: '${errorLogText}'`); // console.error(`Function: sleeves.contractGainRates; Message: '${errorLogText}'`);
this.resetTaskStatus(p); // this.resetTaskStatus(p);
return; // return;
} // }
const retValue = bb.getActionStats(action, true); // const retValue = bb.getActionStats(action, true);
this.gainRatesForTask.hack = retValue.hack; // this.gainRatesForTask.hack = retValue.hack;
this.gainRatesForTask.str = retValue.str; // this.gainRatesForTask.str = retValue.str;
this.gainRatesForTask.def = retValue.def; // this.gainRatesForTask.def = retValue.def;
this.gainRatesForTask.dex = retValue.dex; // this.gainRatesForTask.dex = retValue.dex;
this.gainRatesForTask.agi = retValue.agi; // this.gainRatesForTask.agi = retValue.agi;
this.gainRatesForTask.cha = retValue.cha; // this.gainRatesForTask.cha = retValue.cha;
const rewardMultiplier = Math.pow(action.rewardFac, action.level - 1); // const rewardMultiplier = Math.pow(action.rewardFac, action.level - 1);
this.gainRatesForTask.money = // this.gainRatesForTask.money =
BladeburnerConstants.ContractBaseMoneyGain * rewardMultiplier * bb.skillMultipliers.money; // BladeburnerConstants.ContractBaseMoneyGain * rewardMultiplier * bb.skillMultipliers.money;
} // }
getBladeburnerActionTime(p: IPlayer, type: string, name: string): number { getBladeburnerActionTime(p: IPlayer, type: string, name: string): number {
//Maybe find workerscript and use original //Maybe find workerscript and use original

@ -5,7 +5,6 @@ import { Work, WorkType } from "./Work";
import { CONSTANTS } from "../../../Constants"; import { CONSTANTS } from "../../../Constants";
import { GeneralActions } from "../../../Bladeburner/data/GeneralActions"; import { GeneralActions } from "../../../Bladeburner/data/GeneralActions";
import { applyWorkStatsExp, WorkStats } from "../../../Work/WorkStats"; import { applyWorkStatsExp, WorkStats } from "../../../Work/WorkStats";
import { Contracts } from "src/Bladeburner/data/Contracts";
interface SleeveBladeburnerWorkParams { interface SleeveBladeburnerWorkParams {
type: string; type: string;

@ -38,12 +38,16 @@ export class SleeveCrimeWork extends Work {
}); });
} }
cyclesNeeded(): number {
return this.getCrime().time / CONSTANTS._idleSpeed;
}
process(player: IPlayer, sleeve: Sleeve, cycles: number): number { process(player: IPlayer, sleeve: Sleeve, cycles: number): number {
this.cyclesWorked += cycles; this.cyclesWorked += cycles;
const crime = this.getCrime(); const crime = this.getCrime();
const gains = this.getExp(); const gains = this.getExp();
if (this.cyclesWorked >= crime.time / CONSTANTS._idleSpeed) { if (this.cyclesWorked >= this.cyclesNeeded()) {
if (Math.random() < crime.successRate(sleeve)) { if (Math.random() < crime.successRate(sleeve)) {
applyWorkStats(player, sleeve, gains, 1, "sleeves"); applyWorkStats(player, sleeve, gains, 1, "sleeves");
@ -51,7 +55,7 @@ export class SleeveCrimeWork extends Work {
} else { } else {
applyWorkStats(player, sleeve, scaleWorkStats(gains, 0.25), 1, "sleeves"); applyWorkStats(player, sleeve, scaleWorkStats(gains, 0.25), 1, "sleeves");
} }
this.cyclesWorked -= crime.time / CONSTANTS._idleSpeed; this.cyclesWorked -= this.cyclesNeeded();
} }
return 0; return 0;
} }

@ -1,58 +0,0 @@
import { Sleeve } from "../Sleeve";
import { numeralWrapper } from "../../../ui/numeralFormat";
import { Money } from "../../../ui/React/Money";
import * as React from "react";
import { StatsTable } from "../../../ui/React/StatsTable";
import { Modal } from "../../../ui/React/Modal";
interface IProps {
open: boolean;
onClose: () => void;
sleeve: Sleeve;
}
export function MoreEarningsModal(props: IProps): React.ReactElement {
return (
<Modal open={props.open} onClose={props.onClose}>
<StatsTable
rows={[
["Money ", <Money money={props.sleeve.earningsForTask.money} />],
["Hacking Exp ", numeralWrapper.formatExp(props.sleeve.earningsForTask.hack)],
["Strength Exp ", numeralWrapper.formatExp(props.sleeve.earningsForTask.str)],
["Defense Exp ", numeralWrapper.formatExp(props.sleeve.earningsForTask.def)],
["Dexterity Exp ", numeralWrapper.formatExp(props.sleeve.earningsForTask.dex)],
["Agility Exp ", numeralWrapper.formatExp(props.sleeve.earningsForTask.agi)],
["Charisma Exp ", numeralWrapper.formatExp(props.sleeve.earningsForTask.cha)],
]}
title="Earnings for Current Task:"
/>
<br />
<StatsTable
rows={[
["Money: ", <Money money={props.sleeve.earningsForPlayer.money} />],
["Hacking Exp: ", numeralWrapper.formatExp(props.sleeve.earningsForPlayer.hack)],
["Strength Exp: ", numeralWrapper.formatExp(props.sleeve.earningsForPlayer.str)],
["Defense Exp: ", numeralWrapper.formatExp(props.sleeve.earningsForPlayer.def)],
["Dexterity Exp: ", numeralWrapper.formatExp(props.sleeve.earningsForPlayer.dex)],
["Agility Exp: ", numeralWrapper.formatExp(props.sleeve.earningsForPlayer.agi)],
["Charisma Exp: ", numeralWrapper.formatExp(props.sleeve.earningsForPlayer.cha)],
]}
title="Total Earnings for Host Consciousness:"
/>
<br />
<StatsTable
rows={[
["Money: ", <Money money={props.sleeve.earningsForSleeves.money} />],
["Hacking Exp: ", numeralWrapper.formatExp(props.sleeve.earningsForSleeves.hack)],
["Strength Exp: ", numeralWrapper.formatExp(props.sleeve.earningsForSleeves.str)],
["Defense Exp: ", numeralWrapper.formatExp(props.sleeve.earningsForSleeves.def)],
["Dexterity Exp: ", numeralWrapper.formatExp(props.sleeve.earningsForSleeves.dex)],
["Agility Exp: ", numeralWrapper.formatExp(props.sleeve.earningsForSleeves.agi)],
["Charisma Exp: ", numeralWrapper.formatExp(props.sleeve.earningsForSleeves.cha)],
]}
title="Total Earnings for Other Sleeves:"
/>
<br />
</Modal>
);
}

@ -2,13 +2,10 @@ import { Box, Button, Paper, Tooltip, Typography } from "@mui/material";
import React, { useState } from "react"; import React, { useState } from "react";
import { FactionWorkType } from "../../../Work/data/FactionWorkType"; import { FactionWorkType } from "../../../Work/data/FactionWorkType";
import { CONSTANTS } from "../../../Constants"; import { CONSTANTS } from "../../../Constants";
import { Crimes } from "../../../Crime/Crimes";
import { use } from "../../../ui/Context"; import { use } from "../../../ui/Context";
import { numeralWrapper } from "../../../ui/numeralFormat"; import { numeralWrapper } from "../../../ui/numeralFormat";
import { ProgressBar } from "../../../ui/React/Progress"; import { ProgressBar } from "../../../ui/React/Progress";
import { Sleeve } from "../Sleeve"; import { Sleeve } from "../Sleeve";
import { SleeveTaskType } from "../SleeveTaskTypesEnum";
import { MoreEarningsModal } from "./MoreEarningsModal";
import { MoreStatsModal } from "./MoreStatsModal"; import { MoreStatsModal } from "./MoreStatsModal";
import { SleeveAugmentationsModal } from "./SleeveAugmentationsModal"; import { SleeveAugmentationsModal } from "./SleeveAugmentationsModal";
import { EarningsElement, StatsElement } from "./StatsElement"; import { EarningsElement, StatsElement } from "./StatsElement";
@ -32,7 +29,6 @@ interface IProps {
export function SleeveElem(props: IProps): React.ReactElement { export function SleeveElem(props: IProps): React.ReactElement {
const player = use.Player(); const player = use.Player();
const [statsOpen, setStatsOpen] = useState(false); const [statsOpen, setStatsOpen] = useState(false);
const [earningsOpen, setEarningsOpen] = useState(false);
const [travelOpen, setTravelOpen] = useState(false); const [travelOpen, setTravelOpen] = useState(false);
const [augmentationsOpen, setAugmentationsOpen] = useState(false); const [augmentationsOpen, setAugmentationsOpen] = useState(false);
@ -161,7 +157,6 @@ export function SleeveElem(props: IProps): React.ReactElement {
<StatsElement sleeve={props.sleeve} /> <StatsElement sleeve={props.sleeve} />
<Box display="grid" sx={{ gridTemplateColumns: "1fr 1fr", width: "100%" }}> <Box display="grid" sx={{ gridTemplateColumns: "1fr 1fr", width: "100%" }}>
<Button onClick={() => setStatsOpen(true)}>More Stats</Button> <Button onClick={() => setStatsOpen(true)}>More Stats</Button>
<Button onClick={() => setEarningsOpen(true)}>More Earnings Info</Button>
<Tooltip title={player.money < CONSTANTS.TravelCost ? <Typography>Insufficient funds</Typography> : ""}> <Tooltip title={player.money < CONSTANTS.TravelCost ? <Typography>Insufficient funds</Typography> : ""}>
<span> <span>
<Button <Button
@ -196,12 +191,21 @@ export function SleeveElem(props: IProps): React.ReactElement {
</Button> </Button>
<Typography>{desc}</Typography> <Typography>{desc}</Typography>
<Typography> <Typography>
{(props.sleeve.currentTask === SleeveTaskType.Crime || {isSleeveCrimeWork(props.sleeve.currentWork) && (
props.sleeve.currentTask === SleeveTaskType.Bladeburner) &&
props.sleeve.currentTaskMaxTime > 0 && (
<ProgressBar <ProgressBar
variant="determinate" variant="determinate"
value={(props.sleeve.currentTaskTime / props.sleeve.currentTaskMaxTime) * 100} value={(props.sleeve.currentWork.cyclesWorked / props.sleeve.currentWork.cyclesNeeded()) * 100}
color="primary"
/>
)}
{isSleeveBladeburnerWork(props.sleeve.currentWork) && (
<ProgressBar
variant="determinate"
value={
(props.sleeve.currentWork.cyclesWorked /
props.sleeve.currentWork.cyclesNeeded(player, props.sleeve)) *
100
}
color="primary" color="primary"
/> />
)} )}
@ -209,7 +213,6 @@ export function SleeveElem(props: IProps): React.ReactElement {
</span> </span>
</Paper> </Paper>
<MoreStatsModal open={statsOpen} onClose={() => setStatsOpen(false)} sleeve={props.sleeve} /> <MoreStatsModal open={statsOpen} onClose={() => setStatsOpen(false)} sleeve={props.sleeve} />
<MoreEarningsModal open={earningsOpen} onClose={() => setEarningsOpen(false)} sleeve={props.sleeve} />
<TravelModal <TravelModal
open={travelOpen} open={travelOpen}
onClose={() => setTravelOpen(false)} onClose={() => setTravelOpen(false)}

@ -1,7 +1,6 @@
import React, { useState } from "react"; import React, { useState } from "react";
import { Sleeve } from "../Sleeve"; import { Sleeve } from "../Sleeve";
import { IPlayer } from "../../IPlayer"; import { IPlayer } from "../../IPlayer";
import { SleeveTaskType } from "../SleeveTaskTypesEnum";
import { Crimes } from "../../../Crime/Crimes"; import { Crimes } from "../../../Crime/Crimes";
import { LocationName } from "../../../Locations/data/LocationNames"; import { LocationName } from "../../../Locations/data/LocationNames";
import { CityName } from "../../../Locations/data/CityNames"; import { CityName } from "../../../Locations/data/CityNames";
@ -9,7 +8,9 @@ import { Factions } from "../../../Faction/Factions";
import Select, { SelectChangeEvent } from "@mui/material/Select"; import Select, { SelectChangeEvent } from "@mui/material/Select";
import MenuItem from "@mui/material/MenuItem"; import MenuItem from "@mui/material/MenuItem";
import { FactionNames } from "../../../Faction/data/FactionNames"; import { FactionNames } from "../../../Faction/data/FactionNames";
import { FactionWorkType } from "../../../Work/data/FactionWorkType"; import { isSleeveFactionWork } from "../Work/SleeveFactionWork";
import { isSleeveCompanyWork } from "../Work/SleeveCompanyWork";
import { isSleeveBladeburnerWork } from "../Work/SleeveBladeburnerWork";
const universitySelectorOptions: string[] = [ const universitySelectorOptions: string[] = [
"Study Computer Science", "Study Computer Science",
@ -49,8 +50,8 @@ function possibleJobs(player: IPlayer, sleeve: Sleeve): string[] {
if (sleeve === otherSleeve) { if (sleeve === otherSleeve) {
continue; continue;
} }
if (otherSleeve.currentTask === SleeveTaskType.Company) { if (isSleeveCompanyWork(otherSleeve.currentWork)) {
forbiddenCompanies.push(otherSleeve.currentTaskLocation); forbiddenCompanies.push(otherSleeve.currentWork.companyName);
} }
} }
const allJobs: string[] = Object.keys(player.jobs); const allJobs: string[] = Object.keys(player.jobs);
@ -68,8 +69,8 @@ function possibleFactions(player: IPlayer, sleeve: Sleeve): string[] {
if (sleeve === otherSleeve) { if (sleeve === otherSleeve) {
continue; continue;
} }
if (otherSleeve.currentTask === SleeveTaskType.Faction) { if (isSleeveFactionWork(otherSleeve.currentWork)) {
forbiddenFactions.push(otherSleeve.currentTaskLocation); forbiddenFactions.push(otherSleeve.currentWork.factionName);
} }
} }
@ -98,8 +99,9 @@ function possibleContracts(player: IPlayer, sleeve: Sleeve): string[] {
if (sleeve === otherSleeve) { if (sleeve === otherSleeve) {
continue; continue;
} }
if (otherSleeve.currentTask === SleeveTaskType.Bladeburner && otherSleeve.bbAction == "Take on contracts") { if (isSleeveBladeburnerWork(otherSleeve.currentWork) && otherSleeve.currentWork.actionType === "Contracts") {
contracts = contracts.filter((x) => x != otherSleeve.bbContract); const w = otherSleeve.currentWork;
contracts = contracts.filter((x) => x != w.actionName);
} }
} }
if (contracts.length === 0) { if (contracts.length === 0) {
@ -241,51 +243,37 @@ const canDo: {
}; };
function getABC(sleeve: Sleeve): [string, string, string] { function getABC(sleeve: Sleeve): [string, string, string] {
switch (sleeve.currentTask) {
case SleeveTaskType.Idle:
return ["------", "------", "------"]; return ["------", "------", "------"];
case SleeveTaskType.Company:
return ["Work for Company", sleeve.currentTaskLocation, "------"]; // switch (sleeve.currentTask) {
case SleeveTaskType.Faction: { // case SleeveTaskType.Idle:
let workType = ""; // case SleeveTaskType.Company:
switch (sleeve.factionWorkType) { // case SleeveTaskType.Faction: {
case FactionWorkType.HACKING: // }
workType = "Hacking Contracts"; // case SleeveTaskType.Crime:
break; // return ["Commit Crime", sleeve.crimeType, "------"];
case FactionWorkType.FIELD: // case SleeveTaskType.Class:
workType = "Field Work"; // case SleeveTaskType.Gym: {
break; // switch (sleeve.gymStatType) {
case FactionWorkType.SECURITY: // case "none":
workType = "Security Work"; // return ["Idle", "------", "------"];
break; // case "str":
} // return ["Workout at Gym", "Train Strength", sleeve.currentTaskLocation];
return ["Work for Faction", sleeve.currentTaskLocation, workType]; // case "def":
} // return ["Workout at Gym", "Train Defense", sleeve.currentTaskLocation];
case SleeveTaskType.Crime: // case "dex":
return ["Commit Crime", sleeve.crimeType, "------"]; // return ["Workout at Gym", "Train Dexterity", sleeve.currentTaskLocation];
case SleeveTaskType.Class: // case "agi":
return ["Take University Course", sleeve.className, sleeve.currentTaskLocation]; // return ["Workout at Gym", "Train Agility", sleeve.currentTaskLocation];
case SleeveTaskType.Gym: { // }
switch (sleeve.gymStatType) { // }
case "none": // case SleeveTaskType.Bladeburner:
return ["Idle", "------", "------"]; // return ["Perform Bladeburner Actions", sleeve.bbAction, sleeve.bbContract];
case "str": // case SleeveTaskType.Recovery:
return ["Workout at Gym", "Train Strength", sleeve.currentTaskLocation]; // return ["Shock Recovery", "------", "------"];
case "def": // case SleeveTaskType.Synchro:
return ["Workout at Gym", "Train Defense", sleeve.currentTaskLocation]; // return ["Synchronize", "------", "------"];
case "dex": // }
return ["Workout at Gym", "Train Dexterity", sleeve.currentTaskLocation];
case "agi":
return ["Workout at Gym", "Train Agility", sleeve.currentTaskLocation];
}
}
case SleeveTaskType.Bladeburner:
return ["Perform Bladeburner Actions", sleeve.bbAction, sleeve.bbContract];
case SleeveTaskType.Recovery:
return ["Shock Recovery", "------", "------"];
case SleeveTaskType.Synchro:
return ["Synchronize", "------", "------"];
}
} }
export function TaskSelector(props: IProps): React.ReactElement { export function TaskSelector(props: IProps): React.ReactElement {

@ -1022,7 +1022,7 @@ export interface SleeveInformation {
* Object representing a sleeve current task. * Object representing a sleeve current task.
* @public * @public
*/ */
export interface SleeveTask = any; export type SleeveTask = any;
/** /**
* Object representing a port. A port is a serialized queue. * Object representing a port. A port is a serialized queue.