mirror of
https://github.com/bitburner-official/bitburner-src.git
synced 2026-05-19 06:02:06 +02:00
commit1
This commit is contained in:
@@ -1,47 +1,47 @@
|
||||
import { CONSTANTS } from "../../Constants";
|
||||
|
||||
import { IPlayer } from "../IPlayer";
|
||||
import { Player } from "../../Player";
|
||||
import { Multipliers } from "../Multipliers";
|
||||
|
||||
export const calculateEntropy = (player: IPlayer, stacks = 1): Multipliers => {
|
||||
export const calculateEntropy = (stacks = 1): Multipliers => {
|
||||
const nerf = CONSTANTS.EntropyEffect ** stacks;
|
||||
return {
|
||||
hacking_chance: player.mults.hacking_chance * nerf,
|
||||
hacking_speed: player.mults.hacking_speed * nerf,
|
||||
hacking_money: player.mults.hacking_money * nerf,
|
||||
hacking_grow: player.mults.hacking_grow * nerf,
|
||||
hacking_chance: Player.mults.hacking_chance * nerf,
|
||||
hacking_speed: Player.mults.hacking_speed * nerf,
|
||||
hacking_money: Player.mults.hacking_money * nerf,
|
||||
hacking_grow: Player.mults.hacking_grow * nerf,
|
||||
|
||||
hacking: player.mults.hacking * nerf,
|
||||
strength: player.mults.strength * nerf,
|
||||
defense: player.mults.defense * nerf,
|
||||
dexterity: player.mults.dexterity * nerf,
|
||||
agility: player.mults.agility * nerf,
|
||||
charisma: player.mults.charisma * nerf,
|
||||
hacking: Player.mults.hacking * nerf,
|
||||
strength: Player.mults.strength * nerf,
|
||||
defense: Player.mults.defense * nerf,
|
||||
dexterity: Player.mults.dexterity * nerf,
|
||||
agility: Player.mults.agility * nerf,
|
||||
charisma: Player.mults.charisma * nerf,
|
||||
|
||||
hacking_exp: player.mults.hacking_exp * nerf,
|
||||
strength_exp: player.mults.strength_exp * nerf,
|
||||
defense_exp: player.mults.defense_exp * nerf,
|
||||
dexterity_exp: player.mults.dexterity_exp * nerf,
|
||||
agility_exp: player.mults.agility_exp * nerf,
|
||||
charisma_exp: player.mults.charisma_exp * nerf,
|
||||
hacking_exp: Player.mults.hacking_exp * nerf,
|
||||
strength_exp: Player.mults.strength_exp * nerf,
|
||||
defense_exp: Player.mults.defense_exp * nerf,
|
||||
dexterity_exp: Player.mults.dexterity_exp * nerf,
|
||||
agility_exp: Player.mults.agility_exp * nerf,
|
||||
charisma_exp: Player.mults.charisma_exp * nerf,
|
||||
|
||||
company_rep: player.mults.company_rep * nerf,
|
||||
faction_rep: player.mults.faction_rep * nerf,
|
||||
company_rep: Player.mults.company_rep * nerf,
|
||||
faction_rep: Player.mults.faction_rep * nerf,
|
||||
|
||||
crime_money: player.mults.crime_money * nerf,
|
||||
crime_success: player.mults.crime_success * nerf,
|
||||
crime_money: Player.mults.crime_money * nerf,
|
||||
crime_success: Player.mults.crime_success * nerf,
|
||||
|
||||
hacknet_node_money: player.mults.hacknet_node_money * nerf,
|
||||
hacknet_node_purchase_cost: player.mults.hacknet_node_purchase_cost * nerf,
|
||||
hacknet_node_ram_cost: player.mults.hacknet_node_ram_cost * nerf,
|
||||
hacknet_node_core_cost: player.mults.hacknet_node_core_cost * nerf,
|
||||
hacknet_node_level_cost: player.mults.hacknet_node_level_cost * nerf,
|
||||
hacknet_node_money: Player.mults.hacknet_node_money * nerf,
|
||||
hacknet_node_purchase_cost: Player.mults.hacknet_node_purchase_cost * nerf,
|
||||
hacknet_node_ram_cost: Player.mults.hacknet_node_ram_cost * nerf,
|
||||
hacknet_node_core_cost: Player.mults.hacknet_node_core_cost * nerf,
|
||||
hacknet_node_level_cost: Player.mults.hacknet_node_level_cost * nerf,
|
||||
|
||||
work_money: player.mults.work_money * nerf,
|
||||
work_money: Player.mults.work_money * nerf,
|
||||
|
||||
bladeburner_max_stamina: player.mults.bladeburner_max_stamina * nerf,
|
||||
bladeburner_stamina_gain: player.mults.bladeburner_stamina_gain * nerf,
|
||||
bladeburner_analysis: player.mults.bladeburner_analysis * nerf,
|
||||
bladeburner_success_chance: player.mults.bladeburner_success_chance * nerf,
|
||||
bladeburner_max_stamina: Player.mults.bladeburner_max_stamina * nerf,
|
||||
bladeburner_stamina_gain: Player.mults.bladeburner_stamina_gain * nerf,
|
||||
bladeburner_analysis: Player.mults.bladeburner_analysis * nerf,
|
||||
bladeburner_success_chance: Player.mults.bladeburner_success_chance * nerf,
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { StaticAugmentations } from "../../Augmentation/StaticAugmentations";
|
||||
import { GraftableAugmentation } from "./GraftableAugmentation";
|
||||
import { IPlayer } from "../IPlayer";
|
||||
import { Player } from "../../Player";
|
||||
|
||||
export const getGraftingAvailableAugs = (player: IPlayer): string[] => {
|
||||
export const getGraftingAvailableAugs = (): string[] => {
|
||||
const augs: string[] = [];
|
||||
|
||||
for (const [augName, aug] of Object.entries(StaticAugmentations)) {
|
||||
@@ -10,14 +10,14 @@ export const getGraftingAvailableAugs = (player: IPlayer): string[] => {
|
||||
augs.push(augName);
|
||||
}
|
||||
|
||||
return augs.filter((augmentation: string) => !player.hasAugmentation(augmentation));
|
||||
return augs.filter((augmentation: string) => !Player.hasAugmentation(augmentation));
|
||||
};
|
||||
|
||||
export const graftingIntBonus = (player: IPlayer): number => {
|
||||
return 1 + (player.getIntelligenceBonus(3) - 1) / 3;
|
||||
export const graftingIntBonus = (): number => {
|
||||
return 1 + (Player.getIntelligenceBonus(3) - 1) / 3;
|
||||
};
|
||||
|
||||
export const calculateGraftingTimeWithBonus = (player: IPlayer, aug: GraftableAugmentation): number => {
|
||||
export const calculateGraftingTimeWithBonus = (aug: GraftableAugmentation): number => {
|
||||
const baseTime = aug.time;
|
||||
return baseTime / graftingIntBonus(player);
|
||||
return baseTime / graftingIntBonus();
|
||||
};
|
||||
|
||||
@@ -11,11 +11,11 @@ import { LocationName } from "../../../Locations/data/LocationNames";
|
||||
import { Locations } from "../../../Locations/Locations";
|
||||
import { PurchaseAugmentationsOrderSetting } from "../../../Settings/SettingEnums";
|
||||
import { Settings } from "../../../Settings/Settings";
|
||||
import { use } from "../../../ui/Context";
|
||||
import { Router } from "../../../ui/GameRoot";
|
||||
import { ConfirmationModal } from "../../../ui/React/ConfirmationModal";
|
||||
import { Money } from "../../../ui/React/Money";
|
||||
import { convertTimeMsToTimeElapsedString, formatNumber } from "../../../utils/StringHelperFunctions";
|
||||
import { IPlayer } from "../../IPlayer";
|
||||
import { Player } from "../../../Player";
|
||||
import { GraftableAugmentation } from "../GraftableAugmentation";
|
||||
import { calculateGraftingTimeWithBonus, getGraftingAvailableAugs } from "../GraftingHelpers";
|
||||
|
||||
@@ -29,21 +29,19 @@ export const GraftableAugmentations = (): Record<string, GraftableAugmentation>
|
||||
return gAugs;
|
||||
};
|
||||
|
||||
const canGraft = (player: IPlayer, aug: GraftableAugmentation): boolean => {
|
||||
if (player.money < aug.cost) {
|
||||
const canGraft = (aug: GraftableAugmentation): boolean => {
|
||||
if (Player.money < aug.cost) {
|
||||
return false;
|
||||
}
|
||||
return hasAugmentationPrereqs(aug.augmentation);
|
||||
};
|
||||
|
||||
interface IProps {
|
||||
player: IPlayer;
|
||||
aug: Augmentation;
|
||||
}
|
||||
|
||||
const AugPreReqsChecklist = (props: IProps): React.ReactElement => {
|
||||
const aug = props.aug,
|
||||
player = props.player;
|
||||
const aug = props.aug;
|
||||
|
||||
return (
|
||||
<Typography color={Settings.theme.money}>
|
||||
@@ -51,7 +49,7 @@ const AugPreReqsChecklist = (props: IProps): React.ReactElement => {
|
||||
<br />
|
||||
{aug.prereqs.map((preAug) => (
|
||||
<span style={{ display: "flex", alignItems: "center" }}>
|
||||
{player.hasAugmentation(preAug) ? <CheckBox sx={{ mr: 1 }} /> : <CheckBoxOutlineBlank sx={{ mr: 1 }} />}
|
||||
{Player.hasAugmentation(preAug) ? <CheckBox sx={{ mr: 1 }} /> : <CheckBoxOutlineBlank sx={{ mr: 1 }} />}
|
||||
{preAug}
|
||||
</span>
|
||||
))}
|
||||
@@ -60,12 +58,9 @@ const AugPreReqsChecklist = (props: IProps): React.ReactElement => {
|
||||
};
|
||||
|
||||
export const GraftingRoot = (): React.ReactElement => {
|
||||
const player = use.Player();
|
||||
const router = use.Router();
|
||||
|
||||
const graftableAugmentations = useState(GraftableAugmentations())[0];
|
||||
|
||||
const [selectedAug, setSelectedAug] = useState(getGraftingAvailableAugs(player)[0]);
|
||||
const [selectedAug, setSelectedAug] = useState(getGraftingAvailableAugs()[0]);
|
||||
const [graftOpen, setGraftOpen] = useState(false);
|
||||
const selectedAugmentation = StaticAugmentations[selectedAug];
|
||||
|
||||
@@ -75,7 +70,7 @@ export const GraftingRoot = (): React.ReactElement => {
|
||||
}
|
||||
|
||||
const getAugsSorted = (): string[] => {
|
||||
const augs = getGraftingAvailableAugs(player);
|
||||
const augs = getGraftingAvailableAugs();
|
||||
switch (Settings.PurchaseAugmentationsOrder) {
|
||||
case PurchaseAugmentationsOrderSetting.Cost:
|
||||
return augs.sort((a, b) => graftableAugmentations[a].cost - graftableAugmentations[b].cost);
|
||||
@@ -96,7 +91,7 @@ export const GraftingRoot = (): React.ReactElement => {
|
||||
|
||||
return (
|
||||
<Container disableGutters maxWidth="lg" sx={{ mx: 0 }}>
|
||||
<Button onClick={() => router.toLocation(Locations[LocationName.NewTokyoVitaLife])}>Back</Button>
|
||||
<Button onClick={() => Router.toLocation(Locations[LocationName.NewTokyoVitaLife])}>Back</Button>
|
||||
<Typography variant="h4">Grafting Laboratory</Typography>
|
||||
<Typography>
|
||||
You find yourself in a secret laboratory, owned by a mysterious researcher.
|
||||
@@ -122,14 +117,14 @@ export const GraftingRoot = (): React.ReactElement => {
|
||||
</Button>
|
||||
</Box>
|
||||
</Paper>
|
||||
{getGraftingAvailableAugs(player).length > 0 ? (
|
||||
{getGraftingAvailableAugs().length > 0 ? (
|
||||
<Paper sx={{ mb: 1, width: "fit-content", display: "grid", gridTemplateColumns: "1fr 3fr" }}>
|
||||
<List sx={{ height: 400, overflowY: "scroll", borderRight: `1px solid ${Settings.theme.welllight}` }}>
|
||||
{getAugsSorted().map((k, i) => (
|
||||
<ListItemButton key={i + 1} onClick={() => setSelectedAug(k)} selected={selectedAug === k}>
|
||||
<Typography
|
||||
sx={{
|
||||
color: canGraft(player, graftableAugmentations[k])
|
||||
color: canGraft(graftableAugmentations[k])
|
||||
? Settings.theme.primary
|
||||
: Settings.theme.disabled,
|
||||
}}
|
||||
@@ -146,11 +141,11 @@ export const GraftingRoot = (): React.ReactElement => {
|
||||
<Button
|
||||
onClick={() => setGraftOpen(true)}
|
||||
sx={{ width: "100%" }}
|
||||
disabled={!canGraft(player, graftableAugmentations[selectedAug])}
|
||||
disabled={!canGraft(graftableAugmentations[selectedAug])}
|
||||
>
|
||||
Graft Augmentation (
|
||||
<Typography>
|
||||
<Money money={graftableAugmentations[selectedAug].cost} player={player} />
|
||||
<Money money={graftableAugmentations[selectedAug].cost} forPurchase={true} />
|
||||
</Typography>
|
||||
)
|
||||
</Button>
|
||||
@@ -158,21 +153,20 @@ export const GraftingRoot = (): React.ReactElement => {
|
||||
open={graftOpen}
|
||||
onClose={() => setGraftOpen(false)}
|
||||
onConfirm={() => {
|
||||
player.startWork(
|
||||
Player.startWork(
|
||||
new GraftingWork({
|
||||
augmentation: selectedAug,
|
||||
singularity: false,
|
||||
player: player,
|
||||
}),
|
||||
);
|
||||
player.startFocusing();
|
||||
router.toWork();
|
||||
Player.startFocusing();
|
||||
Router.toWork();
|
||||
}}
|
||||
confirmationText={
|
||||
<>
|
||||
Cancelling grafting will <b>not</b> save grafting progress, and the money you spend will <b>not</b>{" "}
|
||||
be returned.
|
||||
{!player.hasAugmentation(AugmentationNames.CongruityImplant) && (
|
||||
{!Player.hasAugmentation(AugmentationNames.CongruityImplant) && (
|
||||
<>
|
||||
<br />
|
||||
<br />
|
||||
@@ -186,14 +180,12 @@ export const GraftingRoot = (): React.ReactElement => {
|
||||
<Typography color={Settings.theme.info}>
|
||||
<b>Time to Graft:</b>{" "}
|
||||
{convertTimeMsToTimeElapsedString(
|
||||
calculateGraftingTimeWithBonus(player, graftableAugmentations[selectedAug]),
|
||||
calculateGraftingTimeWithBonus(graftableAugmentations[selectedAug]),
|
||||
)}
|
||||
{/* Use formula so the displayed creation time is accurate to player bonus */}
|
||||
</Typography>
|
||||
|
||||
{selectedAugmentation.prereqs.length > 0 && (
|
||||
<AugPreReqsChecklist player={player} aug={selectedAugmentation} />
|
||||
)}
|
||||
{selectedAugmentation.prereqs.length > 0 && <AugPreReqsChecklist aug={selectedAugmentation} />}
|
||||
|
||||
<br />
|
||||
|
||||
@@ -229,10 +221,10 @@ export const GraftingRoot = (): React.ReactElement => {
|
||||
|
||||
<Paper sx={{ my: 1, p: 1, width: "fit-content" }}>
|
||||
<Typography>
|
||||
<b>Entropy strength:</b> {player.entropy}
|
||||
<b>Entropy strength:</b> {Player.entropy}
|
||||
<br />
|
||||
<b>All multipliers decreased by:</b>{" "}
|
||||
{formatNumber((1 - CONSTANTS.EntropyEffect ** player.entropy) * 100, 3)}% (multiplicative)
|
||||
{formatNumber((1 - CONSTANTS.EntropyEffect ** Player.entropy) * 100, 3)}% (multiplicative)
|
||||
</Typography>
|
||||
</Paper>
|
||||
|
||||
|
||||
@@ -32,5 +32,5 @@ export function applyEntropy(this: IPlayer, stacks = 1): void {
|
||||
this.reapplyAllAugmentations();
|
||||
this.reapplyAllSourceFiles();
|
||||
|
||||
this.mults = calculateEntropy(this, stacks);
|
||||
this.mults = calculateEntropy(stacks);
|
||||
}
|
||||
|
||||
@@ -13,5 +13,5 @@ export function inBladeburner(this: IPlayer): boolean {
|
||||
}
|
||||
|
||||
export function startBladeburner(this: IPlayer): void {
|
||||
this.bladeburner = new Bladeburner(this);
|
||||
this.bladeburner = new Bladeburner();
|
||||
}
|
||||
|
||||
@@ -112,15 +112,15 @@ export function prestigeAugmentation(this: PlayerObject): void {
|
||||
const numSleeves = Math.min(3, this.sourceFileLvl(10) + (this.bitNodeN === 10 ? 1 : 0)) + this.sleevesFromCovenant;
|
||||
if (this.sleeves.length > numSleeves) this.sleeves.length = numSleeves;
|
||||
for (let i = this.sleeves.length; i < numSleeves; i++) {
|
||||
this.sleeves.push(new Sleeve(this));
|
||||
this.sleeves.push(new Sleeve());
|
||||
}
|
||||
|
||||
for (let i = 0; i < this.sleeves.length; ++i) {
|
||||
if (this.sleeves[i] instanceof Sleeve) {
|
||||
if (this.sleeves[i].shock >= 100) {
|
||||
this.sleeves[i].synchronize(this);
|
||||
this.sleeves[i].synchronize();
|
||||
} else {
|
||||
this.sleeves[i].shockRecovery(this);
|
||||
this.sleeves[i].shockRecovery();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -149,9 +149,9 @@ export function prestigeSourceFile(this: IPlayer): void {
|
||||
// Duplicate sleeves are reset to level 1 every Bit Node (but the number of sleeves you have persists)
|
||||
for (let i = 0; i < this.sleeves.length; ++i) {
|
||||
if (this.sleeves[i] instanceof Sleeve) {
|
||||
this.sleeves[i].prestige(this);
|
||||
this.sleeves[i].prestige();
|
||||
} else {
|
||||
this.sleeves[i] = new Sleeve(this);
|
||||
this.sleeves[i] = new Sleeve();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -490,7 +490,7 @@ export function regenerateHp(this: IPerson, amt: number): void {
|
||||
}
|
||||
|
||||
export function hospitalize(this: IPlayer): number {
|
||||
const cost = getHospitalizationCost(this);
|
||||
const cost = getHospitalizationCost();
|
||||
SnackbarEvents.emit(`You've been Hospitalized for ${numeralWrapper.formatMoney(cost)}`, ToastVariant.WARNING, 2000);
|
||||
|
||||
this.loseMoney(cost, "hospitalization");
|
||||
@@ -596,7 +596,7 @@ export function quitJob(this: IPlayer, company: string): void {
|
||||
}
|
||||
for (const sleeve of this.sleeves) {
|
||||
if (isSleeveCompanyWork(sleeve.currentWork) && sleeve.currentWork.companyName === company) {
|
||||
sleeve.stopWork(this);
|
||||
sleeve.stopWork();
|
||||
dialogBoxCreate(`You quit ${company} while one of your sleeves was working there. The sleeve is now idle.`);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,20 +3,20 @@ import { IPlayer } from "../IPlayer";
|
||||
|
||||
export function start(this: IPlayer, w: Work): void {
|
||||
if (this.currentWork !== null) {
|
||||
this.currentWork.finish(this, true);
|
||||
this.currentWork.finish(true);
|
||||
}
|
||||
this.currentWork = w;
|
||||
}
|
||||
export function process(this: IPlayer, cycles = 1): void {
|
||||
if (this.currentWork === null) return;
|
||||
const finished = this.currentWork.process(this, cycles);
|
||||
const finished = this.currentWork.process(cycles);
|
||||
if (finished) {
|
||||
this.finishWork(false);
|
||||
}
|
||||
}
|
||||
export function finish(this: IPlayer, cancelled: boolean): void {
|
||||
if (this.currentWork === null) return;
|
||||
this.currentWork.finish(this, cancelled);
|
||||
this.currentWork.finish(cancelled);
|
||||
this.currentWork = null;
|
||||
this.focus = false;
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
* Sleeves are unlocked in BitNode-10.
|
||||
*/
|
||||
|
||||
import { IPlayer } from "../IPlayer";
|
||||
import { Player } from "../../Player";
|
||||
import { Person } from "../Person";
|
||||
|
||||
import { Augmentation } from "../../Augmentation/Augmentation";
|
||||
@@ -74,11 +74,9 @@ export class Sleeve extends Person {
|
||||
*/
|
||||
sync = 1;
|
||||
|
||||
constructor(p: IPlayer | null = null) {
|
||||
constructor() {
|
||||
super();
|
||||
if (p != null) {
|
||||
this.shockRecovery(p);
|
||||
}
|
||||
this.shockRecovery();
|
||||
}
|
||||
|
||||
shockBonus(): number {
|
||||
@@ -89,26 +87,26 @@ export class Sleeve extends Person {
|
||||
return this.sync / 100;
|
||||
}
|
||||
|
||||
startWork(player: IPlayer, w: Work): void {
|
||||
if (this.currentWork) this.currentWork.finish(player);
|
||||
startWork(w: Work): void {
|
||||
if (this.currentWork) this.currentWork.finish();
|
||||
this.currentWork = w;
|
||||
}
|
||||
|
||||
stopWork(player: IPlayer): void {
|
||||
if (this.currentWork) this.currentWork.finish(player);
|
||||
stopWork(): void {
|
||||
if (this.currentWork) this.currentWork.finish();
|
||||
this.currentWork = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Commit crimes
|
||||
*/
|
||||
commitCrime(p: IPlayer, crimeKey: string): boolean {
|
||||
commitCrime(crimeKey: string): boolean {
|
||||
const crime: Crime | null = Crimes[crimeKey] || Object.values(Crimes).find((crime) => crime.name === crimeKey);
|
||||
if (!crime) {
|
||||
return false;
|
||||
}
|
||||
|
||||
this.startWork(p, new SleeveCrimeWork(crime.type));
|
||||
this.startWork(new SleeveCrimeWork(crime.type));
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -152,7 +150,7 @@ export class Sleeve extends Person {
|
||||
/**
|
||||
* Called on every sleeve for a Source File Prestige
|
||||
*/
|
||||
prestige(p: IPlayer): void {
|
||||
prestige(): void {
|
||||
// Reset exp
|
||||
this.exp.hacking = 0;
|
||||
this.exp.strength = 0;
|
||||
@@ -164,8 +162,8 @@ export class Sleeve extends Person {
|
||||
this.hp.current = this.hp.max;
|
||||
|
||||
// Reset task-related stuff
|
||||
this.stopWork(p);
|
||||
this.shockRecovery(p);
|
||||
this.stopWork();
|
||||
this.shockRecovery();
|
||||
|
||||
// Reset augs and multipliers
|
||||
this.augmentations = [];
|
||||
@@ -186,7 +184,7 @@ export class Sleeve extends Person {
|
||||
* Returns an object containing the amount of experience that should be
|
||||
* transferred to all other sleeves
|
||||
*/
|
||||
process(p: IPlayer, numCycles = 1): void {
|
||||
process(numCycles = 1): void {
|
||||
// Only process once every second (5 cycles)
|
||||
const CyclesPerSecond = 1000 / CONSTANTS.MilliPerCycle;
|
||||
this.storedCycles += numCycles;
|
||||
@@ -196,24 +194,24 @@ export class Sleeve extends Person {
|
||||
cyclesUsed = Math.min(cyclesUsed, 15);
|
||||
this.shock = Math.min(100, this.shock + 0.0001 * cyclesUsed);
|
||||
if (!this.currentWork) return;
|
||||
this.currentWork.process(p, this, cyclesUsed);
|
||||
this.currentWork.process(this, cyclesUsed);
|
||||
this.storedCycles -= cyclesUsed;
|
||||
}
|
||||
|
||||
shockRecovery(p: IPlayer): boolean {
|
||||
this.startWork(p, new SleeveRecoveryWork());
|
||||
shockRecovery(): boolean {
|
||||
this.startWork(new SleeveRecoveryWork());
|
||||
return true;
|
||||
}
|
||||
|
||||
synchronize(p: IPlayer): boolean {
|
||||
this.startWork(p, new SleeveSynchroWork());
|
||||
synchronize(): boolean {
|
||||
this.startWork(new SleeveSynchroWork());
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Take a course at a university
|
||||
*/
|
||||
takeUniversityCourse(p: IPlayer, universityName: string, className: string): boolean {
|
||||
takeUniversityCourse(universityName: string, className: string): boolean {
|
||||
// Set exp/money multipliers based on which university.
|
||||
// Also check that the sleeve is in the right city
|
||||
let loc: LocationName | undefined;
|
||||
@@ -261,7 +259,6 @@ export class Sleeve extends Person {
|
||||
if (!classType) return false;
|
||||
|
||||
this.startWork(
|
||||
p,
|
||||
new SleeveClassWork({
|
||||
classType: classType,
|
||||
location: loc,
|
||||
@@ -273,8 +270,8 @@ export class Sleeve extends Person {
|
||||
/**
|
||||
* Travel to another City. Costs money from player
|
||||
*/
|
||||
travel(p: IPlayer, newCity: CityName): boolean {
|
||||
p.loseMoney(CONSTANTS.TravelCost, "sleeves");
|
||||
travel(newCity: CityName): boolean {
|
||||
Player.loseMoney(CONSTANTS.TravelCost, "sleeves");
|
||||
this.city = newCity;
|
||||
|
||||
return true;
|
||||
@@ -284,13 +281,15 @@ export class Sleeve extends Person {
|
||||
return this.augmentations.some((a) => a.name === aug);
|
||||
}
|
||||
|
||||
tryBuyAugmentation(p: IPlayer, aug: Augmentation): boolean {
|
||||
if (!p.canAfford(aug.baseCost)) return false;
|
||||
tryBuyAugmentation(aug: Augmentation): boolean {
|
||||
if (!Player.canAfford(aug.baseCost)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Verify that this sleeve does not already have that augmentation.
|
||||
if (this.hasAugmentation(aug.name)) return false;
|
||||
|
||||
p.loseMoney(aug.baseCost, "sleeves");
|
||||
Player.loseMoney(aug.baseCost, "sleeves");
|
||||
this.installAugmentation(aug);
|
||||
return true;
|
||||
}
|
||||
@@ -303,17 +302,17 @@ export class Sleeve extends Person {
|
||||
* Start work for one of the player's companies
|
||||
* Returns boolean indicating success
|
||||
*/
|
||||
workForCompany(p: IPlayer, companyName: string): boolean {
|
||||
if (!(Companies[companyName] instanceof Company) || p.jobs[companyName] == null) {
|
||||
workForCompany(companyName: string): boolean {
|
||||
if (!(Companies[companyName] instanceof Company) || Player.jobs[companyName] == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const company: Company | null = Companies[companyName];
|
||||
const companyPosition: CompanyPosition | null = CompanyPositions[p.jobs[companyName]];
|
||||
const companyPosition: CompanyPosition | null = CompanyPositions[Player.jobs[companyName]];
|
||||
if (company == null) return false;
|
||||
if (companyPosition == null) return false;
|
||||
|
||||
this.startWork(p, new SleeveCompanyWork({ companyName: companyName }));
|
||||
this.startWork(new SleeveCompanyWork({ companyName: companyName }));
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -322,9 +321,9 @@ export class Sleeve extends Person {
|
||||
* Start work for one of the player's factions
|
||||
* Returns boolean indicating success
|
||||
*/
|
||||
workForFaction(p: IPlayer, factionName: string, workType: string): boolean {
|
||||
workForFaction(factionName: string, workType: string): boolean {
|
||||
const faction = Factions[factionName];
|
||||
if (factionName === "" || !faction || !(faction instanceof Faction) || !p.factions.includes(factionName)) {
|
||||
if (factionName === "" || !faction || !(faction instanceof Faction) || !Player.factions.includes(factionName)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -347,7 +346,6 @@ export class Sleeve extends Person {
|
||||
}
|
||||
|
||||
this.startWork(
|
||||
p,
|
||||
new SleeveFactionWork({
|
||||
factionWorkType: factionWorkType,
|
||||
factionName: faction.name,
|
||||
@@ -360,7 +358,7 @@ export class Sleeve extends Person {
|
||||
/**
|
||||
* Begin a gym workout task
|
||||
*/
|
||||
workoutAtGym(p: IPlayer, gymName: string, stat: string): boolean {
|
||||
workoutAtGym(gymName: string, stat: string): boolean {
|
||||
// Set exp/money multipliers based on which university.
|
||||
// Also check that the sleeve is in the right city
|
||||
let loc: LocationName | undefined;
|
||||
@@ -414,7 +412,6 @@ export class Sleeve extends Person {
|
||||
if (!classType) return false;
|
||||
|
||||
this.startWork(
|
||||
p,
|
||||
new SleeveClassWork({
|
||||
classType: classType,
|
||||
location: loc,
|
||||
@@ -427,41 +424,41 @@ export class Sleeve extends Person {
|
||||
/**
|
||||
* Begin a bladeburner task
|
||||
*/
|
||||
bladeburner(p: IPlayer, action: string, contract: string): boolean {
|
||||
bladeburner(action: string, contract: string): boolean {
|
||||
switch (action) {
|
||||
case "Field analysis":
|
||||
this.startWork(p, new SleeveBladeburnerWork({ type: "General", name: "Field Analysis" }));
|
||||
this.startWork(new SleeveBladeburnerWork({ type: "General", name: "Field Analysis" }));
|
||||
return true;
|
||||
case "Recruitment":
|
||||
this.startWork(p, new SleeveBladeburnerWork({ type: "General", name: "Recruitment" }));
|
||||
this.startWork(new SleeveBladeburnerWork({ type: "General", name: "Recruitment" }));
|
||||
return true;
|
||||
case "Diplomacy":
|
||||
this.startWork(p, new SleeveBladeburnerWork({ type: "General", name: "Diplomacy" }));
|
||||
this.startWork(new SleeveBladeburnerWork({ type: "General", name: "Diplomacy" }));
|
||||
return true;
|
||||
case "Hyperbolic Regeneration Chamber":
|
||||
this.startWork(p, new SleeveBladeburnerWork({ type: "General", name: "Hyperbolic Regeneration Chamber" }));
|
||||
this.startWork(new SleeveBladeburnerWork({ type: "General", name: "Hyperbolic Regeneration Chamber" }));
|
||||
return true;
|
||||
case "Infiltrate synthoids":
|
||||
this.startWork(p, new SleeveInfiltrateWork());
|
||||
this.startWork(new SleeveInfiltrateWork());
|
||||
return true;
|
||||
case "Support main sleeve":
|
||||
this.startWork(p, new SleeveSupportWork(p));
|
||||
this.startWork(new SleeveSupportWork());
|
||||
return true;
|
||||
case "Take on contracts":
|
||||
if (!Contracts[contract]) return false;
|
||||
this.startWork(p, new SleeveBladeburnerWork({ type: "Contracts", name: contract }));
|
||||
this.startWork(new SleeveBladeburnerWork({ type: "Contracts", name: contract }));
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
recruitmentSuccessChance(p: IPlayer): number {
|
||||
return Math.max(0, Math.min(1, p.bladeburner?.getRecruitmentSuccessChance(this) ?? 0));
|
||||
recruitmentSuccessChance(): number {
|
||||
return Math.max(0, Math.min(1, Player.bladeburner?.getRecruitmentSuccessChance(this) ?? 0));
|
||||
}
|
||||
|
||||
contractSuccessChance(p: IPlayer, type: string, name: string): string {
|
||||
const bb = p.bladeburner;
|
||||
contractSuccessChance(type: string, name: string): string {
|
||||
const bb = Player.bladeburner;
|
||||
if (bb === null) {
|
||||
const errorLogText = `bladeburner is null`;
|
||||
console.error(`Function: sleeves.contractSuccessChance; Message: '${errorLogText}'`);
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { FactionNames } from "../../Faction/data/FactionNames";
|
||||
import { Sleeve } from "./Sleeve";
|
||||
|
||||
import { IPlayer } from "../IPlayer";
|
||||
import { Player } from "../../Player";
|
||||
|
||||
import { Augmentation } from "../../Augmentation/Augmentation";
|
||||
@@ -11,7 +10,7 @@ import { Multipliers } from "../Multipliers";
|
||||
import { AugmentationNames } from "../../Augmentation/data/AugmentationNames";
|
||||
import { getFactionAugmentationsFiltered } from "../../Faction/FactionHelpers";
|
||||
|
||||
export function findSleevePurchasableAugs(sleeve: Sleeve, p: IPlayer): Augmentation[] {
|
||||
export function findSleevePurchasableAugs(sleeve: Sleeve): Augmentation[] {
|
||||
// You can only purchase Augmentations that are actually available from
|
||||
// your factions. I.e. you must be in a faction that has the Augmentation
|
||||
// and you must also have enough rep in that faction in order to purchase it.
|
||||
@@ -55,21 +54,21 @@ export function findSleevePurchasableAugs(sleeve: Sleeve, p: IPlayer): Augmentat
|
||||
|
||||
// If player is in a gang, then we return all augs that the player
|
||||
// has enough reputation for (since that gang offers all augs)
|
||||
if (p.inGang()) {
|
||||
const fac = p.getGangFaction();
|
||||
const gangAugs = getFactionAugmentationsFiltered(Player, fac);
|
||||
if (Player.inGang()) {
|
||||
const fac = Player.getGangFaction();
|
||||
const gangAugs = getFactionAugmentationsFiltered(fac);
|
||||
|
||||
for (const augName of gangAugs) {
|
||||
const aug = StaticAugmentations[augName];
|
||||
if (!isAvailableForSleeve(aug)) continue;
|
||||
|
||||
if (fac.playerReputation > aug.getCost(p).repCost) {
|
||||
if (fac.playerReputation > aug.getCost().repCost) {
|
||||
availableAugs.push(aug);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (const facName of p.factions) {
|
||||
for (const facName of Player.factions) {
|
||||
if (facName === FactionNames.Bladeburners) continue;
|
||||
if (facName === FactionNames.Netburners) continue;
|
||||
const fac = Factions[facName];
|
||||
@@ -79,7 +78,7 @@ export function findSleevePurchasableAugs(sleeve: Sleeve, p: IPlayer): Augmentat
|
||||
const aug = StaticAugmentations[augName];
|
||||
if (!isAvailableForSleeve(aug)) continue;
|
||||
|
||||
if (fac.playerReputation > aug.getCost(p).repCost) {
|
||||
if (fac.playerReputation > aug.getCost().repCost) {
|
||||
availableAugs.push(aug);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { IPlayer } from "../../IPlayer";
|
||||
import { Player } from "../../../Player";
|
||||
import { Generic_fromJSON, Generic_toJSON, IReviverValue, Reviver } from "../../../utils/JSONReviver";
|
||||
import { Sleeve } from "../Sleeve";
|
||||
import { applySleeveGains, Work, WorkType } from "./Work";
|
||||
@@ -25,45 +25,45 @@ export class SleeveBladeburnerWork extends Work {
|
||||
this.actionName = params?.name ?? "Field analysis";
|
||||
}
|
||||
|
||||
cyclesNeeded(player: IPlayer, sleeve: Sleeve): number {
|
||||
const ret = player.bladeburner?.getActionTimeNetscriptFn(sleeve, this.actionType, this.actionName);
|
||||
cyclesNeeded(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");
|
||||
process(sleeve: Sleeve, cycles: number): number {
|
||||
if (!Player.bladeburner) throw new Error("sleeve doing blade work without being a member");
|
||||
this.cyclesWorked += cycles;
|
||||
const actionIdent = player.bladeburner.getActionIdFromTypeAndName(this.actionType, this.actionName);
|
||||
const actionIdent = Player.bladeburner.getActionIdFromTypeAndName(this.actionType, this.actionName);
|
||||
if (!actionIdent) throw new Error(`Error getting ${this.actionName} action`);
|
||||
if (this.actionType === "Contracts") {
|
||||
const action = player.bladeburner.getActionObject(actionIdent);
|
||||
const action = Player.bladeburner.getActionObject(actionIdent);
|
||||
if (!action) throw new Error(`Error getting ${this.actionName} action object`);
|
||||
if (action.count <= 0) {
|
||||
sleeve.stopWork(player);
|
||||
sleeve.stopWork();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
while (this.cyclesWorked > this.cyclesNeeded(player, sleeve)) {
|
||||
while (this.cyclesWorked > this.cyclesNeeded(sleeve)) {
|
||||
if (this.actionType === "Contracts") {
|
||||
const action = player.bladeburner.getActionObject(actionIdent);
|
||||
const action = Player.bladeburner.getActionObject(actionIdent);
|
||||
if (!action) throw new Error(`Error getting ${this.actionName} action object`);
|
||||
if (action.count <= 0) {
|
||||
sleeve.stopWork(player);
|
||||
sleeve.stopWork();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
const retValue = player.bladeburner.completeAction(player, sleeve, actionIdent, false);
|
||||
const retValue = Player.bladeburner.completeAction(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}`);
|
||||
applySleeveGains(player, sleeve, exp, 1);
|
||||
applySleeveGains(sleeve, exp, 1);
|
||||
}
|
||||
player.gainMoney(retValue.money, "sleeves");
|
||||
player.gainStats(retValue);
|
||||
this.cyclesWorked -= this.cyclesNeeded(player, sleeve);
|
||||
Player.gainMoney(retValue.money, "sleeves");
|
||||
Player.gainStats(retValue);
|
||||
this.cyclesWorked -= this.cyclesNeeded(sleeve);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -24,9 +24,9 @@ export class SleeveClassWork extends Work {
|
||||
this.location = params?.location ?? LocationName.Sector12RothmanUniversity;
|
||||
}
|
||||
|
||||
calculateRates(player: IPlayer, sleeve: Sleeve): WorkStats {
|
||||
calculateRates(sleeve: Sleeve): WorkStats {
|
||||
return scaleWorkStats(
|
||||
calculateClassEarnings(player, sleeve, this.classType, this.location),
|
||||
calculateClassEarnings(sleeve, this.classType, this.location),
|
||||
sleeve.shockBonus(),
|
||||
false,
|
||||
);
|
||||
@@ -38,9 +38,9 @@ export class SleeveClassWork extends Work {
|
||||
);
|
||||
}
|
||||
|
||||
process(player: IPlayer, sleeve: Sleeve, cycles: number): number {
|
||||
const rate = this.calculateRates(player, sleeve);
|
||||
applySleeveGains(player, sleeve, rate, cycles);
|
||||
process(sleeve: Sleeve, cycles: number): number {
|
||||
const rate = this.calculateRates(sleeve);
|
||||
applySleeveGains(sleeve, rate, cycles);
|
||||
return 0;
|
||||
}
|
||||
APICopy(): Record<string, unknown> {
|
||||
|
||||
@@ -30,14 +30,14 @@ export class SleeveCompanyWork extends Work {
|
||||
return c;
|
||||
}
|
||||
|
||||
getGainRates(player: IPlayer, sleeve: Sleeve): WorkStats {
|
||||
return calculateCompanyWorkStats(player, sleeve, this.getCompany());
|
||||
getGainRates(sleeve: Sleeve): WorkStats {
|
||||
return calculateCompanyWorkStats(sleeve, this.getCompany());
|
||||
}
|
||||
|
||||
process(player: IPlayer, sleeve: Sleeve, cycles: number): number {
|
||||
process(sleeve: Sleeve, cycles: number): number {
|
||||
const company = this.getCompany();
|
||||
const gains = this.getGainRates(player, sleeve);
|
||||
applySleeveGains(player, sleeve, gains, cycles);
|
||||
const gains = this.getGainRates(sleeve);
|
||||
applySleeveGains(sleeve, gains, cycles);
|
||||
company.playerReputation += gains.reputation * cycles;
|
||||
influenceStockThroughCompanyWork(company, gains.reputation, cycles);
|
||||
return 0;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { IPlayer } from "../../IPlayer";
|
||||
import { Player } from "../../../Player";
|
||||
import { Generic_fromJSON, Generic_toJSON, IReviverValue, Reviver } from "../../../utils/JSONReviver";
|
||||
import { Sleeve } from "../Sleeve";
|
||||
import { applySleeveGains, Work, WorkType } from "./Work";
|
||||
@@ -43,19 +43,19 @@ export class SleeveCrimeWork extends Work {
|
||||
return this.getCrime().time / CONSTANTS._idleSpeed;
|
||||
}
|
||||
|
||||
process(player: IPlayer, sleeve: Sleeve, cycles: number): number {
|
||||
process(sleeve: Sleeve, cycles: number): number {
|
||||
this.cyclesWorked += cycles;
|
||||
|
||||
const crime = this.getCrime();
|
||||
let gains = this.getExp();
|
||||
if (this.cyclesWorked >= this.cyclesNeeded()) {
|
||||
if (Math.random() < crime.successRate(sleeve)) {
|
||||
player.karma -= crime.karma * sleeve.syncBonus();
|
||||
Player.karma -= crime.karma * sleeve.syncBonus();
|
||||
} else {
|
||||
gains.money = 0;
|
||||
gains = scaleWorkStats(gains, 0.25);
|
||||
}
|
||||
applySleeveGains(player, sleeve, gains, cycles);
|
||||
applySleeveGains(sleeve, gains, cycles);
|
||||
this.cyclesWorked -= this.cyclesNeeded();
|
||||
}
|
||||
return 0;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { IPlayer } from "../../IPlayer";
|
||||
import { Player } from "../../../Player";
|
||||
import { Generic_fromJSON, Generic_toJSON, IReviverValue, Reviver } from "../../../utils/JSONReviver";
|
||||
import { Sleeve } from "../Sleeve";
|
||||
import { applySleeveGains, Work, WorkType } from "./Work";
|
||||
@@ -57,16 +57,14 @@ export class SleeveFactionWork extends Work {
|
||||
return f;
|
||||
}
|
||||
|
||||
process(player: IPlayer, sleeve: Sleeve, cycles: number): number {
|
||||
if (player.gang) {
|
||||
if (this.factionName === player.gang.facName) {
|
||||
sleeve.stopWork(player);
|
||||
return 0;
|
||||
}
|
||||
process(sleeve: Sleeve, cycles: number): number {
|
||||
if (this.factionName === Player.gang?.facName) {
|
||||
sleeve.stopWork();
|
||||
return 0;
|
||||
}
|
||||
|
||||
const exp = this.getExpRates(sleeve);
|
||||
applySleeveGains(player, sleeve, exp, cycles);
|
||||
applySleeveGains(sleeve, exp, cycles);
|
||||
const rep = this.getReputationRate(sleeve);
|
||||
this.getFaction().playerReputation += rep;
|
||||
return 0;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { IPlayer } from "../../IPlayer";
|
||||
import { Player } from "../../../Player";
|
||||
import { Generic_fromJSON, Generic_toJSON, IReviverValue, Reviver } from "../../../utils/JSONReviver";
|
||||
import { Sleeve } from "../Sleeve";
|
||||
import { Work, WorkType } from "./Work";
|
||||
@@ -20,12 +20,12 @@ export class SleeveInfiltrateWork extends Work {
|
||||
return infiltrateCycles;
|
||||
}
|
||||
|
||||
process(player: IPlayer, sleeve: Sleeve, cycles: number): number {
|
||||
if (!player.bladeburner) throw new Error("sleeve doing blade work without being a member");
|
||||
process(_sleeve: Sleeve, cycles: number): number {
|
||||
if (!Player.bladeburner) throw new Error("sleeve doing blade work without being a member");
|
||||
this.cyclesWorked += cycles;
|
||||
if (this.cyclesWorked > this.cyclesNeeded()) {
|
||||
this.cyclesWorked -= this.cyclesNeeded();
|
||||
player.bladeburner.infiltrateSynthoidCommunities(player);
|
||||
Player.bladeburner.infiltrateSynthoidCommunities();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import { IPlayer } from "../../IPlayer";
|
||||
import { Generic_fromJSON, Generic_toJSON, IReviverValue, Reviver } from "../../../utils/JSONReviver";
|
||||
import { Sleeve } from "../Sleeve";
|
||||
import { Work, WorkType } from "./Work";
|
||||
@@ -11,9 +10,9 @@ export class SleeveRecoveryWork extends Work {
|
||||
super(WorkType.RECOVERY);
|
||||
}
|
||||
|
||||
process(player: IPlayer, sleeve: Sleeve, cycles: number): number {
|
||||
process(sleeve: Sleeve, cycles: number): number {
|
||||
sleeve.shock = Math.min(100, sleeve.shock + 0.0002 * cycles);
|
||||
if (sleeve.shock >= 100) sleeve.stopWork(player);
|
||||
if (sleeve.shock >= 100) sleeve.stopWork();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { IPlayer } from "../../../PersonObjects/IPlayer";
|
||||
import { Player } from "../../../Player";
|
||||
import { Generic_fromJSON, Generic_toJSON, IReviverValue, Reviver } from "../../../utils/JSONReviver";
|
||||
import { Work, WorkType } from "./Work";
|
||||
|
||||
@@ -6,17 +6,17 @@ export const isSleeveSupportWork = (w: Work | null): w is SleeveSupportWork =>
|
||||
w !== null && w.type === WorkType.SUPPORT;
|
||||
|
||||
export class SleeveSupportWork extends Work {
|
||||
constructor(player?: IPlayer) {
|
||||
constructor() {
|
||||
super(WorkType.SUPPORT);
|
||||
if (player) player.bladeburner?.sleeveSupport(true);
|
||||
Player.bladeburner?.sleeveSupport(true);
|
||||
}
|
||||
|
||||
process(): number {
|
||||
return 0;
|
||||
}
|
||||
|
||||
finish(player: IPlayer): void {
|
||||
player.bladeburner?.sleeveSupport(false);
|
||||
finish(): void {
|
||||
Player.bladeburner?.sleeveSupport(false);
|
||||
}
|
||||
|
||||
APICopy(): Record<string, unknown> {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { IPlayer } from "../../IPlayer";
|
||||
import { Player } from "../../../Player";
|
||||
import { Generic_fromJSON, Generic_toJSON, IReviverValue, Reviver } from "../../../utils/JSONReviver";
|
||||
import { Sleeve } from "../Sleeve";
|
||||
import { Work, WorkType } from "./Work";
|
||||
@@ -11,9 +11,9 @@ export class SleeveSynchroWork extends Work {
|
||||
super(WorkType.SYNCHRO);
|
||||
}
|
||||
|
||||
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.stopWork(player);
|
||||
process(sleeve: Sleeve, cycles: number): number {
|
||||
sleeve.sync = Math.min(100, sleeve.sync + Player.getIntelligenceBonus(0.5) * 0.0002 * cycles);
|
||||
if (sleeve.sync >= 100) sleeve.stopWork();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
import { IPlayer } from "../../IPlayer";
|
||||
import { Player } from "../../../Player";
|
||||
import { IReviverValue } from "../../../utils/JSONReviver";
|
||||
import { Sleeve } from "../Sleeve";
|
||||
import { applyWorkStats, applyWorkStatsExp, scaleWorkStats, WorkStats } from "../../../Work/WorkStats";
|
||||
|
||||
export const applySleeveGains = (player: IPlayer, sleeve: Sleeve, rawStats: WorkStats, cycles = 1): void => {
|
||||
export const applySleeveGains = (sleeve: Sleeve, rawStats: WorkStats, cycles = 1): void => {
|
||||
const shockedStats = scaleWorkStats(rawStats, sleeve.shockBonus(), rawStats.money > 0);
|
||||
applyWorkStatsExp(sleeve, shockedStats, cycles);
|
||||
const syncStats = scaleWorkStats(shockedStats, sleeve.syncBonus(), rawStats.money > 0);
|
||||
applyWorkStats(player, player, syncStats, cycles, "sleeves");
|
||||
player.sleeves.filter((s) => s != sleeve).forEach((s) => applyWorkStatsExp(s, syncStats, cycles));
|
||||
applyWorkStats(Player, syncStats, cycles, "sleeves");
|
||||
Player.sleeves.filter((s) => s !== sleeve).forEach((s) => applyWorkStatsExp(s, syncStats, cycles));
|
||||
};
|
||||
|
||||
export abstract class Work {
|
||||
@@ -18,10 +18,10 @@ export abstract class Work {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
abstract process(player: IPlayer, sleeve: Sleeve, cycles: number): number;
|
||||
abstract process(sleeve: Sleeve, cycles: number): number;
|
||||
abstract APICopy(): Record<string, unknown>;
|
||||
abstract toJSON(): IReviverValue;
|
||||
finish(__player: IPlayer): void {
|
||||
finish(): void {
|
||||
/* left for children to implement */
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,7 +56,7 @@ export function CovenantPurchasesRoot(props: IProps): React.ReactElement {
|
||||
if (player.canAfford(purchaseCost())) {
|
||||
player.loseMoney(purchaseCost(), "sleeves");
|
||||
player.sleevesFromCovenant += 1;
|
||||
player.sleeves.push(new Sleeve(player));
|
||||
player.sleeves.push(new Sleeve());
|
||||
rerender();
|
||||
} else {
|
||||
dialogBoxCreate(`You cannot afford to purchase a Duplicate Sleeve`);
|
||||
@@ -67,7 +67,7 @@ export function CovenantPurchasesRoot(props: IProps): React.ReactElement {
|
||||
const upgradePanels = [];
|
||||
for (let i = 0; i < player.sleeves.length; ++i) {
|
||||
const sleeve = player.sleeves[i];
|
||||
upgradePanels.push(<CovenantSleeveMemoryUpgrade index={i} p={player} rerender={rerender} sleeve={sleeve} />);
|
||||
upgradePanels.push(<CovenantSleeveMemoryUpgrade index={i} rerender={rerender} sleeve={sleeve} />);
|
||||
}
|
||||
|
||||
return (
|
||||
@@ -81,7 +81,7 @@ export function CovenantPurchasesRoot(props: IProps): React.ReactElement {
|
||||
</Typography>
|
||||
<Button disabled={purchaseDisabled} onClick={purchaseOnClick}>
|
||||
Purchase -
|
||||
<Money money={purchaseCost()} player={player} />
|
||||
<Money money={purchaseCost()} forPurchase={true} />
|
||||
</Button>
|
||||
</>
|
||||
)}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
import React, { useState } from "react";
|
||||
|
||||
import { Sleeve } from "../Sleeve";
|
||||
import { IPlayer } from "../../IPlayer";
|
||||
import { Player } from "../../../Player";
|
||||
|
||||
import { numeralWrapper } from "../../../ui/numeralFormat";
|
||||
import { Money } from "../../../ui/React/Money";
|
||||
@@ -18,7 +18,6 @@ import Paper from "@mui/material/Paper";
|
||||
|
||||
interface IProps {
|
||||
index: number;
|
||||
p: IPlayer;
|
||||
rerender: () => void;
|
||||
sleeve: Sleeve;
|
||||
}
|
||||
@@ -52,16 +51,16 @@ export function CovenantSleeveMemoryUpgrade(props: IProps): React.ReactElement {
|
||||
|
||||
function purchaseMemory(): void {
|
||||
const cost = getPurchaseCost();
|
||||
if (props.p.canAfford(cost)) {
|
||||
if (Player.canAfford(cost)) {
|
||||
props.sleeve.upgradeMemory(amt);
|
||||
props.p.loseMoney(cost, "sleeves");
|
||||
Player.loseMoney(cost, "sleeves");
|
||||
props.rerender();
|
||||
}
|
||||
}
|
||||
|
||||
// Purchase button props
|
||||
const cost = getPurchaseCost();
|
||||
const purchaseBtnDisabled = !props.p.canAfford(cost);
|
||||
const purchaseBtnDisabled = !Player.canAfford(cost);
|
||||
let purchaseBtnContent = <></>;
|
||||
if (isNaN(amt)) {
|
||||
purchaseBtnContent = <>Invalid value</>;
|
||||
@@ -69,7 +68,7 @@ export function CovenantSleeveMemoryUpgrade(props: IProps): React.ReactElement {
|
||||
purchaseBtnContent = (
|
||||
<>
|
||||
Purchase {amt} memory -
|
||||
<Money money={cost} player={props.p} />
|
||||
<Money money={cost} forPurchase={true} />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Container, Typography, Paper } from "@mui/material";
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { PurchasableAugmentations } from "../../../Augmentation/ui/PurchasableAugmentations";
|
||||
import { use } from "../../../ui/Context";
|
||||
import { Player } from "../../../Player";
|
||||
import { Modal } from "../../../ui/React/Modal";
|
||||
import { Sleeve } from "../Sleeve";
|
||||
import { findSleevePurchasableAugs } from "../SleeveHelpers";
|
||||
@@ -13,7 +13,6 @@ interface IProps {
|
||||
}
|
||||
|
||||
export function SleeveAugmentationsModal(props: IProps): React.ReactElement {
|
||||
const player = use.Player();
|
||||
const setRerender = useState(false)[1];
|
||||
function rerender(): void {
|
||||
setRerender((old) => !old);
|
||||
@@ -30,7 +29,7 @@ export function SleeveAugmentationsModal(props: IProps): React.ReactElement {
|
||||
// You can only purchase Augmentations that are actually available from
|
||||
// your factions. I.e. you must be in a faction that has the Augmentation
|
||||
// and you must also have enough rep in that faction in order to purchase it.
|
||||
const availableAugs = findSleevePurchasableAugs(props.sleeve, player);
|
||||
const availableAugs = findSleevePurchasableAugs(props.sleeve);
|
||||
|
||||
return (
|
||||
<Modal open={props.open} onClose={props.onClose}>
|
||||
@@ -50,12 +49,11 @@ export function SleeveAugmentationsModal(props: IProps): React.ReactElement {
|
||||
<PurchasableAugmentations
|
||||
augNames={availableAugs.map((aug) => aug.name)}
|
||||
ownedAugNames={ownedAugNames}
|
||||
player={player}
|
||||
canPurchase={(player, aug) => {
|
||||
return player.money > aug.baseCost;
|
||||
canPurchase={(aug) => {
|
||||
return Player.money > aug.baseCost;
|
||||
}}
|
||||
purchaseAugmentation={(player, aug) => {
|
||||
props.sleeve.tryBuyAugmentation(player, aug);
|
||||
purchaseAugmentation={(aug) => {
|
||||
props.sleeve.tryBuyAugmentation(aug);
|
||||
rerender();
|
||||
}}
|
||||
sleeveAugs
|
||||
|
||||
@@ -2,7 +2,7 @@ import { Box, Button, Paper, Tooltip, Typography } from "@mui/material";
|
||||
import React, { useState } from "react";
|
||||
import { FactionWorkType } from "../../../Work/data/FactionWorkType";
|
||||
import { CONSTANTS } from "../../../Constants";
|
||||
import { use } from "../../../ui/Context";
|
||||
import { Player } from "../../../Player";
|
||||
import { numeralWrapper } from "../../../ui/numeralFormat";
|
||||
import { ProgressBar } from "../../../ui/React/Progress";
|
||||
import { Sleeve } from "../Sleeve";
|
||||
@@ -27,7 +27,6 @@ interface IProps {
|
||||
}
|
||||
|
||||
export function SleeveElem(props: IProps): React.ReactElement {
|
||||
const player = use.Player();
|
||||
const [statsOpen, setStatsOpen] = useState(false);
|
||||
const [travelOpen, setTravelOpen] = useState(false);
|
||||
const [augmentationsOpen, setAugmentationsOpen] = useState(false);
|
||||
@@ -39,28 +38,28 @@ export function SleeveElem(props: IProps): React.ReactElement {
|
||||
case "------":
|
||||
break;
|
||||
case "Work for Company":
|
||||
props.sleeve.workForCompany(player, abc[1]);
|
||||
props.sleeve.workForCompany(abc[1]);
|
||||
break;
|
||||
case "Work for Faction":
|
||||
props.sleeve.workForFaction(player, abc[1], abc[2]);
|
||||
props.sleeve.workForFaction(abc[1], abc[2]);
|
||||
break;
|
||||
case "Commit Crime":
|
||||
props.sleeve.commitCrime(player, abc[1]);
|
||||
props.sleeve.commitCrime(abc[1]);
|
||||
break;
|
||||
case "Take University Course":
|
||||
props.sleeve.takeUniversityCourse(player, abc[2], abc[1]);
|
||||
props.sleeve.takeUniversityCourse(abc[2], abc[1]);
|
||||
break;
|
||||
case "Workout at Gym":
|
||||
props.sleeve.workoutAtGym(player, abc[2], abc[1]);
|
||||
props.sleeve.workoutAtGym(abc[2], abc[1]);
|
||||
break;
|
||||
case "Perform Bladeburner Actions":
|
||||
props.sleeve.bladeburner(player, abc[1], abc[2]);
|
||||
props.sleeve.bladeburner(abc[1], abc[2]);
|
||||
break;
|
||||
case "Shock Recovery":
|
||||
props.sleeve.shockRecovery(player);
|
||||
props.sleeve.shockRecovery();
|
||||
break;
|
||||
case "Synchronize":
|
||||
props.sleeve.synchronize(player);
|
||||
props.sleeve.synchronize();
|
||||
break;
|
||||
default:
|
||||
console.error(`Invalid/Unrecognized taskValue in setSleeveTask(): ${abc[0]}`);
|
||||
@@ -130,7 +129,7 @@ export function SleeveElem(props: IProps): React.ReactElement {
|
||||
desc = (
|
||||
<>
|
||||
This sleeve is currently attempting to perform {w.actionName}. (
|
||||
{((100 * w.cyclesWorked) / w.cyclesNeeded(player, props.sleeve)).toFixed(2)}%)
|
||||
{((100 * w.cyclesWorked) / w.cyclesNeeded(props.sleeve)).toFixed(2)}%)
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -156,11 +155,11 @@ export function SleeveElem(props: IProps): React.ReactElement {
|
||||
<StatsElement sleeve={props.sleeve} />
|
||||
<Box display="grid" sx={{ gridTemplateColumns: "1fr 1fr", width: "100%" }}>
|
||||
<Button onClick={() => setStatsOpen(true)}>More Stats</Button>
|
||||
<Tooltip title={player.money < CONSTANTS.TravelCost ? <Typography>Insufficient funds</Typography> : ""}>
|
||||
<Tooltip title={Player.money < CONSTANTS.TravelCost ? <Typography>Insufficient funds</Typography> : ""}>
|
||||
<span>
|
||||
<Button
|
||||
onClick={() => setTravelOpen(true)}
|
||||
disabled={player.money < CONSTANTS.TravelCost}
|
||||
disabled={Player.money < CONSTANTS.TravelCost}
|
||||
sx={{ width: "100%", height: "100%" }}
|
||||
>
|
||||
Travel
|
||||
@@ -184,7 +183,7 @@ export function SleeveElem(props: IProps): React.ReactElement {
|
||||
</span>
|
||||
<span>
|
||||
<EarningsElement sleeve={props.sleeve} />
|
||||
<TaskSelector player={player} sleeve={props.sleeve} setABC={setABC} />
|
||||
<TaskSelector sleeve={props.sleeve} setABC={setABC} />
|
||||
<Button onClick={setTask} sx={{ width: "100%" }}>
|
||||
Set Task
|
||||
</Button>
|
||||
@@ -202,7 +201,7 @@ export function SleeveElem(props: IProps): React.ReactElement {
|
||||
variant="determinate"
|
||||
value={
|
||||
(props.sleeve.currentWork.cyclesWorked /
|
||||
props.sleeve.currentWork.cyclesNeeded(player, props.sleeve)) *
|
||||
props.sleeve.currentWork.cyclesNeeded(props.sleeve)) *
|
||||
100
|
||||
}
|
||||
color="primary"
|
||||
|
||||
@@ -9,7 +9,6 @@ import { characterOverviewStyles as useStyles } from "../../../ui/React/Characte
|
||||
import { Money } from "../../../ui/React/Money";
|
||||
import { MoneyRate } from "../../../ui/React/MoneyRate";
|
||||
import { ReputationRate } from "../../../ui/React/ReputationRate";
|
||||
import { use } from "../../../ui/Context";
|
||||
|
||||
import { Sleeve } from "../Sleeve";
|
||||
import { isSleeveClassWork } from "../Work/SleeveClassWork";
|
||||
@@ -95,7 +94,6 @@ export function StatsElement(props: IProps): React.ReactElement {
|
||||
|
||||
export function EarningsElement(props: IProps): React.ReactElement {
|
||||
const classes = useStyles();
|
||||
const player = use.Player();
|
||||
|
||||
let data: (string | JSX.Element)[][] = [];
|
||||
if (isSleeveCrimeWork(props.sleeve.currentWork)) {
|
||||
@@ -111,7 +109,7 @@ export function EarningsElement(props: IProps): React.ReactElement {
|
||||
];
|
||||
}
|
||||
if (isSleeveClassWork(props.sleeve.currentWork)) {
|
||||
const rates = props.sleeve.currentWork.calculateRates(player, props.sleeve);
|
||||
const rates = props.sleeve.currentWork.calculateRates(props.sleeve);
|
||||
data = [
|
||||
[`Money:`, <MoneyRate money={5 * rates.money} />],
|
||||
[`Hacking Exp:`, `${numeralWrapper.formatExp(5 * rates.hackExp)} / sec`],
|
||||
@@ -137,7 +135,7 @@ export function EarningsElement(props: IProps): React.ReactElement {
|
||||
}
|
||||
|
||||
if (isSleeveCompanyWork(props.sleeve.currentWork)) {
|
||||
const rates = props.sleeve.currentWork.getGainRates(player, props.sleeve);
|
||||
const rates = props.sleeve.currentWork.getGainRates(props.sleeve);
|
||||
data = [
|
||||
[`Money:`, <MoneyRate money={5 * rates.money * BitNodeMultipliers.CompanyWorkMoney} />],
|
||||
[`Hacking Exp:`, `${numeralWrapper.formatExp(5 * rates.hackExp)} / sec`],
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React, { useState } from "react";
|
||||
import { Sleeve } from "../Sleeve";
|
||||
import { IPlayer } from "../../IPlayer";
|
||||
import { Player } from "../../../Player";
|
||||
import { Crimes } from "../../../Crime/Crimes";
|
||||
import { LocationName } from "../../../Locations/data/LocationNames";
|
||||
import { CityName } from "../../../Locations/data/CityNames";
|
||||
@@ -43,7 +43,6 @@ const bladeburnerSelectorOptions: string[] = [
|
||||
|
||||
interface IProps {
|
||||
sleeve: Sleeve;
|
||||
player: IPlayer;
|
||||
setABC: (abc: string[]) => void;
|
||||
}
|
||||
|
||||
@@ -52,10 +51,10 @@ interface ITaskDetails {
|
||||
second: (s1: string) => string[];
|
||||
}
|
||||
|
||||
function possibleJobs(player: IPlayer, sleeve: Sleeve): string[] {
|
||||
function possibleJobs(sleeve: Sleeve): string[] {
|
||||
// Array of all companies that other sleeves are working at
|
||||
const forbiddenCompanies: string[] = [];
|
||||
for (const otherSleeve of player.sleeves) {
|
||||
for (const otherSleeve of Player.sleeves) {
|
||||
if (sleeve === otherSleeve) {
|
||||
continue;
|
||||
}
|
||||
@@ -63,18 +62,18 @@ function possibleJobs(player: IPlayer, sleeve: Sleeve): string[] {
|
||||
forbiddenCompanies.push(otherSleeve.currentWork.companyName);
|
||||
}
|
||||
}
|
||||
const allJobs: string[] = Object.keys(player.jobs);
|
||||
const allJobs: string[] = Object.keys(Player.jobs);
|
||||
|
||||
return allJobs.filter((company) => !forbiddenCompanies.includes(company));
|
||||
}
|
||||
|
||||
function possibleFactions(player: IPlayer, sleeve: Sleeve): string[] {
|
||||
function possibleFactions(sleeve: Sleeve): string[] {
|
||||
// Array of all factions that other sleeves are working for
|
||||
const forbiddenFactions = [FactionNames.Bladeburners as string, FactionNames.ShadowsOfAnarchy as string];
|
||||
if (player.gang) {
|
||||
forbiddenFactions.push(player.gang.facName);
|
||||
if (Player.gang) {
|
||||
forbiddenFactions.push(Player.gang.facName);
|
||||
}
|
||||
for (const otherSleeve of player.sleeves) {
|
||||
for (const otherSleeve of Player.sleeves) {
|
||||
if (sleeve === otherSleeve) {
|
||||
continue;
|
||||
}
|
||||
@@ -84,7 +83,7 @@ function possibleFactions(player: IPlayer, sleeve: Sleeve): string[] {
|
||||
}
|
||||
|
||||
const factions = [];
|
||||
for (const fac of player.factions) {
|
||||
for (const fac of Player.factions) {
|
||||
if (!forbiddenFactions.includes(fac)) {
|
||||
factions.push(fac);
|
||||
}
|
||||
@@ -98,13 +97,13 @@ function possibleFactions(player: IPlayer, sleeve: Sleeve): string[] {
|
||||
});
|
||||
}
|
||||
|
||||
function possibleContracts(player: IPlayer, sleeve: Sleeve): string[] {
|
||||
const bb = player.bladeburner;
|
||||
function possibleContracts(sleeve: Sleeve): string[] {
|
||||
const bb = Player.bladeburner;
|
||||
if (bb === null) {
|
||||
return ["------"];
|
||||
}
|
||||
let contracts = bb.getContractNamesNetscriptFn();
|
||||
for (const otherSleeve of player.sleeves) {
|
||||
for (const otherSleeve of Player.sleeves) {
|
||||
if (sleeve === otherSleeve) {
|
||||
continue;
|
||||
}
|
||||
@@ -120,28 +119,28 @@ function possibleContracts(player: IPlayer, sleeve: Sleeve): string[] {
|
||||
}
|
||||
|
||||
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;
|
||||
["Perform Bladeburner Actions"]: (player: IPlayer, sleeve: Sleeve) => ITaskDetails;
|
||||
["Shock Recovery"]: (player: IPlayer, sleeve: Sleeve) => ITaskDetails;
|
||||
["Synchronize"]: (player: IPlayer, sleeve: Sleeve) => ITaskDetails;
|
||||
[key: string]: undefined | ((sleeve: Sleeve) => ITaskDetails);
|
||||
["------"]: (sleeve: Sleeve) => ITaskDetails;
|
||||
["Work for Company"]: (sleeve: Sleeve) => ITaskDetails;
|
||||
["Work for Faction"]: (sleeve: Sleeve) => ITaskDetails;
|
||||
["Commit Crime"]: (sleeve: Sleeve) => ITaskDetails;
|
||||
["Take University Course"]: (sleeve: Sleeve) => ITaskDetails;
|
||||
["Workout at Gym"]: (sleeve: Sleeve) => ITaskDetails;
|
||||
["Perform Bladeburner Actions"]: (sleeve: Sleeve) => ITaskDetails;
|
||||
["Shock Recovery"]: (sleeve: Sleeve) => ITaskDetails;
|
||||
["Synchronize"]: (sleeve: Sleeve) => ITaskDetails;
|
||||
} = {
|
||||
"------": (): ITaskDetails => {
|
||||
return { first: ["------"], second: () => ["------"] };
|
||||
},
|
||||
"Work for Company": (player: IPlayer, sleeve: Sleeve): ITaskDetails => {
|
||||
let jobs = possibleJobs(player, sleeve);
|
||||
"Work for Company": (sleeve: Sleeve): ITaskDetails => {
|
||||
let jobs = possibleJobs(sleeve);
|
||||
|
||||
if (jobs.length === 0) jobs = ["------"];
|
||||
return { first: jobs, second: () => ["------"] };
|
||||
},
|
||||
"Work for Faction": (player: IPlayer, sleeve: Sleeve): ITaskDetails => {
|
||||
let factions = possibleFactions(player, sleeve);
|
||||
"Work for Faction": (sleeve: Sleeve): ITaskDetails => {
|
||||
let factions = possibleFactions(sleeve);
|
||||
if (factions.length === 0) factions = ["------"];
|
||||
|
||||
return {
|
||||
@@ -168,7 +167,7 @@ const tasks: {
|
||||
"Commit Crime": (): ITaskDetails => {
|
||||
return { first: Object.values(Crimes).map((crime) => crime.name), second: () => ["------"] };
|
||||
},
|
||||
"Take University Course": (player: IPlayer, sleeve: Sleeve): ITaskDetails => {
|
||||
"Take University Course": (sleeve: Sleeve): ITaskDetails => {
|
||||
let universities: string[] = [];
|
||||
switch (sleeve.city) {
|
||||
case CityName.Aevum:
|
||||
@@ -187,7 +186,7 @@ const tasks: {
|
||||
|
||||
return { first: universitySelectorOptions, second: () => universities };
|
||||
},
|
||||
"Workout at Gym": (player: IPlayer, sleeve: Sleeve): ITaskDetails => {
|
||||
"Workout at Gym": (sleeve: Sleeve): ITaskDetails => {
|
||||
let gyms: string[] = [];
|
||||
switch (sleeve.city) {
|
||||
case CityName.Aevum:
|
||||
@@ -206,12 +205,12 @@ const tasks: {
|
||||
|
||||
return { first: gymSelectorOptions, second: () => gyms };
|
||||
},
|
||||
"Perform Bladeburner Actions": (player: IPlayer, sleeve: Sleeve): ITaskDetails => {
|
||||
"Perform Bladeburner Actions": (sleeve: Sleeve): ITaskDetails => {
|
||||
return {
|
||||
first: bladeburnerSelectorOptions,
|
||||
second: (s1: string) => {
|
||||
if (s1 === "Take on contracts") {
|
||||
return possibleContracts(player, sleeve);
|
||||
return possibleContracts(sleeve);
|
||||
} else {
|
||||
return ["------"];
|
||||
}
|
||||
@@ -227,28 +226,28 @@ const tasks: {
|
||||
};
|
||||
|
||||
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;
|
||||
["Perform Bladeburner Actions"]: (player: IPlayer, sleeve: Sleeve) => boolean;
|
||||
["Shock Recovery"]: (player: IPlayer, sleeve: Sleeve) => boolean;
|
||||
["Synchronize"]: (player: IPlayer, sleeve: Sleeve) => boolean;
|
||||
[key: string]: undefined | ((sleeve: Sleeve) => boolean);
|
||||
["------"]: (sleeve: Sleeve) => boolean;
|
||||
["Work for Company"]: (sleeve: Sleeve) => boolean;
|
||||
["Work for Faction"]: (sleeve: Sleeve) => boolean;
|
||||
["Commit Crime"]: (sleeve: Sleeve) => boolean;
|
||||
["Take University Course"]: (sleeve: Sleeve) => boolean;
|
||||
["Workout at Gym"]: (sleeve: Sleeve) => boolean;
|
||||
["Perform Bladeburner Actions"]: (sleeve: Sleeve) => boolean;
|
||||
["Shock Recovery"]: (sleeve: Sleeve) => boolean;
|
||||
["Synchronize"]: (sleeve: Sleeve) => boolean;
|
||||
} = {
|
||||
"------": () => 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,
|
||||
"Work for Company": (sleeve: Sleeve) => possibleJobs(sleeve).length > 0,
|
||||
"Work for Faction": (sleeve: Sleeve) => possibleFactions(sleeve).length > 0,
|
||||
"Commit Crime": () => true,
|
||||
"Take University Course": (player: IPlayer, sleeve: Sleeve) =>
|
||||
"Take University Course": (sleeve: Sleeve) =>
|
||||
[CityName.Aevum, CityName.Sector12, CityName.Volhaven].includes(sleeve.city),
|
||||
"Workout at Gym": (player: IPlayer, sleeve: Sleeve) =>
|
||||
"Workout at Gym": (sleeve: Sleeve) =>
|
||||
[CityName.Aevum, CityName.Sector12, CityName.Volhaven].includes(sleeve.city),
|
||||
"Perform Bladeburner Actions": (player: IPlayer) => player.inBladeburner(),
|
||||
"Shock Recovery": (player: IPlayer, sleeve: Sleeve) => sleeve.shock < 100,
|
||||
Synchronize: (player: IPlayer, sleeve: Sleeve) => sleeve.sync < 100,
|
||||
"Perform Bladeburner Actions": () => Player.inBladeburner(),
|
||||
"Shock Recovery": (sleeve: Sleeve) => sleeve.shock < 100,
|
||||
Synchronize: (sleeve: Sleeve) => sleeve.sync < 100,
|
||||
};
|
||||
|
||||
function getABC(sleeve: Sleeve): [string, string, string] {
|
||||
@@ -345,12 +344,12 @@ export function TaskSelector(props: IProps): React.ReactElement {
|
||||
const [s2, setS2] = useState(abc[2]);
|
||||
|
||||
const validActions = Object.keys(canDo).filter((k) =>
|
||||
(canDo[k] as (player: IPlayer, sleeve: Sleeve) => boolean)(props.player, props.sleeve),
|
||||
(canDo[k] as (sleeve: Sleeve) => boolean)(props.sleeve),
|
||||
);
|
||||
|
||||
const detailsF = tasks[s0];
|
||||
if (detailsF === undefined) throw new Error(`No function for task '${s0}'`);
|
||||
const details = detailsF(props.player, props.sleeve);
|
||||
const details = detailsF(props.sleeve);
|
||||
const details2 = details.second(s1);
|
||||
|
||||
if (details.first.length > 0 && !details.first.includes(s1)) {
|
||||
@@ -366,7 +365,7 @@ export function TaskSelector(props: IProps): React.ReactElement {
|
||||
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);
|
||||
const details = detailsF(props.sleeve);
|
||||
const details2 = details.second(details.first[0]) ?? ["------"];
|
||||
setS2(details2[0]);
|
||||
setS1(details.first[0]);
|
||||
|
||||
@@ -6,7 +6,7 @@ import { WorldMap } from "../../../ui/React/WorldMap";
|
||||
import { CityName } from "../../../Locations/data/CityNames";
|
||||
import { Settings } from "../../../Settings/Settings";
|
||||
import { dialogBoxCreate } from "../../../ui/React/DialogBox";
|
||||
import { use } from "../../../ui/Context";
|
||||
import { Player } from "../../../Player";
|
||||
import { Modal } from "../../../ui/React/Modal";
|
||||
import Typography from "@mui/material/Typography";
|
||||
import Button from "@mui/material/Button";
|
||||
@@ -19,14 +19,13 @@ interface IProps {
|
||||
}
|
||||
|
||||
export function TravelModal(props: IProps): React.ReactElement {
|
||||
const player = use.Player();
|
||||
function travel(city: string): void {
|
||||
if (!player.canAfford(CONSTANTS.TravelCost)) {
|
||||
if (!Player.canAfford(CONSTANTS.TravelCost)) {
|
||||
dialogBoxCreate("You cannot afford to have this sleeve travel to another city");
|
||||
}
|
||||
props.sleeve.city = city as CityName;
|
||||
player.loseMoney(CONSTANTS.TravelCost, "sleeve");
|
||||
props.sleeve.stopWork(player);
|
||||
Player.loseMoney(CONSTANTS.TravelCost, "sleeve");
|
||||
props.sleeve.stopWork();
|
||||
props.rerender();
|
||||
props.onClose();
|
||||
}
|
||||
@@ -36,7 +35,7 @@ export function TravelModal(props: IProps): React.ReactElement {
|
||||
<>
|
||||
<Typography>
|
||||
Have this sleeve travel to a different city. This affects the gyms and universities at which this sleeve can
|
||||
study. Traveling to a different city costs <Money money={CONSTANTS.TravelCost} player={player} />. It will
|
||||
study. Traveling to a different city costs <Money money={CONSTANTS.TravelCost} forPurchase={true} />. It will
|
||||
also set your current sleeve task to idle.
|
||||
</Typography>
|
||||
{Settings.DisableASCIIArt ? (
|
||||
|
||||
Reference in New Issue
Block a user