mirror of
https://github.com/bitburner-official/bitburner-src.git
synced 2024-12-18 20:25:45 +01:00
DEVMENU: Easier to add/remove sleeves (#908)
This commit is contained in:
parent
76f0f3d6d3
commit
79b0f83b5f
@ -27,19 +27,23 @@ import { AchievementsDev } from "./DevMenu/ui/AchievementsDev";
|
|||||||
import { EntropyDev } from "./DevMenu/ui/EntropyDev";
|
import { EntropyDev } from "./DevMenu/ui/EntropyDev";
|
||||||
|
|
||||||
import { Exploit } from "./Exploits/Exploit";
|
import { Exploit } from "./Exploits/Exploit";
|
||||||
|
import { useRerender } from "./ui/React/hooks";
|
||||||
|
|
||||||
export function DevMenuRoot(): React.ReactElement {
|
export function DevMenuRoot(): React.ReactElement {
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
Player.giveExploit(Exploit.YoureNotMeantToAccessThis);
|
Player.giveExploit(Exploit.YoureNotMeantToAccessThis);
|
||||||
}, []);
|
}, []);
|
||||||
|
// Pass rerender to certain subpages in case certain tabs are now valid/invalid due to changes made on those pages
|
||||||
|
// Rerender periodically in case game state changes (e.g. player starts gang or buys wse account through a script)
|
||||||
|
const rerender = useRerender(400);
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Typography>Development Menu - Only meant to be used for testing/debugging</Typography>
|
<Typography>Development Menu - Only meant to be used for testing/debugging</Typography>
|
||||||
<General />
|
<General parentRerender={rerender} />
|
||||||
<StatsDev />
|
<StatsDev />
|
||||||
<FactionsDev />
|
<FactionsDev />
|
||||||
<AugmentationsDev />
|
<AugmentationsDev />
|
||||||
<SourceFilesDev />
|
<SourceFilesDev parentRerender={rerender} />
|
||||||
<ProgramsDev />
|
<ProgramsDev />
|
||||||
<ServersDev />
|
<ServersDev />
|
||||||
<CompaniesDev />
|
<CompaniesDev />
|
||||||
|
@ -23,11 +23,10 @@ import { Page } from "../../ui/Router";
|
|||||||
import { Bladeburner } from "../../Bladeburner/Bladeburner";
|
import { Bladeburner } from "../../Bladeburner/Bladeburner";
|
||||||
import { GangConstants } from "../../Gang/data/Constants";
|
import { GangConstants } from "../../Gang/data/Constants";
|
||||||
import { checkForMessagesToSend } from "../../Message/MessageHelpers";
|
import { checkForMessagesToSend } from "../../Message/MessageHelpers";
|
||||||
import { ThemeEvents } from "../../Themes/ui/Theme";
|
|
||||||
import { getEnumHelper } from "../../utils/EnumHelper";
|
import { getEnumHelper } from "../../utils/EnumHelper";
|
||||||
import { formatRam } from "../../ui/formatNumber";
|
import { formatRam } from "../../ui/formatNumber";
|
||||||
|
|
||||||
export function General(): React.ReactElement {
|
export function General({ parentRerender }: { parentRerender: () => void }): React.ReactElement {
|
||||||
const rerender = useRerender(400);
|
const rerender = useRerender(400);
|
||||||
const [error, setError] = useState(false);
|
const [error, setError] = useState(false);
|
||||||
const [corporationName, setCorporationName] = useState("");
|
const [corporationName, setCorporationName] = useState("");
|
||||||
@ -64,38 +63,32 @@ export function General(): React.ReactElement {
|
|||||||
// Corp functions
|
// Corp functions
|
||||||
const createCorporation = () => {
|
const createCorporation = () => {
|
||||||
Player.startCorporation(corporationName, false);
|
Player.startCorporation(corporationName, false);
|
||||||
// Rerender so the corp menu option will show up immediately on the devmenu page selection
|
parentRerender();
|
||||||
ThemeEvents.emit();
|
|
||||||
};
|
};
|
||||||
const destroyCorporation = () => {
|
const destroyCorporation = () => {
|
||||||
Player.corporation = null;
|
Player.corporation = null;
|
||||||
// Rerender so the corp menu option will be removed immediately on the devmenu page selection
|
parentRerender();
|
||||||
ThemeEvents.emit();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Blade functions
|
// Blade functions
|
||||||
const joinBladeburner = () => {
|
const joinBladeburner = () => {
|
||||||
Player.bladeburner = new Bladeburner();
|
Player.bladeburner = new Bladeburner();
|
||||||
// Rerender so the blade menu option will show up immediately on the devmenu page selection
|
parentRerender();
|
||||||
ThemeEvents.emit();
|
|
||||||
};
|
};
|
||||||
const leaveBladeburner = () => {
|
const leaveBladeburner = () => {
|
||||||
Player.bladeburner = null;
|
Player.bladeburner = null;
|
||||||
// Rerender so the blade menu option will be removed immediately on the devmenu page selection
|
parentRerender();
|
||||||
ThemeEvents.emit();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Gang functions
|
// Gang functions
|
||||||
const startGang = () => {
|
const startGang = () => {
|
||||||
const isHacking = gangFaction === FactionName.NiteSec || gangFaction === FactionName.TheBlackHand;
|
const isHacking = gangFaction === FactionName.NiteSec || gangFaction === FactionName.TheBlackHand;
|
||||||
Player.startGang(gangFaction, isHacking);
|
Player.startGang(gangFaction, isHacking);
|
||||||
// Rerender so the gang menu option will show up immediately on the devmenu page selection
|
parentRerender();
|
||||||
ThemeEvents.emit();
|
|
||||||
};
|
};
|
||||||
const stopGang = () => {
|
const stopGang = () => {
|
||||||
Player.gang = null;
|
Player.gang = null;
|
||||||
// Rerender so the gang menu option will be removed immediately on the devmenu page selection
|
parentRerender();
|
||||||
ThemeEvents.emit();
|
|
||||||
};
|
};
|
||||||
const setGangFactionDropdown = (event: SelectChangeEvent) => {
|
const setGangFactionDropdown = (event: SelectChangeEvent) => {
|
||||||
// Todo: Make this a more specific check when a GangName enumlike is added
|
// Todo: Make this a more specific check when a GangName enumlike is added
|
||||||
|
@ -71,6 +71,11 @@ export function SleevesDev(): React.ReactElement {
|
|||||||
<Button onClick={sleeveSyncClearAll}>Clear all</Button>
|
<Button onClick={sleeveSyncClearAll}>Clear all</Button>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<Typography>Total:</Typography>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td colSpan={3}>
|
<td colSpan={3}>
|
||||||
<Adjuster
|
<Adjuster
|
||||||
|
@ -5,7 +5,9 @@ import ExpandMoreIcon from "@mui/icons-material/ExpandMore";
|
|||||||
import { makeStyles } from "@mui/styles";
|
import { makeStyles } from "@mui/styles";
|
||||||
|
|
||||||
import { Player } from "@player";
|
import { Player } from "@player";
|
||||||
import { useRerender } from "../../ui/React/hooks";
|
import { Sleeve } from "../../PersonObjects/Sleeve/Sleeve";
|
||||||
|
import { ButtonWithTooltip } from "../../ui/Components/ButtonWithTooltip";
|
||||||
|
import { MaxSleevesFromCovenant } from "../../PersonObjects/Sleeve/SleeveCovenantPurchases";
|
||||||
|
|
||||||
// Update as additional BitNodes get implemented
|
// Update as additional BitNodes get implemented
|
||||||
const validSFN = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13];
|
const validSFN = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13];
|
||||||
@ -16,11 +18,11 @@ const useStyles = makeStyles({
|
|||||||
},
|
},
|
||||||
extraInfo: {
|
extraInfo: {
|
||||||
marginLeft: "0.5em",
|
marginLeft: "0.5em",
|
||||||
|
marginRight: "0.5em",
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export function SourceFilesDev(): React.ReactElement {
|
export function SourceFilesDev({ parentRerender }: { parentRerender: () => void }): React.ReactElement {
|
||||||
const rerender = useRerender();
|
|
||||||
const classes = useStyles();
|
const classes = useStyles();
|
||||||
|
|
||||||
const setSF = useCallback(
|
const setSF = useCallback(
|
||||||
@ -30,18 +32,34 @@ export function SourceFilesDev(): React.ReactElement {
|
|||||||
}
|
}
|
||||||
if (sfLvl === 0) {
|
if (sfLvl === 0) {
|
||||||
Player.sourceFiles.delete(sfN);
|
Player.sourceFiles.delete(sfN);
|
||||||
rerender();
|
if (sfN === 10) Sleeve.recalculateNumOwned();
|
||||||
|
parentRerender();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Player.sourceFiles.set(sfN, sfLvl);
|
Player.sourceFiles.set(sfN, sfLvl);
|
||||||
rerender();
|
if (sfN === 10) Sleeve.recalculateNumOwned();
|
||||||
|
parentRerender();
|
||||||
},
|
},
|
||||||
[rerender],
|
[parentRerender],
|
||||||
);
|
);
|
||||||
|
|
||||||
const setAllSF = useCallback((sfLvl: number) => () => validSFN.forEach((sfN) => setSF(sfN, sfLvl)()), [setSF]);
|
const setAllSF = useCallback((sfLvl: number) => () => validSFN.forEach((sfN) => setSF(sfN, sfLvl)()), [setSF]);
|
||||||
const clearExploits = () => (Player.exploits = []);
|
const clearExploits = () => (Player.exploits = []);
|
||||||
|
|
||||||
|
const addSleeve = useCallback(() => {
|
||||||
|
if (Player.sleevesFromCovenant >= 10) return;
|
||||||
|
Player.sleevesFromCovenant += 1;
|
||||||
|
Sleeve.recalculateNumOwned();
|
||||||
|
parentRerender();
|
||||||
|
}, [parentRerender]);
|
||||||
|
|
||||||
|
const removeSleeve = useCallback(() => {
|
||||||
|
if (Player.sleevesFromCovenant <= 0) return;
|
||||||
|
Player.sleevesFromCovenant -= 1;
|
||||||
|
Sleeve.recalculateNumOwned();
|
||||||
|
parentRerender();
|
||||||
|
}, [parentRerender]);
|
||||||
|
|
||||||
const devLvls = [0, 1, 2, 3];
|
const devLvls = [0, 1, 2, 3];
|
||||||
|
|
||||||
const buttonRow = (sfN?: number) => {
|
const buttonRow = (sfN?: number) => {
|
||||||
@ -66,6 +84,23 @@ export function SourceFilesDev(): React.ReactElement {
|
|||||||
</Button>
|
</Button>
|
||||||
))}
|
))}
|
||||||
{sfN && <Typography className={classes.extraInfo}>{`Level: ${level}`}</Typography>}
|
{sfN && <Typography className={classes.extraInfo}>{`Level: ${level}`}</Typography>}
|
||||||
|
{sfN === 10 && (
|
||||||
|
<>
|
||||||
|
<ButtonWithTooltip
|
||||||
|
disabledTooltip={Player.sleevesFromCovenant <= 0 ? "Already at minimum" : ""}
|
||||||
|
onClick={removeSleeve}
|
||||||
|
>
|
||||||
|
-1 sleeve
|
||||||
|
</ButtonWithTooltip>
|
||||||
|
<ButtonWithTooltip
|
||||||
|
disabledTooltip={Player.sleevesFromCovenant >= MaxSleevesFromCovenant ? "Already at maximum" : ""}
|
||||||
|
onClick={addSleeve}
|
||||||
|
>
|
||||||
|
+1 sleeve
|
||||||
|
</ButtonWithTooltip>
|
||||||
|
<Typography className={classes.extraInfo}>Extra sleeves: {Player.sleevesFromCovenant}</Typography>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</ButtonGroup>
|
</ButtonGroup>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
@ -32,7 +32,7 @@ import { resetGangs } from "../../Gang/AllGangs";
|
|||||||
import { Cities } from "../../Locations/Cities";
|
import { Cities } from "../../Locations/Cities";
|
||||||
import { Locations } from "../../Locations/Locations";
|
import { Locations } from "../../Locations/Locations";
|
||||||
import { Sleeve } from "../Sleeve/Sleeve";
|
import { Sleeve } from "../Sleeve/Sleeve";
|
||||||
import { isSleeveCompanyWork } from "../Sleeve/Work/SleeveCompanyWork";
|
import { SleeveWorkType } from "../Sleeve/Work/Work";
|
||||||
import { calculateSkillProgress as calculateSkillProgressF, ISkillProgress } from "../formulas/skill";
|
import { calculateSkillProgress as calculateSkillProgressF, ISkillProgress } from "../formulas/skill";
|
||||||
import { AddToAllServers, createUniqueRandomIp } from "../../Server/AllServers";
|
import { AddToAllServers, createUniqueRandomIp } from "../../Server/AllServers";
|
||||||
import { safelyCreateUniqueServer } from "../../Server/ServerHelpers";
|
import { safelyCreateUniqueServer } from "../../Server/ServerHelpers";
|
||||||
@ -109,11 +109,7 @@ export function prestigeAugmentation(this: PlayerObject): void {
|
|||||||
|
|
||||||
this.queuedAugmentations = [];
|
this.queuedAugmentations = [];
|
||||||
|
|
||||||
const numSleeves = Math.min(3, this.sourceFileLvl(10) + (this.bitNodeN === 10 ? 1 : 0)) + this.sleevesFromCovenant;
|
Sleeve.recalculateNumOwned();
|
||||||
if (this.sleeves.length > numSleeves) this.sleeves.length = numSleeves;
|
|
||||||
for (let i = this.sleeves.length; i < numSleeves; i++) {
|
|
||||||
this.sleeves.push(new Sleeve());
|
|
||||||
}
|
|
||||||
|
|
||||||
this.sleeves.forEach((sleeve) => (sleeve.shock <= 0 ? sleeve.synchronize() : sleeve.shockRecovery()));
|
this.sleeves.forEach((sleeve) => (sleeve.shock <= 0 ? sleeve.synchronize() : sleeve.shockRecovery()));
|
||||||
|
|
||||||
@ -369,7 +365,7 @@ export function quitJob(this: PlayerObject, company: CompanyName): void {
|
|||||||
this.finishWork(true);
|
this.finishWork(true);
|
||||||
}
|
}
|
||||||
for (const sleeve of this.sleeves) {
|
for (const sleeve of this.sleeves) {
|
||||||
if (isSleeveCompanyWork(sleeve.currentWork) && sleeve.currentWork.companyName === company) {
|
if (sleeve.currentWork?.type === SleeveWorkType.COMPANY && sleeve.currentWork.companyName === company) {
|
||||||
sleeve.stopWork();
|
sleeve.stopWork();
|
||||||
dialogBoxCreate(`You quit ${company} while one of your sleeves was working there. The sleeve is now idle.`);
|
dialogBoxCreate(`You quit ${company} while one of your sleeves was working there. The sleeve is now idle.`);
|
||||||
}
|
}
|
||||||
|
@ -464,6 +464,19 @@ export class Sleeve extends Person implements SleevePerson {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static recalculateNumOwned() {
|
||||||
|
const numSleeves =
|
||||||
|
Math.min(3, Player.sourceFileLvl(10) + (Player.bitNodeN === 10 ? 1 : 0)) + Player.sleevesFromCovenant;
|
||||||
|
while (Player.sleeves.length > numSleeves) {
|
||||||
|
const destroyedSleeve = Player.sleeves.pop();
|
||||||
|
// This should not happen, but avoid an infinite loop in case sleevesFromCovenent or sf10 level are somehow negative
|
||||||
|
if (!destroyedSleeve) return;
|
||||||
|
// Stop work, to prevent destroyed sleeves from continuing their tasks in the void
|
||||||
|
destroyedSleeve.stopWork();
|
||||||
|
}
|
||||||
|
while (Player.sleeves.length < numSleeves) Player.sleeves.push(new Sleeve());
|
||||||
|
}
|
||||||
|
|
||||||
whoAmI(): string {
|
whoAmI(): string {
|
||||||
return "Sleeve";
|
return "Sleeve";
|
||||||
}
|
}
|
||||||
|
@ -47,7 +47,7 @@ export function CovenantPurchasesRoot(props: IProps): React.ReactElement {
|
|||||||
if (Player.canAfford(purchaseCost())) {
|
if (Player.canAfford(purchaseCost())) {
|
||||||
Player.loseMoney(purchaseCost(), "sleeves");
|
Player.loseMoney(purchaseCost(), "sleeves");
|
||||||
Player.sleevesFromCovenant += 1;
|
Player.sleevesFromCovenant += 1;
|
||||||
Player.sleeves.push(new Sleeve());
|
Sleeve.recalculateNumOwned();
|
||||||
rerender();
|
rerender();
|
||||||
} else {
|
} else {
|
||||||
dialogBoxCreate(`You cannot afford to purchase a Duplicate Sleeve`);
|
dialogBoxCreate(`You cannot afford to purchase a Duplicate Sleeve`);
|
||||||
|
Loading…
Reference in New Issue
Block a user