2021-09-10 03:38:05 +02:00
|
|
|
import React, { useState } from "react";
|
|
|
|
import { Sleeve } from "../Sleeve";
|
|
|
|
import { IPlayer } from "../../IPlayer";
|
|
|
|
import { SleeveTaskType } from "../SleeveTaskTypesEnum";
|
|
|
|
import { Crimes } from "../../../Crime/Crimes";
|
|
|
|
import { LocationName } from "../../../Locations/data/LocationNames";
|
|
|
|
import { CityName } from "../../../Locations/data/CityNames";
|
|
|
|
import { Factions } from "../../../Faction/Factions";
|
|
|
|
import { FactionWorkType } from "../../../Faction/FactionWorkTypeEnum";
|
2021-09-27 02:55:38 +02:00
|
|
|
import Select, { SelectChangeEvent } from "@mui/material/Select";
|
|
|
|
import MenuItem from "@mui/material/MenuItem";
|
2022-03-19 09:09:59 +01:00
|
|
|
import { FactionNames } from "../../../Faction/data/FactionNames";
|
2021-09-10 03:38:05 +02:00
|
|
|
|
|
|
|
const universitySelectorOptions: string[] = [
|
|
|
|
"Study Computer Science",
|
|
|
|
"Data Structures",
|
|
|
|
"Networks",
|
|
|
|
"Algorithms",
|
|
|
|
"Management",
|
|
|
|
"Leadership",
|
|
|
|
];
|
|
|
|
|
|
|
|
const gymSelectorOptions: string[] = ["Train Strength", "Train Defense", "Train Dexterity", "Train Agility"];
|
|
|
|
|
2022-04-14 18:00:17 +02:00
|
|
|
const bladeburnerSelectorOptions: string[] = [
|
|
|
|
"Field Analysis",
|
|
|
|
"Recruitment",
|
|
|
|
"Diplomacy",
|
|
|
|
"Infiltrate synthoids",
|
|
|
|
"Support main sleeve",
|
|
|
|
"Take on Contracts",
|
|
|
|
];
|
2022-04-14 17:40:59 +02:00
|
|
|
|
2021-09-10 03:38:05 +02:00
|
|
|
interface IProps {
|
|
|
|
sleeve: Sleeve;
|
|
|
|
player: IPlayer;
|
|
|
|
setABC: (abc: string[]) => void;
|
|
|
|
}
|
|
|
|
|
|
|
|
interface ITaskDetails {
|
|
|
|
first: string[];
|
|
|
|
second: (s1: string) => string[];
|
|
|
|
}
|
|
|
|
|
|
|
|
function possibleJobs(player: IPlayer, sleeve: Sleeve): string[] {
|
|
|
|
// Array of all companies that other sleeves are working at
|
|
|
|
const forbiddenCompanies = [];
|
|
|
|
for (const otherSleeve of player.sleeves) {
|
|
|
|
if (sleeve === otherSleeve) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (otherSleeve.currentTask === SleeveTaskType.Company) {
|
|
|
|
forbiddenCompanies.push(otherSleeve.currentTaskLocation);
|
|
|
|
}
|
|
|
|
}
|
2021-09-10 04:57:37 +02:00
|
|
|
const allJobs: string[] = Object.keys(player.jobs);
|
2021-09-10 03:38:05 +02:00
|
|
|
for (let i = 0; i < allJobs.length; ++i) {
|
|
|
|
if (!forbiddenCompanies.includes(allJobs[i])) {
|
|
|
|
allJobs[i];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return allJobs;
|
|
|
|
}
|
|
|
|
|
|
|
|
function possibleFactions(player: IPlayer, sleeve: Sleeve): string[] {
|
|
|
|
// Array of all factions that other sleeves are working for
|
2022-04-22 21:30:49 +02:00
|
|
|
const forbiddenFactions = [FactionNames.Bladeburners as string, FactionNames.ShadowsOfAnarchy as string];
|
2021-09-11 07:54:19 +02:00
|
|
|
if (player.gang) {
|
|
|
|
forbiddenFactions.push(player.gang.facName);
|
|
|
|
}
|
2021-09-10 03:38:05 +02:00
|
|
|
for (const otherSleeve of player.sleeves) {
|
|
|
|
if (sleeve === otherSleeve) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (otherSleeve.currentTask === SleeveTaskType.Faction) {
|
|
|
|
forbiddenFactions.push(otherSleeve.currentTaskLocation);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const factions = [];
|
|
|
|
for (const fac of player.factions) {
|
|
|
|
if (!forbiddenFactions.includes(fac)) {
|
|
|
|
factions.push(fac);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-04-07 01:30:08 +02:00
|
|
|
return factions.filter((faction) => {
|
2022-02-07 12:48:28 +01:00
|
|
|
const facInfo = Factions[faction].getInfo();
|
2022-04-07 01:30:08 +02:00
|
|
|
return facInfo.offerHackingWork || facInfo.offerFieldWork || facInfo.offerSecurityWork;
|
2022-02-07 12:48:28 +01:00
|
|
|
});
|
2021-09-10 03:38:05 +02:00
|
|
|
}
|
|
|
|
|
2022-04-14 17:40:59 +02:00
|
|
|
function possibleContracts(player: IPlayer, sleeve: Sleeve): string[] {
|
|
|
|
const bb = player.bladeburner;
|
2022-04-14 18:00:17 +02:00
|
|
|
if (bb === null) {
|
2022-04-14 17:40:59 +02:00
|
|
|
return ["------"];
|
|
|
|
}
|
|
|
|
let contracts = bb.getContractNamesNetscriptFn();
|
|
|
|
for (const otherSleeve of player.sleeves) {
|
|
|
|
if (sleeve === otherSleeve) {
|
|
|
|
continue;
|
|
|
|
}
|
2022-04-14 18:00:17 +02:00
|
|
|
if (otherSleeve.currentTask === SleeveTaskType.Bladeburner && otherSleeve.bbAction == "Take on Contracts") {
|
|
|
|
contracts = contracts.filter((x) => x != otherSleeve.bbContract);
|
2022-04-14 17:40:59 +02:00
|
|
|
}
|
|
|
|
}
|
2022-04-14 18:00:17 +02:00
|
|
|
if (contracts.length === 0) {
|
2022-04-14 17:40:59 +02:00
|
|
|
return ["------"];
|
|
|
|
}
|
|
|
|
return contracts;
|
|
|
|
}
|
|
|
|
|
2021-09-10 03:38:05 +02:00
|
|
|
const tasks: {
|
|
|
|
[key: string]: undefined | ((player: IPlayer, sleeve: Sleeve) => ITaskDetails);
|
|
|
|
["------"]: (player: IPlayer, sleeve: Sleeve) => ITaskDetails;
|
|
|
|
["Work for Company"]: (player: IPlayer, sleeve: Sleeve) => ITaskDetails;
|
|
|
|
["Work for Faction"]: (player: IPlayer, sleeve: Sleeve) => ITaskDetails;
|
|
|
|
["Commit Crime"]: (player: IPlayer, sleeve: Sleeve) => ITaskDetails;
|
|
|
|
["Take University Course"]: (player: IPlayer, sleeve: Sleeve) => ITaskDetails;
|
|
|
|
["Workout at Gym"]: (player: IPlayer, sleeve: Sleeve) => ITaskDetails;
|
2022-04-14 17:40:59 +02:00
|
|
|
["Perform Bladeburner Actions"]: (player: IPlayer, sleeve: Sleeve) => ITaskDetails;
|
2021-09-10 03:38:05 +02:00
|
|
|
["Shock Recovery"]: (player: IPlayer, sleeve: Sleeve) => ITaskDetails;
|
|
|
|
["Synchronize"]: (player: IPlayer, sleeve: Sleeve) => ITaskDetails;
|
|
|
|
} = {
|
2021-09-10 04:57:37 +02:00
|
|
|
"------": (): ITaskDetails => {
|
2021-09-10 03:38:05 +02:00
|
|
|
return { first: ["------"], second: () => ["------"] };
|
|
|
|
},
|
|
|
|
"Work for Company": (player: IPlayer, sleeve: Sleeve): ITaskDetails => {
|
|
|
|
let jobs = possibleJobs(player, sleeve);
|
|
|
|
|
|
|
|
if (jobs.length === 0) jobs = ["------"];
|
|
|
|
return { first: jobs, second: () => ["------"] };
|
|
|
|
},
|
|
|
|
"Work for Faction": (player: IPlayer, sleeve: Sleeve): ITaskDetails => {
|
|
|
|
let factions = possibleFactions(player, sleeve);
|
|
|
|
if (factions.length === 0) factions = ["------"];
|
|
|
|
|
|
|
|
return {
|
|
|
|
first: factions,
|
|
|
|
second: (s1: string) => {
|
|
|
|
const faction = Factions[s1];
|
2022-04-25 03:38:07 +02:00
|
|
|
if (!faction) return ["------"];
|
|
|
|
|
2021-09-10 03:38:05 +02:00
|
|
|
const facInfo = faction.getInfo();
|
|
|
|
const options: string[] = [];
|
|
|
|
if (facInfo.offerHackingWork) {
|
|
|
|
options.push("Hacking Contracts");
|
|
|
|
}
|
|
|
|
if (facInfo.offerFieldWork) {
|
|
|
|
options.push("Field Work");
|
|
|
|
}
|
|
|
|
if (facInfo.offerSecurityWork) {
|
|
|
|
options.push("Security Work");
|
|
|
|
}
|
|
|
|
return options;
|
|
|
|
},
|
|
|
|
};
|
|
|
|
},
|
2021-09-10 04:57:37 +02:00
|
|
|
"Commit Crime": (): ITaskDetails => {
|
2021-10-18 21:01:06 +02:00
|
|
|
return { first: Object.values(Crimes).map((crime) => crime.name), second: () => ["------"] };
|
2021-09-10 03:38:05 +02:00
|
|
|
},
|
|
|
|
"Take University Course": (player: IPlayer, sleeve: Sleeve): ITaskDetails => {
|
|
|
|
let universities: string[] = [];
|
|
|
|
switch (sleeve.city) {
|
|
|
|
case CityName.Aevum:
|
|
|
|
universities = [LocationName.AevumSummitUniversity];
|
|
|
|
break;
|
|
|
|
case CityName.Sector12:
|
|
|
|
universities = [LocationName.Sector12RothmanUniversity];
|
|
|
|
break;
|
|
|
|
case CityName.Volhaven:
|
|
|
|
universities = [LocationName.VolhavenZBInstituteOfTechnology];
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
universities = ["No university available in city!"];
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return { first: universitySelectorOptions, second: () => universities };
|
|
|
|
},
|
|
|
|
"Workout at Gym": (player: IPlayer, sleeve: Sleeve): ITaskDetails => {
|
|
|
|
let gyms: string[] = [];
|
|
|
|
switch (sleeve.city) {
|
|
|
|
case CityName.Aevum:
|
|
|
|
gyms = [LocationName.AevumCrushFitnessGym, LocationName.AevumSnapFitnessGym];
|
|
|
|
break;
|
|
|
|
case CityName.Sector12:
|
|
|
|
gyms = [LocationName.Sector12IronGym, LocationName.Sector12PowerhouseGym];
|
|
|
|
break;
|
|
|
|
case CityName.Volhaven:
|
|
|
|
gyms = [LocationName.VolhavenMilleniumFitnessGym];
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
gyms = ["No gym available in city!"];
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return { first: gymSelectorOptions, second: () => gyms };
|
|
|
|
},
|
2022-04-14 17:40:59 +02:00
|
|
|
"Perform Bladeburner Actions": (player: IPlayer, sleeve: Sleeve): ITaskDetails => {
|
2022-04-14 17:57:01 +02:00
|
|
|
return {
|
|
|
|
first: bladeburnerSelectorOptions,
|
2022-04-14 17:40:59 +02:00
|
|
|
second: (s1: string) => {
|
2022-04-14 18:00:17 +02:00
|
|
|
if (s1 === "Take on Contracts") {
|
2022-04-14 17:40:59 +02:00
|
|
|
return possibleContracts(player, sleeve);
|
|
|
|
} else {
|
|
|
|
return ["------"];
|
|
|
|
}
|
2022-04-14 18:00:17 +02:00
|
|
|
},
|
|
|
|
};
|
2022-04-14 17:40:59 +02:00
|
|
|
},
|
2021-09-10 04:57:37 +02:00
|
|
|
"Shock Recovery": (): ITaskDetails => {
|
2021-09-10 03:38:05 +02:00
|
|
|
return { first: ["------"], second: () => ["------"] };
|
|
|
|
},
|
2021-09-10 04:57:37 +02:00
|
|
|
Synchronize: (): ITaskDetails => {
|
2021-09-10 03:38:05 +02:00
|
|
|
return { first: ["------"], second: () => ["------"] };
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
|
|
|
const canDo: {
|
|
|
|
[key: string]: undefined | ((player: IPlayer, sleeve: Sleeve) => boolean);
|
|
|
|
["------"]: (player: IPlayer, sleeve: Sleeve) => boolean;
|
|
|
|
["Work for Company"]: (player: IPlayer, sleeve: Sleeve) => boolean;
|
|
|
|
["Work for Faction"]: (player: IPlayer, sleeve: Sleeve) => boolean;
|
|
|
|
["Commit Crime"]: (player: IPlayer, sleeve: Sleeve) => boolean;
|
|
|
|
["Take University Course"]: (player: IPlayer, sleeve: Sleeve) => boolean;
|
|
|
|
["Workout at Gym"]: (player: IPlayer, sleeve: Sleeve) => boolean;
|
2022-04-14 17:40:59 +02:00
|
|
|
["Perform Bladeburner Actions"]: (player: IPlayer, sleeve: Sleeve) => boolean;
|
2021-09-10 03:38:05 +02:00
|
|
|
["Shock Recovery"]: (player: IPlayer, sleeve: Sleeve) => boolean;
|
|
|
|
["Synchronize"]: (player: IPlayer, sleeve: Sleeve) => boolean;
|
|
|
|
} = {
|
2021-09-10 04:57:37 +02:00
|
|
|
"------": () => true,
|
|
|
|
"Work for Company": (player: IPlayer, sleeve: Sleeve) => possibleJobs(player, sleeve).length > 0,
|
|
|
|
"Work for Faction": (player: IPlayer, sleeve: Sleeve) => possibleFactions(player, sleeve).length > 0,
|
|
|
|
"Commit Crime": () => true,
|
2021-09-22 18:56:55 +02:00
|
|
|
"Take University Course": (player: IPlayer, sleeve: Sleeve) =>
|
|
|
|
[CityName.Aevum, CityName.Sector12, CityName.Volhaven].includes(sleeve.city),
|
|
|
|
"Workout at Gym": (player: IPlayer, sleeve: Sleeve) =>
|
|
|
|
[CityName.Aevum, CityName.Sector12, CityName.Volhaven].includes(sleeve.city),
|
2022-04-14 21:28:13 +02:00
|
|
|
"Perform Bladeburner Actions": (player: IPlayer, _: Sleeve) => player.inBladeburner(),
|
2021-09-10 04:57:37 +02:00
|
|
|
"Shock Recovery": (player: IPlayer, sleeve: Sleeve) => sleeve.shock < 100,
|
|
|
|
Synchronize: (player: IPlayer, sleeve: Sleeve) => sleeve.sync < 100,
|
2021-09-10 03:38:05 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
function getABC(sleeve: Sleeve): [string, string, string] {
|
|
|
|
switch (sleeve.currentTask) {
|
|
|
|
case SleeveTaskType.Idle:
|
|
|
|
return ["------", "------", "------"];
|
|
|
|
case SleeveTaskType.Company:
|
|
|
|
return ["Work for Company", sleeve.currentTaskLocation, "------"];
|
2021-09-10 04:57:37 +02:00
|
|
|
case SleeveTaskType.Faction: {
|
2021-09-10 03:38:05 +02:00
|
|
|
let workType = "";
|
|
|
|
switch (sleeve.factionWorkType) {
|
|
|
|
case FactionWorkType.Hacking:
|
|
|
|
workType = "Hacking Contracts";
|
|
|
|
break;
|
|
|
|
case FactionWorkType.Field:
|
|
|
|
workType = "Field Work";
|
|
|
|
break;
|
|
|
|
case FactionWorkType.Security:
|
|
|
|
workType = "Security Work";
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return ["Work for Faction", sleeve.currentTaskLocation, workType];
|
2021-09-10 04:57:37 +02:00
|
|
|
}
|
2021-09-10 03:38:05 +02:00
|
|
|
case SleeveTaskType.Crime:
|
|
|
|
return ["Commit Crime", sleeve.crimeType, "------"];
|
|
|
|
case SleeveTaskType.Class:
|
|
|
|
return ["Take University Course", sleeve.className, sleeve.currentTaskLocation];
|
|
|
|
case SleeveTaskType.Gym:
|
|
|
|
return ["Workout at Gym", sleeve.gymStatType, sleeve.currentTaskLocation];
|
2022-04-14 17:40:59 +02:00
|
|
|
case SleeveTaskType.Bladeburner:
|
|
|
|
return ["Perform Bladeburner Actions", sleeve.bbAction, sleeve.bbContract];
|
2021-09-10 03:38:05 +02:00
|
|
|
case SleeveTaskType.Recovery:
|
|
|
|
return ["Shock Recovery", "------", "------"];
|
|
|
|
case SleeveTaskType.Synchro:
|
|
|
|
return ["Synchronize", "------", "------"];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
export function TaskSelector(props: IProps): React.ReactElement {
|
|
|
|
const abc = getABC(props.sleeve);
|
|
|
|
const [s0, setS0] = useState(abc[0]);
|
|
|
|
const [s1, setS1] = useState(abc[1]);
|
|
|
|
const [s2, setS2] = useState(abc[2]);
|
|
|
|
|
2021-09-22 18:56:55 +02:00
|
|
|
const validActions = Object.keys(canDo).filter((k) =>
|
|
|
|
(canDo[k] as (player: IPlayer, sleeve: Sleeve) => boolean)(props.player, props.sleeve),
|
2021-09-10 03:38:05 +02:00
|
|
|
);
|
|
|
|
|
|
|
|
const detailsF = tasks[s0];
|
|
|
|
if (detailsF === undefined) throw new Error(`No function for task '${s0}'`);
|
|
|
|
const details = detailsF(props.player, props.sleeve);
|
|
|
|
const details2 = details.second(s1);
|
|
|
|
|
2021-09-11 07:54:19 +02:00
|
|
|
if (details.first.length > 0 && !details.first.includes(s1)) {
|
|
|
|
setS1(details.first[0]);
|
|
|
|
props.setABC([s0, details.first[0], s2]);
|
|
|
|
}
|
|
|
|
if (details2.length > 0 && !details2.includes(s2)) {
|
|
|
|
setS2(details2[0]);
|
|
|
|
props.setABC([s0, s1, details2[0]]);
|
|
|
|
}
|
|
|
|
|
2021-09-27 02:55:38 +02:00
|
|
|
function onS0Change(event: SelectChangeEvent<string>): void {
|
2021-09-10 03:38:05 +02:00
|
|
|
const n = event.target.value;
|
|
|
|
const detailsF = tasks[n];
|
|
|
|
if (detailsF === undefined) throw new Error(`No function for task '${s0}'`);
|
|
|
|
const details = detailsF(props.player, props.sleeve);
|
2022-04-25 03:38:07 +02:00
|
|
|
const details2 = details.second(details.first[0]) ?? ["------"];
|
2021-09-10 03:38:05 +02:00
|
|
|
setS2(details2[0]);
|
|
|
|
setS1(details.first[0]);
|
|
|
|
setS0(n);
|
|
|
|
props.setABC([n, details.first[0], details2[0]]);
|
|
|
|
}
|
|
|
|
|
2021-09-27 02:55:38 +02:00
|
|
|
function onS1Change(event: SelectChangeEvent<string>): void {
|
2021-09-10 03:38:05 +02:00
|
|
|
setS1(event.target.value);
|
|
|
|
props.setABC([s0, event.target.value, s2]);
|
|
|
|
}
|
|
|
|
|
2021-09-27 02:55:38 +02:00
|
|
|
function onS2Change(event: SelectChangeEvent<string>): void {
|
2021-09-10 03:38:05 +02:00
|
|
|
setS2(event.target.value);
|
|
|
|
props.setABC([s0, s1, event.target.value]);
|
|
|
|
}
|
|
|
|
|
|
|
|
return (
|
|
|
|
<>
|
2022-04-07 01:30:08 +02:00
|
|
|
<Select onChange={onS0Change} value={s0} sx={{ width: "100%" }}>
|
2021-09-10 03:38:05 +02:00
|
|
|
{validActions.map((task) => (
|
2021-09-27 02:55:38 +02:00
|
|
|
<MenuItem key={task} value={task}>
|
2021-09-10 03:38:05 +02:00
|
|
|
{task}
|
2021-09-27 02:55:38 +02:00
|
|
|
</MenuItem>
|
2021-09-10 03:38:05 +02:00
|
|
|
))}
|
2021-09-27 02:55:38 +02:00
|
|
|
</Select>
|
2021-09-10 03:38:05 +02:00
|
|
|
{!(details.first.length === 1 && details.first[0] === "------") && (
|
2021-09-27 02:55:38 +02:00
|
|
|
<>
|
2022-04-07 01:30:08 +02:00
|
|
|
<Select onChange={onS1Change} value={s1} sx={{ width: "100%" }}>
|
2021-09-27 02:55:38 +02:00
|
|
|
{details.first.map((detail) => (
|
|
|
|
<MenuItem key={detail} value={detail}>
|
|
|
|
{detail}
|
|
|
|
</MenuItem>
|
|
|
|
))}
|
|
|
|
</Select>
|
|
|
|
</>
|
2021-09-10 03:38:05 +02:00
|
|
|
)}
|
|
|
|
{!(details2.length === 1 && details2[0] === "------") && (
|
2021-09-27 02:55:38 +02:00
|
|
|
<>
|
2022-04-07 01:30:08 +02:00
|
|
|
<Select onChange={onS2Change} value={s2} sx={{ width: "100%" }}>
|
2021-09-27 02:55:38 +02:00
|
|
|
{details2.map((detail) => (
|
|
|
|
<MenuItem key={detail} value={detail}>
|
|
|
|
{detail}
|
|
|
|
</MenuItem>
|
|
|
|
))}
|
|
|
|
</Select>
|
|
|
|
</>
|
2021-09-10 03:38:05 +02:00
|
|
|
)}
|
|
|
|
</>
|
|
|
|
);
|
|
|
|
}
|