mirror of
https://github.com/bitburner-official/bitburner-src.git
synced 2024-12-20 21:25:47 +01:00
commit1
This commit is contained in:
parent
cc2246213f
commit
83d357e758
@ -347,18 +347,18 @@ export const achievements: IMap<Achievement> = {
|
||||
FIRST_HACKNET_NODE: {
|
||||
...achievementData["FIRST_HACKNET_NODE"],
|
||||
Icon: "node",
|
||||
Condition: () => !hasHacknetServers(Player) && Player.hacknetNodes.length > 0,
|
||||
Condition: () => !hasHacknetServers() && Player.hacknetNodes.length > 0,
|
||||
},
|
||||
"30_HACKNET_NODE": {
|
||||
...achievementData["30_HACKNET_NODE"],
|
||||
Icon: "hacknet-all",
|
||||
Condition: () => !hasHacknetServers(Player) && Player.hacknetNodes.length >= 30,
|
||||
Condition: () => !hasHacknetServers() && Player.hacknetNodes.length >= 30,
|
||||
},
|
||||
MAX_HACKNET_NODE: {
|
||||
...achievementData["MAX_HACKNET_NODE"],
|
||||
Icon: "hacknet-max",
|
||||
Condition: (): boolean => {
|
||||
if (hasHacknetServers(Player)) return false;
|
||||
if (hasHacknetServers()) return false;
|
||||
for (const h of Player.hacknetNodes) {
|
||||
if (!(h instanceof HacknetNode)) return false;
|
||||
if (
|
||||
@ -374,7 +374,7 @@ export const achievements: IMap<Achievement> = {
|
||||
HACKNET_NODE_10M: {
|
||||
...achievementData["HACKNET_NODE_10M"],
|
||||
Icon: "hacknet-10m",
|
||||
Condition: () => !hasHacknetServers(Player) && Player.moneySourceB.hacknet >= 10e6,
|
||||
Condition: () => !hasHacknetServers() && Player.moneySourceB.hacknet >= 10e6,
|
||||
},
|
||||
REPUTATION_10M: {
|
||||
...achievementData["REPUTATION_10M"],
|
||||
@ -515,14 +515,14 @@ export const achievements: IMap<Achievement> = {
|
||||
...achievementData["FIRST_HACKNET_SERVER"],
|
||||
Icon: "HASHNET",
|
||||
Visible: () => hasAccessToSF(Player, 9),
|
||||
Condition: () => hasHacknetServers(Player) && Player.hacknetNodes.length > 0,
|
||||
Condition: () => hasHacknetServers() && Player.hacknetNodes.length > 0,
|
||||
AdditionalUnlock: [achievementData.FIRST_HACKNET_NODE.ID],
|
||||
},
|
||||
ALL_HACKNET_SERVER: {
|
||||
...achievementData["ALL_HACKNET_SERVER"],
|
||||
Icon: "HASHNETALL",
|
||||
Visible: () => hasAccessToSF(Player, 9),
|
||||
Condition: () => hasHacknetServers(Player) && Player.hacknetNodes.length === HacknetServerConstants.MaxServers,
|
||||
Condition: () => hasHacknetServers() && Player.hacknetNodes.length === HacknetServerConstants.MaxServers,
|
||||
AdditionalUnlock: [achievementData["30_HACKNET_NODE"].ID],
|
||||
},
|
||||
MAX_HACKNET_SERVER: {
|
||||
@ -530,7 +530,7 @@ export const achievements: IMap<Achievement> = {
|
||||
Icon: "HASHNETALL",
|
||||
Visible: () => hasAccessToSF(Player, 9),
|
||||
Condition: (): boolean => {
|
||||
if (!hasHacknetServers(Player)) return false;
|
||||
if (!hasHacknetServers()) return false;
|
||||
for (const h of Player.hacknetNodes) {
|
||||
if (typeof h !== "string") return false;
|
||||
const hs = GetServer(h);
|
||||
@ -551,7 +551,7 @@ export const achievements: IMap<Achievement> = {
|
||||
...achievementData["HACKNET_SERVER_1B"],
|
||||
Icon: "HASHNETMONEY",
|
||||
Visible: () => hasAccessToSF(Player, 9),
|
||||
Condition: () => hasHacknetServers(Player) && Player.moneySourceB.hacknet >= 1e9,
|
||||
Condition: () => hasHacknetServers() && Player.moneySourceB.hacknet >= 1e9,
|
||||
AdditionalUnlock: [achievementData.HACKNET_NODE_10M.ID],
|
||||
},
|
||||
MAX_CACHE: {
|
||||
@ -559,7 +559,7 @@ export const achievements: IMap<Achievement> = {
|
||||
Icon: "HASHNETCAP",
|
||||
Visible: () => hasAccessToSF(Player, 9),
|
||||
Condition: () =>
|
||||
hasHacknetServers(Player) &&
|
||||
hasHacknetServers() &&
|
||||
Player.hashManager.hashes === Player.hashManager.capacity &&
|
||||
Player.hashManager.capacity > 0,
|
||||
},
|
||||
|
@ -8,7 +8,7 @@ import { Money } from "../ui/React/Money";
|
||||
|
||||
import { Generic_fromJSON, Generic_toJSON, IReviverValue, Reviver } from "../utils/JSONReviver";
|
||||
import { FactionNames } from "../Faction/data/FactionNames";
|
||||
import { IPlayer } from "../PersonObjects/IPlayer";
|
||||
import { Player } from "../Player";
|
||||
import { AugmentationNames } from "./data/AugmentationNames";
|
||||
import { CONSTANTS } from "../Constants";
|
||||
import { StaticAugmentations } from "./StaticAugmentations";
|
||||
@ -531,26 +531,26 @@ export class Augmentation {
|
||||
}
|
||||
}
|
||||
|
||||
getCost(player: IPlayer): AugmentationCosts {
|
||||
getCost(): AugmentationCosts {
|
||||
const augmentationReference = StaticAugmentations[this.name];
|
||||
let moneyCost = augmentationReference.baseCost;
|
||||
let repCost = augmentationReference.baseRepRequirement;
|
||||
|
||||
if (augmentationReference.name === AugmentationNames.NeuroFluxGovernor) {
|
||||
let nextLevel = this.getLevel(player);
|
||||
let nextLevel = this.getLevel();
|
||||
--nextLevel;
|
||||
const multiplier = Math.pow(CONSTANTS.NeuroFluxGovernorLevelMult, nextLevel);
|
||||
repCost = augmentationReference.baseRepRequirement * multiplier * BitNodeMultipliers.AugmentationRepCost;
|
||||
moneyCost = augmentationReference.baseCost * multiplier * BitNodeMultipliers.AugmentationMoneyCost;
|
||||
|
||||
for (let i = 0; i < player.queuedAugmentations.length; ++i) {
|
||||
for (let i = 0; i < Player.queuedAugmentations.length; ++i) {
|
||||
moneyCost *= getBaseAugmentationPriceMultiplier();
|
||||
}
|
||||
} else if (augmentationReference.factions.includes(FactionNames.ShadowsOfAnarchy)) {
|
||||
const soaAugmentationNames = initSoAAugmentations().map((augmentation) => augmentation.name);
|
||||
const soaMultiplier = Math.pow(
|
||||
CONSTANTS.SoACostMult,
|
||||
soaAugmentationNames.filter((augmentationName) => player.hasAugmentation(augmentationName)).length,
|
||||
soaAugmentationNames.filter((augmentationName) => Player.hasAugmentation(augmentationName)).length,
|
||||
);
|
||||
moneyCost = augmentationReference.baseCost * soaMultiplier;
|
||||
if (soaAugmentationNames.find((augmentationName) => augmentationName === augmentationReference.name)) {
|
||||
@ -566,19 +566,19 @@ export class Augmentation {
|
||||
return { moneyCost, repCost };
|
||||
}
|
||||
|
||||
getLevel(player: IPlayer): number {
|
||||
getLevel(): number {
|
||||
// Get current Neuroflux level based on Player's augmentations
|
||||
if (this.name === AugmentationNames.NeuroFluxGovernor) {
|
||||
let currLevel = 0;
|
||||
for (let i = 0; i < player.augmentations.length; ++i) {
|
||||
if (player.augmentations[i].name === AugmentationNames.NeuroFluxGovernor) {
|
||||
currLevel = player.augmentations[i].level;
|
||||
for (let i = 0; i < Player.augmentations.length; ++i) {
|
||||
if (Player.augmentations[i].name === AugmentationNames.NeuroFluxGovernor) {
|
||||
currLevel = Player.augmentations[i].level;
|
||||
}
|
||||
}
|
||||
|
||||
// Account for purchased but uninstalled Augmentations
|
||||
for (let i = 0; i < player.queuedAugmentations.length; ++i) {
|
||||
if (player.queuedAugmentations[i].name == AugmentationNames.NeuroFluxGovernor) {
|
||||
for (let i = 0; i < Player.queuedAugmentations.length; ++i) {
|
||||
if (Player.queuedAugmentations[i].name == AugmentationNames.NeuroFluxGovernor) {
|
||||
++currLevel;
|
||||
}
|
||||
}
|
||||
|
@ -20,7 +20,7 @@ import Paper from "@mui/material/Paper";
|
||||
import Container from "@mui/material/Container";
|
||||
import { Settings } from "../../Settings/Settings";
|
||||
import { ConfirmationModal } from "../../ui/React/ConfirmationModal";
|
||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||
import { Player } from "../../Player";
|
||||
import { AugmentationNames } from "../data/AugmentationNames";
|
||||
import { StaticAugmentations } from "../StaticAugmentations";
|
||||
import { CONSTANTS } from "../../Constants";
|
||||
@ -29,12 +29,8 @@ import { Info } from "@mui/icons-material";
|
||||
import { Link } from "@mui/material";
|
||||
import { AlertEvents } from "../../ui/React/AlertManager";
|
||||
|
||||
interface NFGDisplayProps {
|
||||
player: IPlayer;
|
||||
}
|
||||
|
||||
const NeuroFluxDisplay = ({ player }: NFGDisplayProps): React.ReactElement => {
|
||||
const level = player.augmentations.find((e) => e.name === AugmentationNames.NeuroFluxGovernor)?.level ?? 0;
|
||||
const NeuroFluxDisplay = (): React.ReactElement => {
|
||||
const level = Player.augmentations.find((e) => e.name === AugmentationNames.NeuroFluxGovernor)?.level ?? 0;
|
||||
|
||||
const openBloodDonation = () => {
|
||||
AlertEvents.emit(
|
||||
@ -67,18 +63,14 @@ const NeuroFluxDisplay = ({ player }: NFGDisplayProps): React.ReactElement => {
|
||||
);
|
||||
};
|
||||
|
||||
interface EntropyDisplayProps {
|
||||
player: IPlayer;
|
||||
}
|
||||
|
||||
const EntropyDisplay = ({ player }: EntropyDisplayProps): React.ReactElement => {
|
||||
return player.entropy > 0 ? (
|
||||
const EntropyDisplay = (): React.ReactElement => {
|
||||
return Player.entropy > 0 ? (
|
||||
<Paper sx={{ p: 1 }}>
|
||||
<Typography variant="h5" color={Settings.theme.error}>
|
||||
Entropy Virus - Level {player.entropy}
|
||||
Entropy Virus - Level {Player.entropy}
|
||||
</Typography>
|
||||
<Typography color={Settings.theme.error}>
|
||||
<b>All multipliers decreased by:</b> {formatNumber((1 - CONSTANTS.EntropyEffect ** player.entropy) * 100, 3)}%
|
||||
<b>All multipliers decreased by:</b> {formatNumber((1 - CONSTANTS.EntropyEffect ** Player.entropy) * 100, 3)}%
|
||||
(multiplicative)
|
||||
</Typography>
|
||||
</Paper>
|
||||
@ -222,8 +214,8 @@ export function AugmentationsRoot(props: IProps): React.ReactElement {
|
||||
gap: 1,
|
||||
}}
|
||||
>
|
||||
<NeuroFluxDisplay player={player} />
|
||||
<EntropyDisplay player={player} />
|
||||
<NeuroFluxDisplay />
|
||||
<EntropyDisplay />
|
||||
</Box>
|
||||
|
||||
<Box>
|
||||
|
@ -6,7 +6,7 @@ import { CheckBox, CheckBoxOutlineBlank, CheckCircle, NewReleases, Report } from
|
||||
import { Box, Button, Container, Paper, Tooltip, Typography } from "@mui/material";
|
||||
import React, { useState } from "react";
|
||||
import { Faction } from "../../Faction/Faction";
|
||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||
import { Player } from "../../Player";
|
||||
import { Settings } from "../../Settings/Settings";
|
||||
import { numeralWrapper } from "../../ui/numeralFormat";
|
||||
import { Augmentation } from "../Augmentation";
|
||||
@ -15,12 +15,11 @@ import { StaticAugmentations } from "../StaticAugmentations";
|
||||
import { PurchaseAugmentationModal } from "./PurchaseAugmentationModal";
|
||||
|
||||
interface IPreReqsProps {
|
||||
player: IPlayer;
|
||||
aug: Augmentation;
|
||||
}
|
||||
|
||||
const PreReqs = (props: IPreReqsProps): React.ReactElement => {
|
||||
const ownedPreReqs = props.aug.prereqs.filter((aug) => props.player.hasAugmentation(aug));
|
||||
const ownedPreReqs = props.aug.prereqs.filter((aug) => Player.hasAugmentation(aug));
|
||||
const hasPreReqs = props.aug.prereqs.length > 0 && ownedPreReqs.length === props.aug.prereqs.length;
|
||||
|
||||
return (
|
||||
@ -32,7 +31,7 @@ const PreReqs = (props: IPreReqsProps): React.ReactElement => {
|
||||
</Typography>
|
||||
{props.aug.prereqs.map((preAug) => (
|
||||
<Requirement
|
||||
fulfilled={props.player.hasAugmentation(preAug)}
|
||||
fulfilled={Player.hasAugmentation(preAug)}
|
||||
value={preAug}
|
||||
color={Settings.theme.money}
|
||||
key={preAug}
|
||||
@ -68,7 +67,6 @@ const PreReqs = (props: IPreReqsProps): React.ReactElement => {
|
||||
};
|
||||
|
||||
interface IExclusiveProps {
|
||||
player: IPlayer;
|
||||
aug: Augmentation;
|
||||
}
|
||||
|
||||
@ -85,12 +83,12 @@ const Exclusive = (props: IExclusiveProps): React.ReactElement => {
|
||||
<li>
|
||||
<b>{props.aug.factions[0]}</b> faction
|
||||
</li>
|
||||
{props.player.isAwareOfGang() && !props.aug.isSpecial && (
|
||||
{Player.isAwareOfGang() && !props.aug.isSpecial && (
|
||||
<li>
|
||||
Certain <b>gangs</b>
|
||||
</li>
|
||||
)}
|
||||
{props.player.canAccessGrafting() &&
|
||||
{Player.canAccessGrafting() &&
|
||||
!props.aug.isSpecial &&
|
||||
props.aug.name !== AugmentationNames.TheRedPill && (
|
||||
<li>
|
||||
@ -130,10 +128,9 @@ const Requirement = (props: IReqProps): React.ReactElement => {
|
||||
interface IPurchasableAugsProps {
|
||||
augNames: string[];
|
||||
ownedAugNames: string[];
|
||||
player: IPlayer;
|
||||
|
||||
canPurchase: (player: IPlayer, aug: Augmentation) => boolean;
|
||||
purchaseAugmentation: (player: IPlayer, aug: Augmentation, showModal: (open: boolean) => void) => void;
|
||||
canPurchase: (aug: Augmentation) => boolean;
|
||||
purchaseAugmentation: (aug: Augmentation, showModal: (open: boolean) => void) => void;
|
||||
|
||||
rep?: number;
|
||||
sleeveAugs?: boolean;
|
||||
@ -167,7 +164,7 @@ export function PurchasableAugmentation(props: IPurchasableAugProps): React.Reac
|
||||
const [open, setOpen] = useState(false);
|
||||
|
||||
const aug = StaticAugmentations[props.augName];
|
||||
const augCosts = aug.getCost(props.parent.player);
|
||||
const augCosts = aug.getCost();
|
||||
const cost = props.parent.sleeveAugs ? aug.baseCost : augCosts.moneyCost;
|
||||
const repCost = augCosts.repCost;
|
||||
const info = typeof aug.info === "string" ? <span>{aug.info}</span> : aug.info;
|
||||
@ -195,11 +192,11 @@ export function PurchasableAugmentation(props: IPurchasableAugProps): React.Reac
|
||||
<Box sx={{ display: "flex", alignItems: "center" }}>
|
||||
<Button
|
||||
onClick={() =>
|
||||
props.parent.purchaseAugmentation(props.parent.player, aug, (open): void => {
|
||||
props.parent.purchaseAugmentation(aug, (open): void => {
|
||||
setOpen(open);
|
||||
})
|
||||
}
|
||||
disabled={!props.parent.canPurchase(props.parent.player, aug) || props.owned}
|
||||
disabled={!props.parent.canPurchase(aug) || props.owned}
|
||||
sx={{ width: "48px", height: "36px", float: "left", clear: "none", mr: 1 }}
|
||||
>
|
||||
{props.owned ? "Owned" : "Buy"}
|
||||
@ -213,7 +210,7 @@ export function PurchasableAugmentation(props: IPurchasableAugProps): React.Reac
|
||||
<Typography variant="h5">
|
||||
{props.augName}
|
||||
{props.augName === AugmentationNames.NeuroFluxGovernor &&
|
||||
` - Level ${aug.getLevel(props.parent.player)}`}
|
||||
` - Level ${aug.getLevel()}`}
|
||||
</Typography>
|
||||
<Typography>{description}</Typography>
|
||||
</>
|
||||
@ -226,20 +223,20 @@ export function PurchasableAugmentation(props: IPurchasableAugProps): React.Reac
|
||||
whiteSpace: "nowrap",
|
||||
overflow: "hidden",
|
||||
color:
|
||||
props.owned || !props.parent.canPurchase(props.parent.player, aug)
|
||||
props.owned || !props.parent.canPurchase(aug)
|
||||
? Settings.theme.disabled
|
||||
: Settings.theme.primary,
|
||||
}}
|
||||
>
|
||||
{aug.name}
|
||||
{aug.name === AugmentationNames.NeuroFluxGovernor && ` - Level ${aug.getLevel(props.parent.player)}`}
|
||||
{aug.name === AugmentationNames.NeuroFluxGovernor && ` - Level ${aug.getLevel()}`}
|
||||
</Typography>
|
||||
</Tooltip>
|
||||
|
||||
{aug.factions.length === 1 && !props.parent.sleeveAugs && (
|
||||
<Exclusive player={props.parent.player} aug={aug} />
|
||||
<Exclusive aug={aug} />
|
||||
)}
|
||||
{aug.prereqs.length > 0 && !props.parent.sleeveAugs && <PreReqs player={props.parent.player} aug={aug} />}
|
||||
{aug.prereqs.length > 0 && !props.parent.sleeveAugs && <PreReqs aug={aug} />}
|
||||
</Box>
|
||||
</Box>
|
||||
</Box>
|
||||
@ -247,7 +244,7 @@ export function PurchasableAugmentation(props: IPurchasableAugProps): React.Reac
|
||||
{props.owned || (
|
||||
<Box sx={{ display: "grid", alignItems: "center", gridTemplateColumns: "1fr 1fr" }}>
|
||||
<Requirement
|
||||
fulfilled={cost === 0 || props.parent.player.money > cost}
|
||||
fulfilled={cost === 0 || Player.money > cost}
|
||||
value={numeralWrapper.formatMoney(cost)}
|
||||
color={Settings.theme.money}
|
||||
/>
|
||||
|
@ -44,7 +44,7 @@ export function PurchaseAugmentationModal(props: IProps): React.ReactElement {
|
||||
<br />
|
||||
<br />
|
||||
Would you like to purchase the {props.aug.name} Augmentation for
|
||||
<Money money={props.aug.getCost(player).moneyCost} />?
|
||||
<Money money={props.aug.getCost().moneyCost} />?
|
||||
<br />
|
||||
<br />
|
||||
</Typography>
|
||||
|
@ -1,6 +1,6 @@
|
||||
import React from "react";
|
||||
import { BitNodeMultipliers, IBitNodeMultipliers } from "./BitNodeMultipliers";
|
||||
import { IPlayer } from "../PersonObjects/IPlayer";
|
||||
import { Player } from "../Player";
|
||||
import { IMap } from "../types";
|
||||
import { FactionNames } from "../Faction/data/FactionNames";
|
||||
import { CityName } from "../Locations/data/CityNames";
|
||||
@ -876,6 +876,6 @@ export function getBitNodeMultipliers(n: number, lvl: number): IBitNodeMultiplie
|
||||
}
|
||||
}
|
||||
|
||||
export function initBitNodeMultipliers(p: IPlayer): void {
|
||||
Object.assign(BitNodeMultipliers, getBitNodeMultipliers(p.bitNodeN, p.sourceFileLvl(p.bitNodeN)));
|
||||
export function initBitNodeMultipliers(): void {
|
||||
Object.assign(BitNodeMultipliers, getBitNodeMultipliers(Player.bitNodeN, Player.sourceFileLvl(Player.bitNodeN)));
|
||||
}
|
||||
|
@ -14,10 +14,10 @@ import { Skills } from "./Skills";
|
||||
import { Skill } from "./Skill";
|
||||
import { City } from "./City";
|
||||
import { IAction } from "./IAction";
|
||||
import { IPlayer } from "../PersonObjects/IPlayer";
|
||||
import { Player } from "../Player";
|
||||
import { createTaskTracker, ITaskTracker } from "../PersonObjects/ITaskTracker";
|
||||
import { IPerson } from "../PersonObjects/IPerson";
|
||||
import { IRouter } from "../ui/Router";
|
||||
import { Router } from "../ui/GameRoot";
|
||||
import { ConsoleHelpText } from "./data/Help";
|
||||
import { exceptionAlert } from "../utils/helpers/exceptionAlert";
|
||||
import { getRandomInt } from "../utils/helpers/getRandomInt";
|
||||
@ -39,7 +39,7 @@ import { KEY } from "../utils/helpers/keyCodes";
|
||||
import { isSleeveInfiltrateWork } from "../PersonObjects/Sleeve/Work/SleeveInfiltrateWork";
|
||||
import { isSleeveSupportWork } from "../PersonObjects/Sleeve/Work/SleeveSupportWork";
|
||||
|
||||
interface BlackOpsAttempt {
|
||||
export interface BlackOpsAttempt {
|
||||
error?: string;
|
||||
isAvailable?: boolean;
|
||||
action?: BlackOperation;
|
||||
@ -100,7 +100,7 @@ export class Bladeburner implements IBladeburner {
|
||||
consoleHistory: string[] = [];
|
||||
consoleLogs: string[] = ["Bladeburner Console", "Type 'help' to see console commands"];
|
||||
|
||||
constructor(player?: IPlayer) {
|
||||
constructor() {
|
||||
for (let i = 0; i < BladeburnerConstants.CityNames.length; ++i) {
|
||||
this.cities[BladeburnerConstants.CityNames[i]] = new City(BladeburnerConstants.CityNames[i]);
|
||||
}
|
||||
@ -108,7 +108,7 @@ export class Bladeburner implements IBladeburner {
|
||||
this.updateSkillMultipliers(); // Calls resetSkillMultipliers()
|
||||
|
||||
// Max Stamina is based on stats and Bladeburner-specific bonuses
|
||||
if (player) this.calculateMaxStamina(player);
|
||||
this.calculateMaxStamina();
|
||||
this.stamina = this.maxStamina;
|
||||
this.create();
|
||||
}
|
||||
@ -162,7 +162,8 @@ export class Bladeburner implements IBladeburner {
|
||||
return { isAvailable: true, action };
|
||||
}
|
||||
|
||||
startAction(person: IPerson, actionId: IActionIdentifier): void {
|
||||
/** This function is only for the player. Sleeves use their own functions to perform blade work. */
|
||||
startAction(actionId: IActionIdentifier): void {
|
||||
if (actionId == null) return;
|
||||
this.action = actionId;
|
||||
this.actionTimeCurrent = 0;
|
||||
@ -179,7 +180,7 @@ export class Bladeburner implements IBladeburner {
|
||||
if (action.count < 1) {
|
||||
return this.resetAction();
|
||||
}
|
||||
this.actionTimeToComplete = action.getActionTime(this, person);
|
||||
this.actionTimeToComplete = action.getActionTime(this, Player);
|
||||
} catch (e: unknown) {
|
||||
exceptionAlert(e);
|
||||
}
|
||||
@ -196,7 +197,7 @@ export class Bladeburner implements IBladeburner {
|
||||
if (actionId.name === "Raid" && this.getCurrentCity().comms === 0) {
|
||||
return this.resetAction();
|
||||
}
|
||||
this.actionTimeToComplete = action.getActionTime(this, person);
|
||||
this.actionTimeToComplete = action.getActionTime(this, Player);
|
||||
} catch (e: unknown) {
|
||||
exceptionAlert(e);
|
||||
}
|
||||
@ -214,14 +215,14 @@ export class Bladeburner implements IBladeburner {
|
||||
if (testBlackOp.action === undefined) {
|
||||
throw new Error("action should not be null");
|
||||
}
|
||||
this.actionTimeToComplete = testBlackOp.action.getActionTime(this, person);
|
||||
this.actionTimeToComplete = testBlackOp.action.getActionTime(this, Player);
|
||||
} catch (e: unknown) {
|
||||
exceptionAlert(e);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ActionTypes["Recruitment"]:
|
||||
this.actionTimeToComplete = this.getRecruitmentTime(person);
|
||||
this.actionTimeToComplete = this.getRecruitmentTime(Player);
|
||||
break;
|
||||
case ActionTypes["Training"]:
|
||||
case ActionTypes["FieldAnalysis"]:
|
||||
@ -234,7 +235,7 @@ export class Bladeburner implements IBladeburner {
|
||||
this.actionTimeToComplete = 60;
|
||||
break;
|
||||
default:
|
||||
throw new Error("Invalid Action Type in startAction(Bladeburner,player, ): " + actionId.type);
|
||||
throw new Error("Invalid Action Type in bladeburner.startAction(): " + actionId.type);
|
||||
}
|
||||
}
|
||||
|
||||
@ -252,7 +253,7 @@ export class Bladeburner implements IBladeburner {
|
||||
this.updateSkillMultipliers();
|
||||
}
|
||||
|
||||
executeConsoleCommands(player: IPlayer, commands: string): void {
|
||||
executeConsoleCommands(commands: string): void {
|
||||
try {
|
||||
// Console History
|
||||
if (this.consoleHistory[this.consoleHistory.length - 1] != commands) {
|
||||
@ -264,7 +265,7 @@ export class Bladeburner implements IBladeburner {
|
||||
|
||||
const arrayOfCommands = commands.split(";");
|
||||
for (let i = 0; i < arrayOfCommands.length; ++i) {
|
||||
this.executeConsoleCommand(player, arrayOfCommands[i]);
|
||||
this.executeConsoleCommand(arrayOfCommands[i]);
|
||||
}
|
||||
} catch (e: unknown) {
|
||||
exceptionAlert(e);
|
||||
@ -394,7 +395,7 @@ export class Bladeburner implements IBladeburner {
|
||||
return null;
|
||||
}
|
||||
|
||||
executeStartConsoleCommand(player: IPlayer, args: string[]): void {
|
||||
executeStartConsoleCommand(args: string[]): void {
|
||||
if (args.length !== 3) {
|
||||
this.postToConsole("Invalid usage of 'start' console command: start [type] [name]");
|
||||
this.postToConsole("Use 'help start' for more info");
|
||||
@ -407,7 +408,7 @@ export class Bladeburner implements IBladeburner {
|
||||
if (GeneralActions[name] != null) {
|
||||
this.action.type = ActionTypes[name];
|
||||
this.action.name = name;
|
||||
this.startAction(player, this.action);
|
||||
this.startAction(this.action);
|
||||
} else {
|
||||
this.postToConsole("Invalid action name specified: " + args[2]);
|
||||
}
|
||||
@ -417,7 +418,7 @@ export class Bladeburner implements IBladeburner {
|
||||
if (this.contracts[name] != null) {
|
||||
this.action.type = ActionTypes.Contract;
|
||||
this.action.name = name;
|
||||
this.startAction(player, this.action);
|
||||
this.startAction(this.action);
|
||||
} else {
|
||||
this.postToConsole("Invalid contract name specified: " + args[2]);
|
||||
}
|
||||
@ -429,7 +430,7 @@ export class Bladeburner implements IBladeburner {
|
||||
if (this.operations[name] != null) {
|
||||
this.action.type = ActionTypes.Operation;
|
||||
this.action.name = name;
|
||||
this.startAction(player, this.action);
|
||||
this.startAction(this.action);
|
||||
} else {
|
||||
this.postToConsole("Invalid Operation name specified: " + args[2]);
|
||||
}
|
||||
@ -441,7 +442,7 @@ export class Bladeburner implements IBladeburner {
|
||||
if (BlackOperations[name] != null) {
|
||||
this.action.type = ActionTypes.BlackOperation;
|
||||
this.action.name = name;
|
||||
this.startAction(player, this.action);
|
||||
this.startAction(this.action);
|
||||
} else {
|
||||
this.postToConsole("Invalid BlackOp name specified: " + args[2]);
|
||||
}
|
||||
@ -820,7 +821,7 @@ export class Bladeburner implements IBladeburner {
|
||||
return args;
|
||||
}
|
||||
|
||||
executeConsoleCommand(player: IPlayer, command: string): void {
|
||||
executeConsoleCommand(command: string): void {
|
||||
command = command.trim();
|
||||
command = command.replace(/\s\s+/g, " "); // Replace all whitespace w/ a single space
|
||||
|
||||
@ -845,7 +846,7 @@ export class Bladeburner implements IBladeburner {
|
||||
this.executeSkillConsoleCommand(args);
|
||||
break;
|
||||
case "start":
|
||||
this.executeStartConsoleCommand(player, args);
|
||||
this.executeStartConsoleCommand(args);
|
||||
break;
|
||||
case "stop":
|
||||
this.resetAction();
|
||||
@ -1105,7 +1106,7 @@ export class Bladeburner implements IBladeburner {
|
||||
}
|
||||
}
|
||||
|
||||
completeOperation(success: boolean, player: IPlayer): void {
|
||||
completeOperation(success: boolean): void {
|
||||
if (this.action.type !== ActionTypes.Operation) {
|
||||
throw new Error("completeOperation() called even though current action is not an Operation");
|
||||
}
|
||||
@ -1126,7 +1127,7 @@ export class Bladeburner implements IBladeburner {
|
||||
const losses = getRandomInt(0, max);
|
||||
this.teamSize -= losses;
|
||||
if (this.teamSize < this.sleeveSize) {
|
||||
const sup = player.sleeves.filter((x) => isSleeveSupportWork(x.currentWork));
|
||||
const sup = Player.sleeves.filter((x) => isSleeveSupportWork(x.currentWork));
|
||||
for (let i = 0; i > this.teamSize - this.sleeveSize; i--) {
|
||||
const r = Math.floor(Math.random() * sup.length);
|
||||
sup[r].takeDamage(sup[r].hp.max);
|
||||
@ -1256,7 +1257,7 @@ export class Bladeburner implements IBladeburner {
|
||||
}
|
||||
}
|
||||
|
||||
completeAction(player: IPlayer, person: IPerson, actionIdent: IActionIdentifier, isPlayer = true): ITaskTracker {
|
||||
completeAction(person: IPerson, actionIdent: IActionIdentifier, isPlayer = true): ITaskTracker {
|
||||
let retValue = createTaskTracker();
|
||||
switch (actionIdent.type) {
|
||||
case ActionTypes["Contract"]:
|
||||
@ -1304,24 +1305,16 @@ export class Bladeburner implements IBladeburner {
|
||||
this.changeRank(person, gain);
|
||||
if (isOperation && this.logging.ops) {
|
||||
this.log(
|
||||
`${person.whoAmI()}: ` +
|
||||
action.name +
|
||||
" successfully completed! Gained " +
|
||||
formatNumber(gain, 3) +
|
||||
" rank",
|
||||
`${person.whoAmI()}: ${action.name} successfully completed! Gained ${formatNumber(gain, 3)} rank`,
|
||||
);
|
||||
} else if (!isOperation && this.logging.contracts) {
|
||||
this.log(
|
||||
`${person.whoAmI()}: ` +
|
||||
action.name +
|
||||
" contract successfully completed! Gained " +
|
||||
formatNumber(gain, 3) +
|
||||
" rank and " +
|
||||
numeralWrapper.formatMoney(moneyGain),
|
||||
`${person.whoAmI()}: ${action.name} contract successfully completed! Gained ` +
|
||||
`${formatNumber(gain, 3)} rank and ${numeralWrapper.formatMoney(moneyGain)}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
isOperation ? this.completeOperation(true, player) : this.completeContract(true, actionIdent);
|
||||
isOperation ? this.completeOperation(true) : this.completeContract(true, actionIdent);
|
||||
} else {
|
||||
retValue = this.getActionStats(action, person, false);
|
||||
++action.failures;
|
||||
@ -1335,7 +1328,7 @@ export class Bladeburner implements IBladeburner {
|
||||
damage = action.hpLoss * difficultyMultiplier;
|
||||
damage = Math.ceil(addOffset(damage, 10));
|
||||
this.hpLost += damage;
|
||||
const cost = calculateHospitalizationCost(player, damage);
|
||||
const cost = calculateHospitalizationCost(damage);
|
||||
if (person.takeDamage(damage)) {
|
||||
++this.numHosp;
|
||||
this.moneyLost += cost;
|
||||
@ -1353,7 +1346,7 @@ export class Bladeburner implements IBladeburner {
|
||||
} else if (!isOperation && this.logging.contracts) {
|
||||
this.log(`${person.whoAmI()}: ` + action.name + " contract failed! " + logLossText);
|
||||
}
|
||||
isOperation ? this.completeOperation(false, player) : this.completeContract(false, actionIdent);
|
||||
isOperation ? this.completeOperation(false) : this.completeContract(false, actionIdent);
|
||||
}
|
||||
if (action.autoLevel) {
|
||||
action.level = action.maxLevel;
|
||||
@ -1412,7 +1405,7 @@ export class Bladeburner implements IBladeburner {
|
||||
if (action.hpLoss) {
|
||||
damage = action.hpLoss * difficultyMultiplier;
|
||||
damage = Math.ceil(addOffset(damage, 10));
|
||||
const cost = calculateHospitalizationCost(player, damage);
|
||||
const cost = calculateHospitalizationCost(damage);
|
||||
if (person.takeDamage(damage)) {
|
||||
++this.numHosp;
|
||||
this.moneyLost += cost;
|
||||
@ -1440,7 +1433,7 @@ export class Bladeburner implements IBladeburner {
|
||||
const losses = getRandomInt(1, teamLossMax);
|
||||
this.teamSize -= losses;
|
||||
if (this.teamSize < this.sleeveSize) {
|
||||
const sup = player.sleeves.filter((x) => isSleeveSupportWork(x.currentWork));
|
||||
const sup = Player.sleeves.filter((x) => isSleeveSupportWork(x.currentWork));
|
||||
for (let i = 0; i > this.teamSize - this.sleeveSize; i--) {
|
||||
const r = Math.floor(Math.random() * sup.length);
|
||||
sup[r].takeDamage(sup[r].hp.max);
|
||||
@ -1603,8 +1596,8 @@ export class Bladeburner implements IBladeburner {
|
||||
return retValue;
|
||||
}
|
||||
|
||||
infiltrateSynthoidCommunities(p: IPlayer): void {
|
||||
const infilSleeves = p.sleeves.filter((s) => isSleeveInfiltrateWork(s.currentWork)).length;
|
||||
infiltrateSynthoidCommunities(): void {
|
||||
const infilSleeves = Player.sleeves.filter((s) => isSleeveInfiltrateWork(s.currentWork)).length;
|
||||
const amt = Math.pow(infilSleeves, -0.5) / 2;
|
||||
for (const contract of Object.keys(this.contracts)) {
|
||||
this.contracts[contract].count += amt;
|
||||
@ -1654,7 +1647,7 @@ export class Bladeburner implements IBladeburner {
|
||||
}
|
||||
}
|
||||
|
||||
processAction(router: IRouter, player: IPlayer, seconds: number): void {
|
||||
processAction(seconds: number): void {
|
||||
if (this.action.type === ActionTypes["Idle"]) return;
|
||||
if (this.actionTimeToComplete <= 0) {
|
||||
throw new Error(`Invalid actionTimeToComplete value: ${this.actionTimeToComplete}, type; ${this.action.type}`);
|
||||
@ -1670,31 +1663,31 @@ export class Bladeburner implements IBladeburner {
|
||||
if (this.actionTimeCurrent >= this.actionTimeToComplete) {
|
||||
this.actionTimeOverflow = this.actionTimeCurrent - this.actionTimeToComplete;
|
||||
const action = this.getActionObject(this.action);
|
||||
const retValue = this.completeAction(player, player, this.action);
|
||||
player.gainMoney(retValue.money, "bladeburner");
|
||||
player.gainStats(retValue);
|
||||
const retValue = this.completeAction(Player, this.action);
|
||||
Player.gainMoney(retValue.money, "bladeburner");
|
||||
Player.gainStats(retValue);
|
||||
// Operation Daedalus
|
||||
if (action == null) {
|
||||
throw new Error("Failed to get BlackOperation Object for: " + this.action.name);
|
||||
} else if (this.action.type != ActionTypes["BlackOperation"] && this.action.type != ActionTypes["BlackOp"]) {
|
||||
this.startAction(player, this.action); // Repeat action
|
||||
this.startAction(this.action); // Repeat action
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
calculateStaminaGainPerSecond(player: IPlayer): number {
|
||||
const effAgility = player.skills.agility * this.skillMultipliers.effAgi;
|
||||
calculateStaminaGainPerSecond(): number {
|
||||
const effAgility = Player.skills.agility * this.skillMultipliers.effAgi;
|
||||
const maxStaminaBonus = this.maxStamina / BladeburnerConstants.MaxStaminaToGainFactor;
|
||||
const gain = (BladeburnerConstants.StaminaGainPerSecond + maxStaminaBonus) * Math.pow(effAgility, 0.17);
|
||||
return gain * (this.skillMultipliers.stamina * player.mults.bladeburner_stamina_gain);
|
||||
return gain * (this.skillMultipliers.stamina * Player.mults.bladeburner_stamina_gain);
|
||||
}
|
||||
|
||||
calculateMaxStamina(player: IPlayer): void {
|
||||
const effAgility = player.skills.agility * this.skillMultipliers.effAgi;
|
||||
calculateMaxStamina(): void {
|
||||
const effAgility = Player.skills.agility * this.skillMultipliers.effAgi;
|
||||
const maxStamina =
|
||||
(Math.pow(effAgility, 0.8) + this.staminaBonus) *
|
||||
this.skillMultipliers.stamina *
|
||||
player.mults.bladeburner_max_stamina;
|
||||
Player.mults.bladeburner_max_stamina;
|
||||
if (this.maxStamina !== maxStamina) {
|
||||
const oldMax = this.maxStamina;
|
||||
this.maxStamina = maxStamina;
|
||||
@ -1974,12 +1967,12 @@ export class Bladeburner implements IBladeburner {
|
||||
});
|
||||
}
|
||||
|
||||
process(router: IRouter, player: IPlayer): void {
|
||||
process(): void {
|
||||
// Edge race condition when the engine checks the processing counters and attempts to route before the router is initialized.
|
||||
if (!router.isInitialized) return;
|
||||
if (!Router.isInitialized) return;
|
||||
|
||||
// If the Player starts doing some other actions, set action to idle and alert
|
||||
if (!player.hasAugmentation(AugmentationNames.BladesSimulacrum, true) && player.currentWork) {
|
||||
if (!Player.hasAugmentation(AugmentationNames.BladesSimulacrum, true) && Player.currentWork) {
|
||||
if (this.action.type !== ActionTypes["Idle"]) {
|
||||
let msg = "Your Bladeburner action was cancelled because you started doing something else.";
|
||||
if (this.automateEnabled) {
|
||||
@ -2006,8 +1999,8 @@ export class Bladeburner implements IBladeburner {
|
||||
this.storedCycles -= seconds * BladeburnerConstants.CyclesPerSecond;
|
||||
|
||||
// Stamina
|
||||
this.calculateMaxStamina(player);
|
||||
this.stamina += this.calculateStaminaGainPerSecond(player) * seconds;
|
||||
this.calculateMaxStamina();
|
||||
this.stamina += this.calculateStaminaGainPerSecond() * seconds;
|
||||
this.stamina = Math.min(this.maxStamina, this.stamina);
|
||||
|
||||
// Count increase for contracts/operations
|
||||
@ -2042,7 +2035,7 @@ export class Bladeburner implements IBladeburner {
|
||||
this.randomEventCounter += getRandomInt(240, 600);
|
||||
}
|
||||
|
||||
this.processAction(router, player, seconds);
|
||||
this.processAction(seconds);
|
||||
|
||||
// Automation
|
||||
if (this.automateEnabled) {
|
||||
@ -2053,7 +2046,7 @@ export class Bladeburner implements IBladeburner {
|
||||
type: this.automateActionLow.type,
|
||||
name: this.automateActionLow.name,
|
||||
});
|
||||
this.startAction(player, this.action);
|
||||
this.startAction(this.action);
|
||||
}
|
||||
} else if (this.stamina >= this.automateThreshHigh) {
|
||||
if (this.action.name !== this.automateActionHigh.name || this.action.type !== this.automateActionHigh.type) {
|
||||
@ -2061,7 +2054,7 @@ export class Bladeburner implements IBladeburner {
|
||||
type: this.automateActionHigh.type,
|
||||
name: this.automateActionHigh.name,
|
||||
});
|
||||
this.startAction(player, this.action);
|
||||
this.startAction(this.action);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2121,7 +2114,7 @@ export class Bladeburner implements IBladeburner {
|
||||
return Object.keys(Skills);
|
||||
}
|
||||
|
||||
startActionNetscriptFn(player: IPlayer, type: string, name: string, workerScript: WorkerScript): boolean {
|
||||
startActionNetscriptFn(type: string, name: string, workerScript: WorkerScript): boolean {
|
||||
const errorLogText = `Invalid action: type='${type}' name='${name}'`;
|
||||
const actionId = this.getActionIdFromTypeAndName(type, name);
|
||||
if (actionId == null) {
|
||||
@ -2139,7 +2132,7 @@ export class Bladeburner implements IBladeburner {
|
||||
}
|
||||
|
||||
try {
|
||||
this.startAction(player, actionId);
|
||||
this.startAction(actionId);
|
||||
workerScript.log(
|
||||
"bladeburner.startAction",
|
||||
() => `Starting bladeburner action with type '${type}' and name '${name}'`,
|
||||
|
@ -2,13 +2,13 @@ import { IActionIdentifier } from "./IActionIdentifier";
|
||||
import { City } from "./City";
|
||||
import { Skill } from "./Skill";
|
||||
import { IAction } from "./IAction";
|
||||
import { IPlayer } from "../PersonObjects/IPlayer";
|
||||
import { IPerson } from "../PersonObjects/IPerson";
|
||||
import { ITaskTracker } from "../PersonObjects/ITaskTracker";
|
||||
import { IRouter } from "../ui/Router";
|
||||
import { WorkerScript } from "../Netscript/WorkerScript";
|
||||
import { Contract } from "./Contract";
|
||||
import { Operation } from "./Operation";
|
||||
import { IReviverValue } from "../utils/JSONReviver";
|
||||
import { BlackOpsAttempt } from "./Bladeburner";
|
||||
|
||||
export interface IBladeburner {
|
||||
numHosp: number;
|
||||
@ -20,6 +20,7 @@ export interface IBladeburner {
|
||||
totalSkillPoints: number;
|
||||
|
||||
teamSize: number;
|
||||
sleeveSize: number;
|
||||
teamLost: number;
|
||||
hpLost: number;
|
||||
|
||||
@ -60,9 +61,10 @@ export interface IBladeburner {
|
||||
|
||||
getCurrentCity(): City;
|
||||
calculateStaminaPenalty(): number;
|
||||
startAction(player: IPlayer, action: IActionIdentifier): void;
|
||||
canAttemptBlackOp(actionId: IActionIdentifier): BlackOpsAttempt;
|
||||
startAction(action: IActionIdentifier): void;
|
||||
upgradeSkill(skill: Skill): void;
|
||||
executeConsoleCommands(player: IPlayer, command: string): void;
|
||||
executeConsoleCommands(command: string): void;
|
||||
postToConsole(input: string, saveToLogs?: boolean): void;
|
||||
log(input: string): void;
|
||||
resetAction(): void;
|
||||
@ -79,7 +81,7 @@ export interface IBladeburner {
|
||||
getBlackOpNamesNetscriptFn(): string[];
|
||||
getGeneralActionNamesNetscriptFn(): string[];
|
||||
getSkillNamesNetscriptFn(): string[];
|
||||
startActionNetscriptFn(player: IPlayer, type: string, name: string, workerScript: WorkerScript): boolean;
|
||||
startActionNetscriptFn(type: string, name: string, workerScript: WorkerScript): boolean;
|
||||
getActionTimeNetscriptFn(person: IPerson, type: string, name: string): number | string;
|
||||
getActionEstimatedSuccessChanceNetscriptFn(person: IPerson, type: string, name: string): [number, number] | string;
|
||||
getActionCountRemainingNetscriptFn(type: string, name: string, workerScript: WorkerScript): number;
|
||||
@ -90,32 +92,33 @@ export interface IBladeburner {
|
||||
setTeamSizeNetscriptFn(type: string, name: string, size: number, workerScript: WorkerScript): number;
|
||||
joinBladeburnerFactionNetscriptFn(workerScript: WorkerScript): boolean;
|
||||
getActionIdFromTypeAndName(type: string, name: string): IActionIdentifier | null;
|
||||
executeStartConsoleCommand(player: IPlayer, args: string[]): void;
|
||||
executeStartConsoleCommand(args: string[]): void;
|
||||
executeSkillConsoleCommand(args: string[]): void;
|
||||
executeLogConsoleCommand(args: string[]): void;
|
||||
executeHelpConsoleCommand(args: string[]): void;
|
||||
executeAutomateConsoleCommand(args: string[]): void;
|
||||
parseCommandArguments(command: string): string[];
|
||||
executeConsoleCommand(player: IPlayer, command: string): void;
|
||||
executeConsoleCommand(command: string): void;
|
||||
triggerMigration(sourceCityName: string): void;
|
||||
triggerPotentialMigration(sourceCityName: string, chance: number): void;
|
||||
randomEvent(): void;
|
||||
getDiplomacyEffectiveness(player: IPlayer): number;
|
||||
getRecruitmentSuccessChance(player: IPerson): number;
|
||||
getRecruitmentTime(player: IPerson): number;
|
||||
getDiplomacyEffectiveness(person: IPerson): number;
|
||||
getRecruitmentSuccessChance(person: IPerson): number;
|
||||
getRecruitmentTime(person: IPerson): number;
|
||||
resetSkillMultipliers(): void;
|
||||
updateSkillMultipliers(): void;
|
||||
completeOperation(success: boolean, player: IPlayer): void;
|
||||
completeOperation(success: boolean): void;
|
||||
getActionObject(actionId: IActionIdentifier): IAction | null;
|
||||
completeContract(success: boolean, actionIdent: IActionIdentifier): void;
|
||||
completeAction(player: IPlayer, person: IPerson, actionIdent: IActionIdentifier, isPlayer?: boolean): ITaskTracker;
|
||||
infiltrateSynthoidCommunities(p: IPlayer): void;
|
||||
changeRank(player: IPlayer, change: number): void;
|
||||
processAction(router: IRouter, player: IPlayer, seconds: number): void;
|
||||
calculateStaminaGainPerSecond(player: IPlayer): number;
|
||||
calculateMaxStamina(player: IPlayer): void;
|
||||
completeAction(person: IPerson, actionIdent: IActionIdentifier, isPlayer?: boolean): ITaskTracker;
|
||||
infiltrateSynthoidCommunities(): void;
|
||||
changeRank(person: IPerson, change: number): void;
|
||||
processAction(seconds: number): void;
|
||||
calculateStaminaGainPerSecond(): number;
|
||||
calculateMaxStamina(): void;
|
||||
create(): void;
|
||||
process(router: IRouter, player: IPlayer): void;
|
||||
process(): void;
|
||||
getActionStats(action: IAction, person: IPerson, success: boolean): ITaskTracker;
|
||||
sleeveSupport(joining: boolean): void;
|
||||
toJSON():IReviverValue;
|
||||
}
|
||||
|
@ -27,14 +27,14 @@ export function ActionLevel({ action, isActive, bladeburner, rerender }: IProps)
|
||||
function increaseLevel(): void {
|
||||
if (!canIncrease) return;
|
||||
++action.level;
|
||||
if (isActive) bladeburner.startAction(player, bladeburner.action);
|
||||
if (isActive) bladeburner.startAction(bladeburner.action);
|
||||
rerender();
|
||||
}
|
||||
|
||||
function decreaseLevel(): void {
|
||||
if (!canDecrease) return;
|
||||
--action.level;
|
||||
if (isActive) bladeburner.startAction(player, bladeburner.action);
|
||||
if (isActive) bladeburner.startAction(bladeburner.action);
|
||||
rerender();
|
||||
}
|
||||
|
||||
|
@ -5,7 +5,6 @@ import { OperationPage } from "./OperationPage";
|
||||
import { BlackOpPage } from "./BlackOpPage";
|
||||
import { SkillPage } from "./SkillPage";
|
||||
import { IBladeburner } from "../IBladeburner";
|
||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||
|
||||
import Tabs from "@mui/material/Tabs";
|
||||
import Tab from "@mui/material/Tab";
|
||||
@ -13,7 +12,6 @@ import Box from "@mui/material/Box";
|
||||
|
||||
interface IProps {
|
||||
bladeburner: IBladeburner;
|
||||
player: IPlayer;
|
||||
}
|
||||
|
||||
export function AllPages(props: IProps): React.ReactElement {
|
||||
@ -33,10 +31,10 @@ export function AllPages(props: IProps): React.ReactElement {
|
||||
<Tab label="Skills" />
|
||||
</Tabs>
|
||||
<Box sx={{ p: 1 }}>
|
||||
{value === 0 && <GeneralActionPage bladeburner={props.bladeburner} player={props.player} />}
|
||||
{value === 1 && <ContractPage bladeburner={props.bladeburner} player={props.player} />}
|
||||
{value === 2 && <OperationPage bladeburner={props.bladeburner} player={props.player} />}
|
||||
{value === 3 && <BlackOpPage bladeburner={props.bladeburner} player={props.player} />}
|
||||
{value === 0 && <GeneralActionPage bladeburner={props.bladeburner} />}
|
||||
{value === 1 && <ContractPage bladeburner={props.bladeburner} />}
|
||||
{value === 2 && <OperationPage bladeburner={props.bladeburner} />}
|
||||
{value === 3 && <BlackOpPage bladeburner={props.bladeburner} />}
|
||||
{value === 4 && <SkillPage bladeburner={props.bladeburner} />}
|
||||
</Box>
|
||||
</>
|
||||
|
@ -6,7 +6,7 @@ import { TeamSizeButton } from "./TeamSizeButton";
|
||||
import { IBladeburner } from "../IBladeburner";
|
||||
import { BlackOperation } from "../BlackOperation";
|
||||
import { BlackOperations } from "../data/BlackOperations";
|
||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||
import { Player } from "../../Player";
|
||||
import { CopyableText } from "../../ui/React/CopyableText";
|
||||
import { SuccessChance } from "./SuccessChance";
|
||||
import { StartButton } from "./StartButton";
|
||||
@ -16,7 +16,6 @@ import Paper from "@mui/material/Paper";
|
||||
|
||||
interface IProps {
|
||||
bladeburner: IBladeburner;
|
||||
player: IPlayer;
|
||||
action: BlackOperation;
|
||||
}
|
||||
|
||||
@ -37,7 +36,7 @@ export function BlackOpElem(props: IProps): React.ReactElement {
|
||||
const isActive =
|
||||
props.bladeburner.action.type === ActionTypes["BlackOperation"] &&
|
||||
props.action.name === props.bladeburner.action.name;
|
||||
const actionTime = props.action.getActionTime(props.bladeburner, props.player);
|
||||
const actionTime = props.action.getActionTime(props.bladeburner, Player);
|
||||
const hasReqdRank = props.bladeburner.rank >= props.action.reqdRank;
|
||||
const computedActionTimeCurrent = Math.min(
|
||||
props.bladeburner.actionTimeCurrent + props.bladeburner.actionTimeOverflow,
|
||||
|
@ -3,11 +3,9 @@ import { BlackOperations } from "../BlackOperations";
|
||||
import { BlackOperation } from "../BlackOperation";
|
||||
import { BlackOpElem } from "./BlackOpElem";
|
||||
import { IBladeburner } from "../IBladeburner";
|
||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||
|
||||
interface IProps {
|
||||
bladeburner: IBladeburner;
|
||||
player: IPlayer;
|
||||
}
|
||||
|
||||
export function BlackOpList(props: IProps): React.ReactElement {
|
||||
@ -35,7 +33,7 @@ export function BlackOpList(props: IProps): React.ReactElement {
|
||||
return (
|
||||
<>
|
||||
{blackops.map((blackop: BlackOperation) => (
|
||||
<BlackOpElem key={blackop.name} bladeburner={props.bladeburner} action={blackop} player={props.player} />
|
||||
<BlackOpElem key={blackop.name} bladeburner={props.bladeburner} action={blackop} />
|
||||
))}
|
||||
</>
|
||||
);
|
||||
|
@ -1,7 +1,6 @@
|
||||
import * as React from "react";
|
||||
import { BlackOpList } from "./BlackOpList";
|
||||
import { IBladeburner } from "../IBladeburner";
|
||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||
import Typography from "@mui/material/Typography";
|
||||
import { FactionNames } from "../../Faction/data/FactionNames";
|
||||
import { use } from "../../ui/Context";
|
||||
@ -11,7 +10,6 @@ import { CorruptableText } from "../../ui/React/CorruptableText";
|
||||
|
||||
interface IProps {
|
||||
bladeburner: IBladeburner;
|
||||
player: IPlayer;
|
||||
}
|
||||
|
||||
export function BlackOpPage(props: IProps): React.ReactElement {
|
||||
@ -37,7 +35,7 @@ export function BlackOpPage(props: IProps): React.ReactElement {
|
||||
<CorruptableText content="Destroy w0rld_d34mon"></CorruptableText>
|
||||
</Button>
|
||||
) : (
|
||||
<BlackOpList bladeburner={props.bladeburner} player={props.player} />
|
||||
<BlackOpList bladeburner={props.bladeburner} />
|
||||
)}
|
||||
</>
|
||||
);
|
||||
|
@ -24,11 +24,11 @@ export function BladeburnerRoot(): React.ReactElement {
|
||||
return (
|
||||
<Box display="flex" flexDirection="column">
|
||||
<Box sx={{ display: "grid", gridTemplateColumns: "4fr 8fr", p: 1 }}>
|
||||
<Stats bladeburner={bladeburner} player={player} router={router} />
|
||||
<Console bladeburner={bladeburner} player={player} />
|
||||
<Stats bladeburner={bladeburner} />
|
||||
<Console bladeburner={bladeburner} />
|
||||
</Box>
|
||||
|
||||
<AllPages bladeburner={bladeburner} player={player} />
|
||||
<AllPages bladeburner={bladeburner} />
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
@ -2,7 +2,6 @@ import React, { useState, useRef, useEffect } from "react";
|
||||
import { IBladeburner } from "../IBladeburner";
|
||||
import { KEY } from "../../utils/helpers/keyCodes";
|
||||
|
||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||
import Paper from "@mui/material/Paper";
|
||||
import List from "@mui/material/List";
|
||||
import ListItem from "@mui/material/ListItem";
|
||||
@ -50,7 +49,6 @@ function Line(props: ILineProps): React.ReactElement {
|
||||
|
||||
interface IProps {
|
||||
bladeburner: IBladeburner;
|
||||
player: IPlayer;
|
||||
}
|
||||
|
||||
export function Console(props: IProps): React.ReactElement {
|
||||
@ -81,7 +79,7 @@ export function Console(props: IProps): React.ReactElement {
|
||||
event.preventDefault();
|
||||
if (command.length > 0) {
|
||||
props.bladeburner.postToConsole("> " + command);
|
||||
props.bladeburner.executeConsoleCommands(props.player, command);
|
||||
props.bladeburner.executeConsoleCommands(command);
|
||||
setConsoleHistoryIndex(props.bladeburner.consoleHistory.length);
|
||||
setCommand("");
|
||||
}
|
||||
|
@ -5,7 +5,7 @@ import { formatNumber, convertTimeMsToTimeElapsedString } from "../../utils/Stri
|
||||
import { Contracts } from "../data/Contracts";
|
||||
import { IBladeburner } from "../IBladeburner";
|
||||
import { IAction } from "../IAction";
|
||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||
import { Player } from "../../Player";
|
||||
import { SuccessChance } from "./SuccessChance";
|
||||
import { CopyableText } from "../../ui/React/CopyableText";
|
||||
import { ActionLevel } from "./ActionLevel";
|
||||
@ -17,7 +17,6 @@ import Paper from "@mui/material/Paper";
|
||||
|
||||
interface IProps {
|
||||
bladeburner: IBladeburner;
|
||||
player: IPlayer;
|
||||
action: IAction;
|
||||
}
|
||||
|
||||
@ -32,7 +31,7 @@ export function ContractElem(props: IProps): React.ReactElement {
|
||||
props.bladeburner.actionTimeCurrent + props.bladeburner.actionTimeOverflow,
|
||||
props.bladeburner.actionTimeToComplete,
|
||||
);
|
||||
const actionTime = props.action.getActionTime(props.bladeburner, props.player);
|
||||
const actionTime = props.action.getActionTime(props.bladeburner, Player);
|
||||
|
||||
const actionData = Contracts[props.action.name];
|
||||
if (actionData === undefined) {
|
||||
|
@ -1,11 +1,9 @@
|
||||
import React from "react";
|
||||
import { ContractElem } from "./ContractElem";
|
||||
import { IBladeburner } from "../IBladeburner";
|
||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||
|
||||
interface IProps {
|
||||
bladeburner: IBladeburner;
|
||||
player: IPlayer;
|
||||
}
|
||||
|
||||
export function ContractList(props: IProps): React.ReactElement {
|
||||
@ -14,7 +12,7 @@ export function ContractList(props: IProps): React.ReactElement {
|
||||
return (
|
||||
<>
|
||||
{names.map((name: string) => (
|
||||
<ContractElem key={name} bladeburner={props.bladeburner} action={contracts[name]} player={props.player} />
|
||||
<ContractElem key={name} bladeburner={props.bladeburner} action={contracts[name]} />
|
||||
))}
|
||||
</>
|
||||
);
|
||||
|
@ -1,12 +1,10 @@
|
||||
import * as React from "react";
|
||||
import { ContractList } from "./ContractList";
|
||||
import { IBladeburner } from "../IBladeburner";
|
||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||
import Typography from "@mui/material/Typography";
|
||||
|
||||
interface IProps {
|
||||
bladeburner: IBladeburner;
|
||||
player: IPlayer;
|
||||
}
|
||||
|
||||
export function ContractPage(props: IProps): React.ReactElement {
|
||||
@ -20,7 +18,7 @@ export function ContractPage(props: IProps): React.ReactElement {
|
||||
You can unlock higher-level contracts by successfully completing them. Higher-level contracts are more
|
||||
difficult, but grant more rank, experience, and money.
|
||||
</Typography>
|
||||
<ContractList bladeburner={props.bladeburner} player={props.player} />
|
||||
<ContractList bladeburner={props.bladeburner} />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
@ -5,7 +5,7 @@ import { formatNumber, convertTimeMsToTimeElapsedString } from "../../utils/Stri
|
||||
import { IBladeburner } from "../IBladeburner";
|
||||
import { IAction } from "../IAction";
|
||||
import { GeneralActions } from "../data/GeneralActions";
|
||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||
import { Player } from "../../Player";
|
||||
import { CopyableText } from "../../ui/React/CopyableText";
|
||||
|
||||
import { StartButton } from "./StartButton";
|
||||
@ -16,7 +16,6 @@ import Paper from "@mui/material/Paper";
|
||||
|
||||
interface IProps {
|
||||
bladeburner: IBladeburner;
|
||||
player: IPlayer;
|
||||
action: IAction;
|
||||
}
|
||||
|
||||
@ -40,13 +39,13 @@ export function GeneralActionElem(props: IProps): React.ReactElement {
|
||||
case "Incite Violence":
|
||||
return 60;
|
||||
case "Recruitment":
|
||||
return props.bladeburner.getRecruitmentTime(props.player);
|
||||
return props.bladeburner.getRecruitmentTime(Player);
|
||||
}
|
||||
return -1; // dead code
|
||||
})();
|
||||
const successChance =
|
||||
props.action.name === "Recruitment"
|
||||
? Math.max(0, Math.min(props.bladeburner.getRecruitmentSuccessChance(props.player), 1))
|
||||
? Math.max(0, Math.min(props.bladeburner.getRecruitmentSuccessChance(Player), 1))
|
||||
: -1;
|
||||
|
||||
const actionData = GeneralActions[props.action.name];
|
||||
|
@ -3,11 +3,9 @@ import { GeneralActionElem } from "./GeneralActionElem";
|
||||
import { Action } from "../Action";
|
||||
import { GeneralActions } from "../GeneralActions";
|
||||
import { IBladeburner } from "../IBladeburner";
|
||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||
|
||||
interface IProps {
|
||||
bladeburner: IBladeburner;
|
||||
player: IPlayer;
|
||||
}
|
||||
|
||||
export function GeneralActionList(props: IProps): React.ReactElement {
|
||||
@ -20,7 +18,7 @@ export function GeneralActionList(props: IProps): React.ReactElement {
|
||||
return (
|
||||
<>
|
||||
{actions.map((action: Action) => (
|
||||
<GeneralActionElem key={action.name} bladeburner={props.bladeburner} action={action} player={props.player} />
|
||||
<GeneralActionElem key={action.name} bladeburner={props.bladeburner} action={action} />
|
||||
))}
|
||||
</>
|
||||
);
|
||||
|
@ -1,19 +1,17 @@
|
||||
import * as React from "react";
|
||||
import { GeneralActionList } from "./GeneralActionList";
|
||||
import { IBladeburner } from "../IBladeburner";
|
||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||
import Typography from "@mui/material/Typography";
|
||||
|
||||
interface IProps {
|
||||
bladeburner: IBladeburner;
|
||||
player: IPlayer;
|
||||
}
|
||||
|
||||
export function GeneralActionPage(props: IProps): React.ReactElement {
|
||||
return (
|
||||
<>
|
||||
<Typography>These are generic actions that will assist you in your Bladeburner duties.</Typography>
|
||||
<GeneralActionList bladeburner={props.bladeburner} player={props.player} />
|
||||
<GeneralActionList bladeburner={props.bladeburner} />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
@ -10,7 +10,7 @@ import { TeamSizeButton } from "./TeamSizeButton";
|
||||
import { IBladeburner } from "../IBladeburner";
|
||||
import { Operation } from "../Operation";
|
||||
import { Operations } from "../data/Operations";
|
||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||
import { Player } from "../../Player";
|
||||
import { CopyableText } from "../../ui/React/CopyableText";
|
||||
|
||||
import Typography from "@mui/material/Typography";
|
||||
@ -18,7 +18,6 @@ import Paper from "@mui/material/Paper";
|
||||
|
||||
interface IProps {
|
||||
bladeburner: IBladeburner;
|
||||
player: IPlayer;
|
||||
action: Operation;
|
||||
}
|
||||
|
||||
@ -33,7 +32,7 @@ export function OperationElem(props: IProps): React.ReactElement {
|
||||
props.bladeburner.actionTimeCurrent + props.bladeburner.actionTimeOverflow,
|
||||
props.bladeburner.actionTimeToComplete,
|
||||
);
|
||||
const actionTime = props.action.getActionTime(props.bladeburner, props.player);
|
||||
const actionTime = props.action.getActionTime(props.bladeburner, Player);
|
||||
|
||||
const actionData = Operations[props.action.name];
|
||||
if (actionData === undefined) {
|
||||
|
@ -1,11 +1,9 @@
|
||||
import React from "react";
|
||||
import { OperationElem } from "./OperationElem";
|
||||
import { IBladeburner } from "../IBladeburner";
|
||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||
|
||||
interface IProps {
|
||||
bladeburner: IBladeburner;
|
||||
player: IPlayer;
|
||||
}
|
||||
|
||||
export function OperationList(props: IProps): React.ReactElement {
|
||||
@ -14,7 +12,7 @@ export function OperationList(props: IProps): React.ReactElement {
|
||||
return (
|
||||
<>
|
||||
{names.map((name: string) => (
|
||||
<OperationElem key={name} bladeburner={props.bladeburner} action={operations[name]} player={props.player} />
|
||||
<OperationElem key={name} bladeburner={props.bladeburner} action={operations[name]} />
|
||||
))}
|
||||
</>
|
||||
);
|
||||
|
@ -1,12 +1,10 @@
|
||||
import * as React from "react";
|
||||
import { OperationList } from "./OperationList";
|
||||
import { IBladeburner } from "../IBladeburner";
|
||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||
import Typography from "@mui/material/Typography";
|
||||
|
||||
interface IProps {
|
||||
bladeburner: IBladeburner;
|
||||
player: IPlayer;
|
||||
}
|
||||
|
||||
export function OperationPage(props: IProps): React.ReactElement {
|
||||
@ -29,7 +27,7 @@ export function OperationPage(props: IProps): React.ReactElement {
|
||||
You can unlock higher-level operations by successfully completing them. Higher-level operations are more
|
||||
difficult, but grant more rank and experience.
|
||||
</Typography>
|
||||
<OperationList bladeburner={props.bladeburner} player={props.player} />
|
||||
<OperationList bladeburner={props.bladeburner} />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
@ -34,7 +34,7 @@ export function StartButton(props: IProps): React.ReactElement {
|
||||
props.bladeburner.action.type = props.type;
|
||||
props.bladeburner.action.name = props.name;
|
||||
if (!player.hasAugmentation(AugmentationNames.BladesSimulacrum, true)) player.finishWork(true);
|
||||
props.bladeburner.startAction(player, props.bladeburner.action);
|
||||
props.bladeburner.startAction(props.bladeburner.action);
|
||||
props.rerender();
|
||||
}
|
||||
|
||||
|
@ -1,11 +1,11 @@
|
||||
import React, { useState, useEffect } from "react";
|
||||
import { formatNumber, convertTimeMsToTimeElapsedString } from "../../utils/StringHelperFunctions";
|
||||
import { BladeburnerConstants } from "../data/Constants";
|
||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||
import { Player } from "../../Player";
|
||||
import { Money } from "../../ui/React/Money";
|
||||
import { numeralWrapper } from "../../ui/numeralFormat";
|
||||
import { Factions } from "../../Faction/Factions";
|
||||
import { IRouter } from "../../ui/Router";
|
||||
import { Router } from "../../ui/GameRoot";
|
||||
import { joinFaction } from "../../Faction/FactionHelpers";
|
||||
import { IBladeburner } from "../IBladeburner";
|
||||
|
||||
@ -19,8 +19,6 @@ import { FactionNames } from "../../Faction/data/FactionNames";
|
||||
|
||||
interface IProps {
|
||||
bladeburner: IBladeburner;
|
||||
router: IRouter;
|
||||
player: IPlayer;
|
||||
}
|
||||
|
||||
export function Stats(props: IProps): React.ReactElement {
|
||||
@ -40,7 +38,7 @@ export function Stats(props: IProps): React.ReactElement {
|
||||
joinFaction(faction);
|
||||
}
|
||||
|
||||
props.router.toFaction(faction);
|
||||
Router.toFaction(faction);
|
||||
}
|
||||
|
||||
return (
|
||||
@ -170,13 +168,13 @@ export function Stats(props: IProps): React.ReactElement {
|
||||
<Typography>Skill Points: {formatNumber(props.bladeburner.skillPoints, 0)}</Typography>
|
||||
<br />
|
||||
<Typography>
|
||||
Aug. Success Chance mult: {formatNumber(props.player.mults.bladeburner_success_chance * 100, 1)}%
|
||||
Aug. Success Chance mult: {formatNumber(Player.mults.bladeburner_success_chance * 100, 1)}%
|
||||
<br />
|
||||
Aug. Max Stamina mult: {formatNumber(props.player.mults.bladeburner_max_stamina * 100, 1)}%
|
||||
Aug. Max Stamina mult: {formatNumber(Player.mults.bladeburner_max_stamina * 100, 1)}%
|
||||
<br />
|
||||
Aug. Stamina Gain mult: {formatNumber(props.player.mults.bladeburner_stamina_gain * 100, 1)}%
|
||||
Aug. Stamina Gain mult: {formatNumber(Player.mults.bladeburner_stamina_gain * 100, 1)}%
|
||||
<br />
|
||||
Aug. Field Analysis mult: {formatNumber(props.player.mults.bladeburner_analysis * 100, 1)}%
|
||||
Aug. Field Analysis mult: {formatNumber(Player.mults.bladeburner_analysis * 100, 1)}%
|
||||
</Typography>
|
||||
</Box>
|
||||
</Paper>
|
||||
|
@ -1,8 +1,8 @@
|
||||
import * as React from "react";
|
||||
|
||||
import { IPlayer } from "../PersonObjects/IPlayer";
|
||||
import { Player } from "../Player";
|
||||
import { Money } from "../ui/React/Money";
|
||||
import { Game, reachedLimit } from "./Game";
|
||||
import { win, reachedLimit } from "./Game";
|
||||
import { Deck } from "./CardDeck/Deck";
|
||||
import { Hand } from "./CardDeck/Hand";
|
||||
import { InputAdornment } from "@mui/material";
|
||||
@ -24,10 +24,6 @@ enum Result {
|
||||
Tie = "Push! (Tie)",
|
||||
}
|
||||
|
||||
type Props = {
|
||||
p: IPlayer;
|
||||
};
|
||||
|
||||
type State = {
|
||||
playerHand: Hand;
|
||||
dealerHand: Hand;
|
||||
@ -40,11 +36,11 @@ type State = {
|
||||
wagerInvalidHelperText: string;
|
||||
};
|
||||
|
||||
export class Blackjack extends Game<Props, State> {
|
||||
export class Blackjack extends React.Component<{},State> {
|
||||
deck: Deck;
|
||||
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
constructor() {
|
||||
super({});
|
||||
|
||||
this.deck = new Deck(DECK_COUNT);
|
||||
|
||||
@ -64,20 +60,19 @@ export class Blackjack extends Game<Props, State> {
|
||||
}
|
||||
|
||||
canStartGame = (): boolean => {
|
||||
const { p } = this.props;
|
||||
const { bet } = this.state;
|
||||
|
||||
return p.canAfford(bet);
|
||||
return Player.canAfford(bet);
|
||||
};
|
||||
|
||||
startGame = (): void => {
|
||||
if (!this.canStartGame() || reachedLimit(this.props.p)) {
|
||||
if (!this.canStartGame() || reachedLimit()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Take money from player right away so that player's dont just "leave" to avoid the loss (I mean they could
|
||||
// always reload without saving but w.e) TODO: Save/Restore the RNG state to limit the value of save-scumming.
|
||||
this.props.p.loseMoney(this.state.bet, "casino");
|
||||
win(-this.state.bet);
|
||||
|
||||
const playerHand = new Hand([this.deck.safeDrawCard(), this.deck.safeDrawCard()]);
|
||||
const dealerHand = new Hand([this.deck.safeDrawCard(), this.deck.safeDrawCard()]);
|
||||
@ -230,7 +225,7 @@ export class Blackjack extends Game<Props, State> {
|
||||
: (() => {
|
||||
throw new Error(`Unexpected result: ${result}`);
|
||||
})(); // This can't happen, right?
|
||||
this.win(this.props.p, gains);
|
||||
win(gains);
|
||||
this.setState({
|
||||
gameInProgress: false,
|
||||
result,
|
||||
@ -239,7 +234,6 @@ export class Blackjack extends Game<Props, State> {
|
||||
};
|
||||
|
||||
wagerOnChange = (event: React.ChangeEvent<HTMLInputElement>): void => {
|
||||
const { p } = this.props;
|
||||
const betInput = event.target.value;
|
||||
const wager = Math.round(parseFloat(betInput));
|
||||
if (isNaN(wager)) {
|
||||
@ -263,7 +257,7 @@ export class Blackjack extends Game<Props, State> {
|
||||
wagerInvalid: true,
|
||||
wagerInvalidHelperText: "Exceeds max bet",
|
||||
});
|
||||
} else if (!p.canAfford(wager)) {
|
||||
} else if (!Player.canAfford(wager)) {
|
||||
this.setState({
|
||||
bet: 0,
|
||||
betInput,
|
||||
|
@ -5,7 +5,6 @@
|
||||
*/
|
||||
import React, { useState } from "react";
|
||||
|
||||
import { IPlayer } from "../PersonObjects/IPlayer";
|
||||
import { BadRNG } from "./RNG";
|
||||
import { win, reachedLimit } from "./Game";
|
||||
import { trusted } from "./utils";
|
||||
@ -15,14 +14,10 @@ import TextField from "@mui/material/TextField";
|
||||
import Button from "@mui/material/Button";
|
||||
import Box from "@mui/material/Box";
|
||||
|
||||
type IProps = {
|
||||
p: IPlayer;
|
||||
};
|
||||
|
||||
const minPlay = 0;
|
||||
const maxPlay = 10e3;
|
||||
|
||||
export function CoinFlip(props: IProps): React.ReactElement {
|
||||
export function CoinFlip(): React.ReactElement {
|
||||
const [investment, setInvestment] = useState(1000);
|
||||
const [result, setResult] = useState(<span> </span>);
|
||||
const [status, setStatus] = useState("");
|
||||
@ -43,7 +38,7 @@ export function CoinFlip(props: IProps): React.ReactElement {
|
||||
}
|
||||
|
||||
function play(guess: string): void {
|
||||
if (reachedLimit(props.p)) return;
|
||||
if (reachedLimit()) return;
|
||||
const v = BadRNG.random();
|
||||
let letter: string;
|
||||
if (v < 0.5) {
|
||||
@ -65,11 +60,11 @@ export function CoinFlip(props: IProps): React.ReactElement {
|
||||
|
||||
setTimeout(() => setPlayLock(false), 250);
|
||||
if (correct) {
|
||||
win(props.p, investment);
|
||||
win(investment);
|
||||
} else {
|
||||
win(props.p, -investment);
|
||||
win(-investment);
|
||||
}
|
||||
if (reachedLimit(props.p)) return;
|
||||
if (reachedLimit()) return;
|
||||
}
|
||||
|
||||
return (
|
||||
|
16
src/Casino/Game.ts
Normal file
16
src/Casino/Game.ts
Normal file
@ -0,0 +1,16 @@
|
||||
import { Player } from "../Player";
|
||||
import { dialogBoxCreate } from "../ui/React/DialogBox";
|
||||
|
||||
const gainLimit = 10e9;
|
||||
|
||||
export function win(n: number): void {
|
||||
Player.gainMoney(n, "casino");
|
||||
}
|
||||
|
||||
export function reachedLimit(): boolean {
|
||||
const reached = Player.getCasinoWinnings() > gainLimit;
|
||||
if (reached) {
|
||||
dialogBoxCreate("Alright cheater get out of here. You're not allowed here anymore.");
|
||||
}
|
||||
return reached;
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
import * as React from "react";
|
||||
import { IPlayer } from "../PersonObjects/IPlayer";
|
||||
import { dialogBoxCreate } from "../ui/React/DialogBox";
|
||||
|
||||
const gainLimit = 10e9;
|
||||
|
||||
export function win(p: IPlayer, n: number): void {
|
||||
p.gainMoney(n, "casino");
|
||||
}
|
||||
|
||||
export function reachedLimit(p: IPlayer): boolean {
|
||||
const reached = p.getCasinoWinnings() > gainLimit;
|
||||
if (reached) {
|
||||
dialogBoxCreate("Alright cheater get out of here. You're not allowed here anymore.");
|
||||
}
|
||||
return reached;
|
||||
}
|
||||
|
||||
export class Game<T, U> extends React.Component<T, U> {
|
||||
win(p: IPlayer, n: number): void {
|
||||
p.gainMoney(n, "casino");
|
||||
}
|
||||
|
||||
reachedLimit(p: IPlayer): boolean {
|
||||
const reached = p.getCasinoWinnings() > gainLimit;
|
||||
if (reached) {
|
||||
dialogBoxCreate("Alright cheater get out of here. You're not allowed here anymore.");
|
||||
}
|
||||
return reached;
|
||||
}
|
||||
}
|
@ -1,6 +1,5 @@
|
||||
import React, { useState, useEffect } from "react";
|
||||
|
||||
import { IPlayer } from "../PersonObjects/IPlayer";
|
||||
import { Money } from "../ui/React/Money";
|
||||
import { win, reachedLimit } from "./Game";
|
||||
import { WHRNG } from "./RNG";
|
||||
@ -9,10 +8,6 @@ import Typography from "@mui/material/Typography";
|
||||
import Button from "@mui/material/Button";
|
||||
import TextField from "@mui/material/TextField";
|
||||
|
||||
type IProps = {
|
||||
p: IPlayer;
|
||||
};
|
||||
|
||||
const minPlay = 0;
|
||||
const maxPlay = 1e7;
|
||||
|
||||
@ -111,7 +106,7 @@ function Single(s: number): Strategy {
|
||||
};
|
||||
}
|
||||
|
||||
export function Roulette(props: IProps): React.ReactElement {
|
||||
export function Roulette(): React.ReactElement {
|
||||
const [rng] = useState(new WHRNG(new Date().getTime()));
|
||||
const [investment, setInvestment] = useState(1000);
|
||||
const [canPlay, setCanPlay] = useState(true);
|
||||
@ -151,7 +146,7 @@ export function Roulette(props: IProps): React.ReactElement {
|
||||
}
|
||||
|
||||
function play(strategy: Strategy): void {
|
||||
if (reachedLimit(props.p)) return;
|
||||
if (reachedLimit()) return;
|
||||
|
||||
setCanPlay(false);
|
||||
setLock(false);
|
||||
@ -184,14 +179,14 @@ export function Roulette(props: IProps): React.ReactElement {
|
||||
</>
|
||||
);
|
||||
}
|
||||
win(props.p, gain);
|
||||
win(gain);
|
||||
|
||||
setCanPlay(true);
|
||||
setLock(true);
|
||||
setStatus(status);
|
||||
setN(n);
|
||||
|
||||
reachedLimit(props.p);
|
||||
reachedLimit();
|
||||
}, 1600);
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
import React, { useState, useEffect } from "react";
|
||||
|
||||
import { IPlayer } from "../PersonObjects/IPlayer";
|
||||
import { Player } from "../Player";
|
||||
import { Money } from "../ui/React/Money";
|
||||
import { WHRNG } from "./RNG";
|
||||
import { win, reachedLimit } from "./Game";
|
||||
@ -9,10 +9,6 @@ import Typography from "@mui/material/Typography";
|
||||
import TextField from "@mui/material/TextField";
|
||||
import Button from "@mui/material/Button";
|
||||
|
||||
type IProps = {
|
||||
p: IPlayer;
|
||||
};
|
||||
|
||||
// statically shuffled array of symbols.
|
||||
const symbols = [
|
||||
"D",
|
||||
@ -141,8 +137,8 @@ const payLines = [
|
||||
const minPlay = 0;
|
||||
const maxPlay = 1e6;
|
||||
|
||||
export function SlotMachine(props: IProps): React.ReactElement {
|
||||
const [rng] = useState(new WHRNG(props.p.totalPlaytime));
|
||||
export function SlotMachine(): React.ReactElement {
|
||||
const [rng] = useState(new WHRNG(Player.totalPlaytime));
|
||||
const [index, setIndex] = useState<number[]>([0, 0, 0, 0, 0]);
|
||||
const [locks, setLocks] = useState<number[]>([0, 0, 0, 0, 0]);
|
||||
const [investment, setInvestment] = useState(1000);
|
||||
@ -191,9 +187,9 @@ export function SlotMachine(props: IProps): React.ReactElement {
|
||||
}
|
||||
|
||||
function play(): void {
|
||||
if (reachedLimit(props.p)) return;
|
||||
if (reachedLimit()) return;
|
||||
setStatus("playing");
|
||||
win(props.p, -investment);
|
||||
win(-investment);
|
||||
if (!canPlay) return;
|
||||
unlock();
|
||||
setTimeout(lock, rng.random() * 2000 + 1000);
|
||||
@ -235,7 +231,7 @@ export function SlotMachine(props: IProps): React.ReactElement {
|
||||
if (count < 3) continue;
|
||||
const payout = getPayout(data[0], count - 3);
|
||||
gains += investment * payout;
|
||||
win(props.p, investment * payout);
|
||||
win(investment * payout);
|
||||
}
|
||||
|
||||
setStatus(
|
||||
@ -244,7 +240,7 @@ export function SlotMachine(props: IProps): React.ReactElement {
|
||||
</>,
|
||||
);
|
||||
setCanPlay(true);
|
||||
if (reachedLimit(props.p)) return;
|
||||
if (reachedLimit()) return;
|
||||
}
|
||||
|
||||
function unlock(): void {
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { Player } from "../Player";
|
||||
import { IPlayer } from "src/PersonObjects/IPlayer";
|
||||
import { MaterialSizes } from "./MaterialSizes";
|
||||
import { ICorporation } from "./ICorporation";
|
||||
import { Corporation } from "./Corporation";
|
||||
@ -271,7 +270,7 @@ export function BulkPurchase(corp: ICorporation, warehouse: Warehouse, material:
|
||||
}
|
||||
}
|
||||
|
||||
export function SellShares(corporation: ICorporation, player: IPlayer, numShares: number): number {
|
||||
export function SellShares(corporation: ICorporation, numShares: number): number {
|
||||
if (isNaN(numShares)) throw new Error("Invalid value for number of shares");
|
||||
if (numShares < 0) throw new Error("Invalid value for number of shares");
|
||||
if (numShares > corporation.numShares) throw new Error("You don't have that many shares to sell!");
|
||||
@ -287,20 +286,20 @@ export function SellShares(corporation: ICorporation, player: IPlayer, numShares
|
||||
corporation.sharePrice = newSharePrice;
|
||||
corporation.shareSalesUntilPriceUpdate = newSharesUntilUpdate;
|
||||
corporation.shareSaleCooldown = CorporationConstants.SellSharesCooldown;
|
||||
player.gainMoney(profit, "corporation");
|
||||
Player.gainMoney(profit, "corporation");
|
||||
return profit;
|
||||
}
|
||||
|
||||
export function BuyBackShares(corporation: ICorporation, player: IPlayer, numShares: number): boolean {
|
||||
export function BuyBackShares(corporation: ICorporation, numShares: number): boolean {
|
||||
if (isNaN(numShares)) throw new Error("Invalid value for number of shares");
|
||||
if (numShares < 0) throw new Error("Invalid value for number of shares");
|
||||
if (numShares > corporation.issuedShares) throw new Error("You don't have that many shares to buy!");
|
||||
if (!corporation.public) throw new Error("You haven't gone public!");
|
||||
const buybackPrice = corporation.sharePrice * 1.1;
|
||||
if (player.money < numShares * buybackPrice) throw new Error("You cant afford that many shares!");
|
||||
if (Player.money < numShares * buybackPrice) throw new Error("You cant afford that many shares!");
|
||||
corporation.numShares += numShares;
|
||||
corporation.issuedShares -= numShares;
|
||||
player.loseMoney(numShares * buybackPrice, "corporation");
|
||||
Player.loseMoney(numShares * buybackPrice, "corporation");
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -8,7 +8,7 @@ import { Industry } from "./Industry";
|
||||
import { BitNodeMultipliers } from "../BitNode/BitNodeMultipliers";
|
||||
import { showLiterature } from "../Literature/LiteratureHelpers";
|
||||
import { LiteratureNames } from "../Literature/data/LiteratureNames";
|
||||
import { IPlayer } from "../PersonObjects/IPlayer";
|
||||
import { Player } from "../Player";
|
||||
|
||||
import { dialogBoxCreate } from "../ui/React/DialogBox";
|
||||
import { Reviver, Generic_toJSON, Generic_fromJSON, IReviverValue } from "../utils/JSONReviver";
|
||||
@ -76,7 +76,7 @@ export class Corporation {
|
||||
this.storedCycles += numCycles;
|
||||
}
|
||||
|
||||
process(player: IPlayer): void {
|
||||
process(): void {
|
||||
if (this.storedCycles >= CorporationConstants.CyclesPerIndustryStateCycle) {
|
||||
const state = this.getState();
|
||||
const marketCycles = 1;
|
||||
@ -139,7 +139,7 @@ export class Corporation {
|
||||
} else {
|
||||
const totalDividends = this.dividendRate * cycleProfit;
|
||||
const retainedEarnings = cycleProfit - totalDividends;
|
||||
player.gainMoney(this.getCycleDividends(), "corporation");
|
||||
Player.gainMoney(this.getCycleDividends(), "corporation");
|
||||
this.addFunds(retainedEarnings);
|
||||
}
|
||||
} else {
|
||||
@ -428,9 +428,9 @@ export class Corporation {
|
||||
// Adds the Corporation Handbook (Starter Guide) to the player's home computer.
|
||||
// This is a lit file that gives introductory info to the player
|
||||
// This occurs when the player clicks the "Getting Started Guide" button on the overview panel
|
||||
getStarterGuide(player: IPlayer): void {
|
||||
getStarterGuide(): void {
|
||||
// Check if player already has Corporation Handbook
|
||||
const homeComp = player.getHomeComputer();
|
||||
const homeComp = Player.getHomeComputer();
|
||||
let hasHandbook = false;
|
||||
const handbookFn = LiteratureNames.CorporationManagementHandbook;
|
||||
for (let i = 0; i < homeComp.messages.length; ++i) {
|
||||
|
@ -31,7 +31,6 @@ export function Industry(props: IProps): React.ReactElement {
|
||||
<Box sx={{ width: "50%" }}>
|
||||
<IndustryWarehouse
|
||||
rerender={props.rerender}
|
||||
player={player}
|
||||
corp={corp}
|
||||
currentCity={props.city}
|
||||
division={division}
|
||||
|
@ -15,7 +15,6 @@ import { numeralWrapper } from "../../ui/numeralFormat";
|
||||
|
||||
import { ICorporation } from "../ICorporation";
|
||||
import { IIndustry } from "../IIndustry";
|
||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||
import { MoneyCost } from "./MoneyCost";
|
||||
import { isRelevantMaterial } from "./Helpers";
|
||||
import { IndustryProductEquation } from "./IndustryProductEquation";
|
||||
@ -35,7 +34,6 @@ interface IProps {
|
||||
division: IIndustry;
|
||||
warehouse: Warehouse | 0;
|
||||
currentCity: string;
|
||||
player: IPlayer;
|
||||
rerender: () => void;
|
||||
}
|
||||
|
||||
|
@ -35,7 +35,7 @@ export function BuybackSharesModal(props: IProps): React.ReactElement {
|
||||
function buy(): void {
|
||||
if (disabled) return;
|
||||
try {
|
||||
BuyBackShares(corp, player, shares);
|
||||
BuyBackShares(corp, shares);
|
||||
} catch (err) {
|
||||
dialogBoxCreate(err + "");
|
||||
}
|
||||
|
@ -72,7 +72,7 @@ export function CreateCorporationModal(props: IProps): React.ReactElement {
|
||||
</Button>
|
||||
)}
|
||||
<Button onClick={selfFund} disabled={name == "" || !canSelfFund}>
|
||||
Self-Fund (<Money money={150e9} player={player} />)
|
||||
Self-Fund (<Money money={150e9} forPurchase={true} />)
|
||||
</Button>
|
||||
</Modal>
|
||||
);
|
||||
|
@ -49,7 +49,7 @@ export function SellSharesModal(props: IProps): React.ReactElement {
|
||||
function sell(): void {
|
||||
if (disabled) return;
|
||||
try {
|
||||
const profit = SellShares(corp, player, shares);
|
||||
const profit = SellShares(corp, shares);
|
||||
props.onClose();
|
||||
dialogBoxCreate(
|
||||
<>
|
||||
|
@ -1,16 +1,16 @@
|
||||
import { Crimes } from "./Crimes";
|
||||
import { Crime } from "./Crime";
|
||||
import { IPlayer } from "../PersonObjects/IPlayer";
|
||||
import { Player } from "../Player";
|
||||
|
||||
import { dialogBoxCreate } from "../ui/React/DialogBox";
|
||||
|
||||
export function determineCrimeSuccess(p: IPlayer, type: string): boolean {
|
||||
export function determineCrimeSuccess(type: string): boolean {
|
||||
let chance = 0;
|
||||
let found = false;
|
||||
for (const i of Object.keys(Crimes)) {
|
||||
const crime = Crimes[i];
|
||||
if (crime.type === type) {
|
||||
chance = crime.successRate(p);
|
||||
chance = crime.successRate(Player);
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
|
@ -1,7 +1,5 @@
|
||||
import { IPlayer } from "./PersonObjects/IPlayer";
|
||||
import { Player } from "./Player";
|
||||
import { Bladeburner } from "./Bladeburner/Bladeburner";
|
||||
import { IEngine } from "./IEngine";
|
||||
import { IRouter } from "./ui/Router";
|
||||
import { AugmentationNames } from "./Augmentation/data/AugmentationNames";
|
||||
|
||||
import React, { useEffect } from "react";
|
||||
@ -28,44 +26,38 @@ import { Entropy } from "./DevMenu/ui/Entropy";
|
||||
import Typography from "@mui/material/Typography";
|
||||
import { Exploit } from "./Exploits/Exploit";
|
||||
|
||||
interface IProps {
|
||||
player: IPlayer;
|
||||
engine: IEngine;
|
||||
router: IRouter;
|
||||
}
|
||||
|
||||
export function DevMenuRoot(props: IProps): React.ReactElement {
|
||||
export function DevMenuRoot(): React.ReactElement {
|
||||
useEffect(() => {
|
||||
props.player.giveExploit(Exploit.YoureNotMeantToAccessThis);
|
||||
Player.giveExploit(Exploit.YoureNotMeantToAccessThis);
|
||||
}, []);
|
||||
return (
|
||||
<>
|
||||
<Typography>Development Menu - Only meant to be used for testing/debugging</Typography>
|
||||
<General player={props.player} router={props.router} />
|
||||
<Stats player={props.player} />
|
||||
<Factions player={props.player} />
|
||||
<Augmentations player={props.player} />
|
||||
<SourceFiles player={props.player} />
|
||||
<Programs player={props.player} />
|
||||
<General />
|
||||
<Stats />
|
||||
<Factions />
|
||||
<Augmentations />
|
||||
<SourceFiles />
|
||||
<Programs />
|
||||
<Servers />
|
||||
<Companies />
|
||||
|
||||
{props.player.bladeburner instanceof Bladeburner && <BladeburnerElem player={props.player} />}
|
||||
{Player.bladeburner instanceof Bladeburner && <BladeburnerElem />}
|
||||
|
||||
{props.player.inGang() && <Gang player={props.player} />}
|
||||
{Player.inGang() && <Gang />}
|
||||
|
||||
{props.player.hasCorporation() && <Corporation player={props.player} />}
|
||||
{Player.hasCorporation() && <Corporation />}
|
||||
|
||||
<CodingContracts />
|
||||
|
||||
{props.player.hasWseAccount && <StockMarket />}
|
||||
{Player.hasWseAccount && <StockMarket />}
|
||||
|
||||
{props.player.sleeves.length > 0 && <Sleeves player={props.player} />}
|
||||
{props.player.augmentations.some((aug) => aug.name === AugmentationNames.StaneksGift1) && <Stanek />}
|
||||
{Player.sleeves.length > 0 && <Sleeves />}
|
||||
{Player.augmentations.some((aug) => aug.name === AugmentationNames.StaneksGift1) && <Stanek />}
|
||||
|
||||
<TimeSkip player={props.player} engine={props.engine} />
|
||||
<Achievements player={props.player} engine={props.engine} />
|
||||
<Entropy player={props.player} engine={props.engine} />
|
||||
<TimeSkip />
|
||||
<Achievements />
|
||||
<Entropy />
|
||||
<SaveFile />
|
||||
</>
|
||||
);
|
||||
|
@ -11,44 +11,39 @@ import { Tooltip } from "@mui/material";
|
||||
import LockIcon from "@mui/icons-material/Lock";
|
||||
import LockOpenIcon from "@mui/icons-material/LockOpen";
|
||||
|
||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||
import { Player } from "../../Player";
|
||||
import { achievements } from "../../Achievements/Achievements";
|
||||
import { IEngine } from "../../IEngine";
|
||||
import { Engine } from "../../engine";
|
||||
|
||||
interface IProps {
|
||||
player: IPlayer;
|
||||
engine: IEngine;
|
||||
}
|
||||
|
||||
export function Achievements(props: IProps): React.ReactElement {
|
||||
const [playerAchievement, setPlayerAchievements] = useState(props.player.achievements.map((m) => m.ID));
|
||||
export function Achievements(): React.ReactElement {
|
||||
const [playerAchievement, setPlayerAchievements] = useState(Player.achievements.map((m) => m.ID));
|
||||
|
||||
function grantAchievement(id: string): void {
|
||||
props.player.giveAchievement(id);
|
||||
setPlayerAchievements(props.player.achievements.map((m) => m.ID));
|
||||
Player.giveAchievement(id);
|
||||
setPlayerAchievements(Player.achievements.map((m) => m.ID));
|
||||
}
|
||||
|
||||
function grantAllAchievements(): void {
|
||||
Object.values(achievements).forEach((a) => props.player.giveAchievement(a.ID));
|
||||
setPlayerAchievements(props.player.achievements.map((m) => m.ID));
|
||||
Object.values(achievements).forEach((a) => Player.giveAchievement(a.ID));
|
||||
setPlayerAchievements(Player.achievements.map((m) => m.ID));
|
||||
}
|
||||
|
||||
function removeAchievement(id: string): void {
|
||||
props.player.achievements = props.player.achievements.filter((a) => a.ID !== id);
|
||||
setPlayerAchievements(props.player.achievements.map((m) => m.ID));
|
||||
Player.achievements = Player.achievements.filter((a) => a.ID !== id);
|
||||
setPlayerAchievements(Player.achievements.map((m) => m.ID));
|
||||
}
|
||||
|
||||
function clearAchievements(): void {
|
||||
props.player.achievements = [];
|
||||
setPlayerAchievements(props.player.achievements.map((m) => m.ID));
|
||||
Player.achievements = [];
|
||||
setPlayerAchievements(Player.achievements.map((m) => m.ID));
|
||||
}
|
||||
|
||||
function disableEngine(): void {
|
||||
props.engine.Counters.achievementsCounter = Number.MAX_VALUE;
|
||||
Engine.Counters.achievementsCounter = Number.MAX_VALUE;
|
||||
}
|
||||
|
||||
function enableEngine(): void {
|
||||
props.engine.Counters.achievementsCounter = 0;
|
||||
Engine.Counters.achievementsCounter = 0;
|
||||
}
|
||||
|
||||
return (
|
||||
|
@ -12,34 +12,30 @@ import {
|
||||
} from "@mui/material";
|
||||
import React, { useState } from "react";
|
||||
import { AugmentationNames } from "../../Augmentation/data/AugmentationNames";
|
||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||
import { Player } from "../../Player";
|
||||
|
||||
interface IProps {
|
||||
player: IPlayer;
|
||||
}
|
||||
|
||||
export function Augmentations(props: IProps): React.ReactElement {
|
||||
export function Augmentations(): React.ReactElement {
|
||||
const [augmentation, setAugmentation] = useState("Augmented Targeting I");
|
||||
|
||||
function setAugmentationDropdown(event: SelectChangeEvent<string>): void {
|
||||
setAugmentation(event.target.value);
|
||||
}
|
||||
function queueAug(): void {
|
||||
props.player.queueAugmentation(augmentation);
|
||||
Player.queueAugmentation(augmentation);
|
||||
}
|
||||
|
||||
function queueAllAugs(): void {
|
||||
for (const augName of Object.values(AugmentationNames)) {
|
||||
props.player.queueAugmentation(augName);
|
||||
Player.queueAugmentation(augName);
|
||||
}
|
||||
}
|
||||
|
||||
function clearAugs(): void {
|
||||
props.player.augmentations = [];
|
||||
Player.augmentations = [];
|
||||
}
|
||||
|
||||
function clearQueuedAugs(): void {
|
||||
props.player.queuedAugmentations = [];
|
||||
Player.queuedAugmentations = [];
|
||||
}
|
||||
|
||||
return (
|
||||
|
@ -7,21 +7,17 @@ import AccordionDetails from "@mui/material/AccordionDetails";
|
||||
import ExpandMoreIcon from "@mui/icons-material/ExpandMore";
|
||||
|
||||
import { Adjuster } from "./Adjuster";
|
||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||
import { Player } from "../../Player";
|
||||
|
||||
const bigNumber = 1e27;
|
||||
|
||||
interface IProps {
|
||||
player: IPlayer;
|
||||
}
|
||||
|
||||
export function Bladeburner(props: IProps): React.ReactElement {
|
||||
const bladeburner = props.player.bladeburner;
|
||||
export function Bladeburner(): React.ReactElement {
|
||||
const bladeburner = Player.bladeburner;
|
||||
if (bladeburner === null) return <></>;
|
||||
function modifyBladeburnerRank(modify: number): (x: number) => void {
|
||||
return function (rank: number): void {
|
||||
if (!bladeburner) return;
|
||||
bladeburner.changeRank(props.player, rank * modify);
|
||||
bladeburner.changeRank(Player, rank * modify);
|
||||
};
|
||||
}
|
||||
|
||||
@ -34,7 +30,7 @@ export function Bladeburner(props: IProps): React.ReactElement {
|
||||
function addTonsBladeburnerRank(): void {
|
||||
if (!bladeburner) return;
|
||||
|
||||
bladeburner.changeRank(props.player, bigNumber);
|
||||
bladeburner.changeRank(Player, bigNumber);
|
||||
}
|
||||
|
||||
function modifyBladeburnerCycles(modify: number): (x: number) => void {
|
||||
|
@ -8,58 +8,54 @@ import ExpandMoreIcon from "@mui/icons-material/ExpandMore";
|
||||
import Typography from "@mui/material/Typography";
|
||||
import Button from "@mui/material/Button";
|
||||
import { Adjuster } from "./Adjuster";
|
||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||
import { Player } from "../../Player";
|
||||
|
||||
const bigNumber = 1e27;
|
||||
|
||||
interface IProps {
|
||||
player: IPlayer;
|
||||
}
|
||||
|
||||
export function Corporation(props: IProps): React.ReactElement {
|
||||
export function Corporation(): React.ReactElement {
|
||||
function addTonsCorporationFunds(): void {
|
||||
if (props.player.corporation) {
|
||||
props.player.corporation.funds = props.player.corporation.funds + bigNumber;
|
||||
if (Player.corporation) {
|
||||
Player.corporation.funds = Player.corporation.funds + bigNumber;
|
||||
}
|
||||
}
|
||||
|
||||
function modifyCorporationFunds(modify: number): (x: number) => void {
|
||||
return function (funds: number): void {
|
||||
if (props.player.corporation) {
|
||||
props.player.corporation.funds += funds * modify;
|
||||
if (Player.corporation) {
|
||||
Player.corporation.funds += funds * modify;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function resetCorporationFunds(): void {
|
||||
if (props.player.corporation) {
|
||||
props.player.corporation.funds = props.player.corporation.funds - props.player.corporation.funds;
|
||||
if (Player.corporation) {
|
||||
Player.corporation.funds = Player.corporation.funds - Player.corporation.funds;
|
||||
}
|
||||
}
|
||||
|
||||
function addTonsCorporationCycles(): void {
|
||||
if (props.player.corporation) {
|
||||
props.player.corporation.storedCycles = bigNumber;
|
||||
if (Player.corporation) {
|
||||
Player.corporation.storedCycles = bigNumber;
|
||||
}
|
||||
}
|
||||
|
||||
function modifyCorporationCycles(modify: number): (x: number) => void {
|
||||
return function (cycles: number): void {
|
||||
if (props.player.corporation) {
|
||||
props.player.corporation.storedCycles += cycles * modify;
|
||||
if (Player.corporation) {
|
||||
Player.corporation.storedCycles += cycles * modify;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function resetCorporationCycles(): void {
|
||||
if (props.player.corporation) {
|
||||
props.player.corporation.storedCycles = 0;
|
||||
if (Player.corporation) {
|
||||
Player.corporation.storedCycles = 0;
|
||||
}
|
||||
}
|
||||
|
||||
function finishCorporationProducts(): void {
|
||||
if (!props.player.corporation) return;
|
||||
props.player.corporation.divisions.forEach((div) => {
|
||||
if (!Player.corporation) return;
|
||||
Player.corporation.divisions.forEach((div) => {
|
||||
Object.keys(div.products).forEach((prod) => {
|
||||
const product = div.products[prod];
|
||||
if (product === undefined) throw new Error("Impossible product undefined");
|
||||
@ -69,8 +65,8 @@ export function Corporation(props: IProps): React.ReactElement {
|
||||
}
|
||||
|
||||
function addCorporationResearch(): void {
|
||||
if (!props.player.corporation) return;
|
||||
props.player.corporation.divisions.forEach((div) => {
|
||||
if (!Player.corporation) return;
|
||||
Player.corporation.divisions.forEach((div) => {
|
||||
div.sciResearch.qty += 1e10;
|
||||
});
|
||||
}
|
||||
|
@ -6,18 +6,12 @@ import AccordionDetails from "@mui/material/AccordionDetails";
|
||||
import ExpandMoreIcon from "@mui/icons-material/ExpandMore";
|
||||
|
||||
import Typography from "@mui/material/Typography";
|
||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||
import { Player } from "../../Player";
|
||||
import { Adjuster } from "./Adjuster";
|
||||
import { IEngine } from "../../IEngine";
|
||||
|
||||
// Update as additional BitNodes get implemented
|
||||
|
||||
interface IProps {
|
||||
player: IPlayer;
|
||||
engine: IEngine;
|
||||
}
|
||||
|
||||
export function Entropy(props: IProps): React.ReactElement {
|
||||
export function Entropy(): React.ReactElement {
|
||||
return (
|
||||
<Accordion TransitionProps={{ unmountOnExit: true }}>
|
||||
<AccordionSummary expandIcon={<ExpandMoreIcon />}>
|
||||
@ -28,20 +22,20 @@ export function Entropy(props: IProps): React.ReactElement {
|
||||
label="Set entropy"
|
||||
placeholder="entropy"
|
||||
add={(num) => {
|
||||
props.player.entropy += num;
|
||||
props.player.applyEntropy(props.player.entropy);
|
||||
Player.entropy += num;
|
||||
Player.applyEntropy(Player.entropy);
|
||||
}}
|
||||
subtract={(num) => {
|
||||
props.player.entropy -= num;
|
||||
props.player.applyEntropy(props.player.entropy);
|
||||
Player.entropy -= num;
|
||||
Player.applyEntropy(Player.entropy);
|
||||
}}
|
||||
tons={() => {
|
||||
props.player.entropy += 1e12;
|
||||
props.player.applyEntropy(props.player.entropy);
|
||||
Player.entropy += 1e12;
|
||||
Player.applyEntropy(Player.entropy);
|
||||
}}
|
||||
reset={() => {
|
||||
props.player.entropy = 0;
|
||||
props.player.applyEntropy(props.player.entropy);
|
||||
Player.entropy = 0;
|
||||
Player.applyEntropy(Player.entropy);
|
||||
}}
|
||||
/>
|
||||
</AccordionDetails>
|
||||
|
@ -9,7 +9,7 @@ import Typography from "@mui/material/Typography";
|
||||
import Button from "@mui/material/Button";
|
||||
import Select, { SelectChangeEvent } from "@mui/material/Select";
|
||||
import { Adjuster } from "./Adjuster";
|
||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||
import { Player } from "../../Player";
|
||||
import { Factions as AllFaction } from "../../Faction/Factions";
|
||||
import FormControl from "@mui/material/FormControl";
|
||||
import MenuItem from "@mui/material/MenuItem";
|
||||
@ -21,11 +21,7 @@ import { FactionNames } from "../../Faction/data/FactionNames";
|
||||
|
||||
const bigNumber = 1e12;
|
||||
|
||||
interface IProps {
|
||||
player: IPlayer;
|
||||
}
|
||||
|
||||
export function Factions(props: IProps): React.ReactElement {
|
||||
export function Factions(): React.ReactElement {
|
||||
const [faction, setFaction] = useState(FactionNames.Illuminati as string);
|
||||
|
||||
function setFactionDropdown(event: SelectChangeEvent<string>): void {
|
||||
@ -33,11 +29,11 @@ export function Factions(props: IProps): React.ReactElement {
|
||||
}
|
||||
|
||||
function receiveInvite(): void {
|
||||
props.player.receiveInvite(faction);
|
||||
Player.receiveInvite(faction);
|
||||
}
|
||||
|
||||
function receiveAllInvites(): void {
|
||||
Object.values(FactionNames).forEach((faction) => props.player.receiveInvite(faction));
|
||||
Object.values(FactionNames).forEach((faction) => Player.receiveInvite(faction));
|
||||
}
|
||||
|
||||
function modifyFactionRep(modifier: number): (x: number) => void {
|
||||
|
@ -7,32 +7,28 @@ import AccordionDetails from "@mui/material/AccordionDetails";
|
||||
import ExpandMoreIcon from "@mui/icons-material/ExpandMore";
|
||||
|
||||
import { Adjuster } from "./Adjuster";
|
||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||
import { Player } from "../../Player";
|
||||
|
||||
const bigNumber = 1e27;
|
||||
|
||||
interface IProps {
|
||||
player: IPlayer;
|
||||
}
|
||||
|
||||
export function Gang(props: IProps): React.ReactElement {
|
||||
export function Gang(): React.ReactElement {
|
||||
function addTonsGangCycles(): void {
|
||||
if (props.player.gang) {
|
||||
props.player.gang.storedCycles = bigNumber;
|
||||
if (Player.gang) {
|
||||
Player.gang.storedCycles = bigNumber;
|
||||
}
|
||||
}
|
||||
|
||||
function modifyGangCycles(modify: number): (x: number) => void {
|
||||
return function (cycles: number): void {
|
||||
if (props.player.gang) {
|
||||
props.player.gang.storedCycles += cycles * modify;
|
||||
if (Player.gang) {
|
||||
Player.gang.storedCycles += cycles * modify;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function resetGangCycles(): void {
|
||||
if (props.player.gang) {
|
||||
props.player.gang.storedCycles = 0;
|
||||
if (Player.gang) {
|
||||
Player.gang.storedCycles = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -8,61 +8,56 @@ import ExpandMoreIcon from "@mui/icons-material/ExpandMore";
|
||||
import Typography from "@mui/material/Typography";
|
||||
import Button from "@mui/material/Button";
|
||||
import { Money } from "../../ui/React/Money";
|
||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||
import { IRouter } from "../../ui/Router";
|
||||
import { Player } from "../../Player";
|
||||
import { Router } from "../../ui/GameRoot";
|
||||
import { MenuItem, SelectChangeEvent, TextField, Select } from "@mui/material";
|
||||
import { Bladeburner } from "../../Bladeburner/Bladeburner";
|
||||
import { GangConstants } from "../../Gang/data/Constants";
|
||||
import { FactionNames } from "../../Faction/data/FactionNames";
|
||||
import { checkForMessagesToSend } from "../../Message/MessageHelpers";
|
||||
|
||||
interface IProps {
|
||||
player: IPlayer;
|
||||
router: IRouter;
|
||||
}
|
||||
|
||||
export function General(props: IProps): React.ReactElement {
|
||||
export function General(): React.ReactElement {
|
||||
const [error, setError] = useState(false);
|
||||
const [corporationName, setCorporationName] = useState("");
|
||||
const [gangFaction, setGangFaction] = useState("");
|
||||
|
||||
function addMoney(n: number) {
|
||||
return function () {
|
||||
props.player.gainMoney(n, "other");
|
||||
Player.gainMoney(n, "other");
|
||||
};
|
||||
}
|
||||
|
||||
function upgradeRam(): void {
|
||||
props.player.getHomeComputer().maxRam *= 2;
|
||||
Player.getHomeComputer().maxRam *= 2;
|
||||
}
|
||||
|
||||
function quickB1tFlum3(): void {
|
||||
props.router.toBitVerse(true, true);
|
||||
Router.toBitVerse(true, true);
|
||||
}
|
||||
|
||||
function b1tflum3(): void {
|
||||
props.router.toBitVerse(true, false);
|
||||
Router.toBitVerse(true, false);
|
||||
}
|
||||
|
||||
function quickHackW0r1dD43m0n(): void {
|
||||
props.router.toBitVerse(false, true);
|
||||
Router.toBitVerse(false, true);
|
||||
}
|
||||
|
||||
function hackW0r1dD43m0n(): void {
|
||||
props.router.toBitVerse(false, false);
|
||||
Router.toBitVerse(false, false);
|
||||
}
|
||||
|
||||
function createCorporation(): void {
|
||||
props.player.startCorporation(corporationName);
|
||||
Player.startCorporation(corporationName);
|
||||
}
|
||||
|
||||
function joinBladeburner(): void {
|
||||
props.player.bladeburner = new Bladeburner(props.player);
|
||||
Player.bladeburner = new Bladeburner();
|
||||
}
|
||||
|
||||
function startGang(): void {
|
||||
const isHacking = gangFaction === FactionNames.NiteSec || gangFaction === FactionNames.TheBlackHand;
|
||||
props.player.startGang(gangFaction, isHacking);
|
||||
Player.startGang(gangFaction, isHacking);
|
||||
}
|
||||
|
||||
function setGangFactionDropdown(event: SelectChangeEvent<string>): void {
|
||||
|
@ -8,29 +8,25 @@ import ExpandMoreIcon from "@mui/icons-material/ExpandMore";
|
||||
import Typography from "@mui/material/Typography";
|
||||
import Button from "@mui/material/Button";
|
||||
import Select, { SelectChangeEvent } from "@mui/material/Select";
|
||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||
import { Player } from "../../Player";
|
||||
import { Programs as AllPrograms } from "../../Programs/Programs";
|
||||
import MenuItem from "@mui/material/MenuItem";
|
||||
|
||||
interface IProps {
|
||||
player: IPlayer;
|
||||
}
|
||||
|
||||
export function Programs(props: IProps): React.ReactElement {
|
||||
export function Programs(): React.ReactElement {
|
||||
const [program, setProgram] = useState("NUKE.exe");
|
||||
function setProgramDropdown(event: SelectChangeEvent<string>): void {
|
||||
setProgram(event.target.value);
|
||||
}
|
||||
function addProgram(): void {
|
||||
if (!props.player.hasProgram(program)) {
|
||||
props.player.getHomeComputer().programs.push(program);
|
||||
if (!Player.hasProgram(program)) {
|
||||
Player.getHomeComputer().programs.push(program);
|
||||
}
|
||||
}
|
||||
|
||||
function addAllPrograms(): void {
|
||||
for (const i of Object.keys(AllPrograms)) {
|
||||
if (!props.player.hasProgram(AllPrograms[i].name)) {
|
||||
props.player.getHomeComputer().programs.push(AllPrograms[i].name);
|
||||
if (!Player.hasProgram(AllPrograms[i].name)) {
|
||||
Player.getHomeComputer().programs.push(AllPrograms[i].name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -7,41 +7,37 @@ import ExpandMoreIcon from "@mui/icons-material/ExpandMore";
|
||||
|
||||
import Button from "@mui/material/Button";
|
||||
import Typography from "@mui/material/Typography";
|
||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||
import { Player } from "../../Player";
|
||||
import { Adjuster } from "./Adjuster";
|
||||
|
||||
interface IProps {
|
||||
player: IPlayer;
|
||||
}
|
||||
|
||||
export function Sleeves(props: IProps): React.ReactElement {
|
||||
export function Sleeves(): React.ReactElement {
|
||||
function sleeveMaxAllShock(): void {
|
||||
for (let i = 0; i < props.player.sleeves.length; ++i) {
|
||||
props.player.sleeves[i].shock = 0;
|
||||
for (let i = 0; i < Player.sleeves.length; ++i) {
|
||||
Player.sleeves[i].shock = 0;
|
||||
}
|
||||
}
|
||||
|
||||
function sleeveClearAllShock(): void {
|
||||
for (let i = 0; i < props.player.sleeves.length; ++i) {
|
||||
props.player.sleeves[i].shock = 100;
|
||||
for (let i = 0; i < Player.sleeves.length; ++i) {
|
||||
Player.sleeves[i].shock = 100;
|
||||
}
|
||||
}
|
||||
|
||||
function sleeveSyncMaxAll(): void {
|
||||
for (let i = 0; i < props.player.sleeves.length; ++i) {
|
||||
props.player.sleeves[i].sync = 100;
|
||||
for (let i = 0; i < Player.sleeves.length; ++i) {
|
||||
Player.sleeves[i].sync = 100;
|
||||
}
|
||||
}
|
||||
|
||||
function sleeveSyncClearAll(): void {
|
||||
for (let i = 0; i < props.player.sleeves.length; ++i) {
|
||||
props.player.sleeves[i].sync = 0;
|
||||
for (let i = 0; i < Player.sleeves.length; ++i) {
|
||||
Player.sleeves[i].sync = 0;
|
||||
}
|
||||
}
|
||||
|
||||
function sleeveSetStoredCycles(cycles: number): void {
|
||||
for (let i = 0; i < props.player.sleeves.length; ++i) {
|
||||
props.player.sleeves[i].storedCycles = cycles;
|
||||
for (let i = 0; i < Player.sleeves.length; ++i) {
|
||||
Player.sleeves[i].storedCycles = cycles;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -8,35 +8,31 @@ import ExpandMoreIcon from "@mui/icons-material/ExpandMore";
|
||||
import Typography from "@mui/material/Typography";
|
||||
import Button from "@mui/material/Button";
|
||||
import { PlayerOwnedSourceFile } from "../../SourceFile/PlayerOwnedSourceFile";
|
||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||
import { Player } from "../../Player";
|
||||
import ButtonGroup from "@mui/material/ButtonGroup";
|
||||
|
||||
// Update as additional BitNodes get implemented
|
||||
const validSFN = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13];
|
||||
|
||||
interface IProps {
|
||||
player: IPlayer;
|
||||
}
|
||||
|
||||
export function SourceFiles(props: IProps): React.ReactElement {
|
||||
export function SourceFiles(): React.ReactElement {
|
||||
function setSF(sfN: number, sfLvl: number) {
|
||||
return function () {
|
||||
if (sfN === 9) {
|
||||
props.player.hacknetNodes = [];
|
||||
Player.hacknetNodes = [];
|
||||
}
|
||||
if (sfLvl === 0) {
|
||||
props.player.sourceFiles = props.player.sourceFiles.filter((sf) => sf.n !== sfN);
|
||||
Player.sourceFiles = Player.sourceFiles.filter((sf) => sf.n !== sfN);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!props.player.sourceFiles.some((sf) => sf.n === sfN)) {
|
||||
props.player.sourceFiles.push(new PlayerOwnedSourceFile(sfN, sfLvl));
|
||||
if (!Player.sourceFiles.some((sf) => sf.n === sfN)) {
|
||||
Player.sourceFiles.push(new PlayerOwnedSourceFile(sfN, sfLvl));
|
||||
return;
|
||||
}
|
||||
|
||||
for (let i = 0; i < props.player.sourceFiles.length; i++) {
|
||||
if (props.player.sourceFiles[i].n === sfN) {
|
||||
props.player.sourceFiles[i].lvl = sfLvl;
|
||||
for (let i = 0; i < Player.sourceFiles.length; i++) {
|
||||
if (Player.sourceFiles[i].n === sfN) {
|
||||
Player.sourceFiles[i].lvl = sfLvl;
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -51,7 +47,7 @@ export function SourceFiles(props: IProps): React.ReactElement {
|
||||
}
|
||||
|
||||
function clearExploits(): void {
|
||||
props.player.exploits = [];
|
||||
Player.exploits = [];
|
||||
}
|
||||
|
||||
return (
|
||||
|
@ -8,132 +8,128 @@ import ExpandMoreIcon from "@mui/icons-material/ExpandMore";
|
||||
import Typography from "@mui/material/Typography";
|
||||
import Button from "@mui/material/Button";
|
||||
import { Adjuster } from "./Adjuster";
|
||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||
import { Player } from "../../Player";
|
||||
|
||||
const bigNumber = 1e27;
|
||||
|
||||
interface IProps {
|
||||
player: IPlayer;
|
||||
}
|
||||
|
||||
export function Stats(props: IProps): React.ReactElement {
|
||||
export function Stats(): React.ReactElement {
|
||||
function modifyExp(stat: string, modifier: number) {
|
||||
return function (exp: number) {
|
||||
switch (stat) {
|
||||
case "hacking":
|
||||
if (exp) {
|
||||
props.player.gainHackingExp(exp * modifier);
|
||||
Player.gainHackingExp(exp * modifier);
|
||||
}
|
||||
break;
|
||||
case "strength":
|
||||
if (exp) {
|
||||
props.player.gainStrengthExp(exp * modifier);
|
||||
Player.gainStrengthExp(exp * modifier);
|
||||
}
|
||||
break;
|
||||
case "defense":
|
||||
if (exp) {
|
||||
props.player.gainDefenseExp(exp * modifier);
|
||||
Player.gainDefenseExp(exp * modifier);
|
||||
}
|
||||
break;
|
||||
case "dexterity":
|
||||
if (exp) {
|
||||
props.player.gainDexterityExp(exp * modifier);
|
||||
Player.gainDexterityExp(exp * modifier);
|
||||
}
|
||||
break;
|
||||
case "agility":
|
||||
if (exp) {
|
||||
props.player.gainAgilityExp(exp * modifier);
|
||||
Player.gainAgilityExp(exp * modifier);
|
||||
}
|
||||
break;
|
||||
case "charisma":
|
||||
if (exp) {
|
||||
props.player.gainCharismaExp(exp * modifier);
|
||||
Player.gainCharismaExp(exp * modifier);
|
||||
}
|
||||
break;
|
||||
case "intelligence":
|
||||
if (exp) {
|
||||
props.player.gainIntelligenceExp(exp * modifier);
|
||||
Player.gainIntelligenceExp(exp * modifier);
|
||||
}
|
||||
break;
|
||||
}
|
||||
props.player.updateSkillLevels();
|
||||
Player.updateSkillLevels();
|
||||
};
|
||||
}
|
||||
|
||||
function modifyKarma(modifier: number) {
|
||||
return function (amt: number) {
|
||||
props.player.karma += amt * modifier;
|
||||
Player.karma += amt * modifier;
|
||||
};
|
||||
}
|
||||
|
||||
function tonsOfExp(): void {
|
||||
props.player.gainHackingExp(bigNumber);
|
||||
props.player.gainStrengthExp(bigNumber);
|
||||
props.player.gainDefenseExp(bigNumber);
|
||||
props.player.gainDexterityExp(bigNumber);
|
||||
props.player.gainAgilityExp(bigNumber);
|
||||
props.player.gainCharismaExp(bigNumber);
|
||||
props.player.gainIntelligenceExp(bigNumber);
|
||||
props.player.updateSkillLevels();
|
||||
Player.gainHackingExp(bigNumber);
|
||||
Player.gainStrengthExp(bigNumber);
|
||||
Player.gainDefenseExp(bigNumber);
|
||||
Player.gainDexterityExp(bigNumber);
|
||||
Player.gainAgilityExp(bigNumber);
|
||||
Player.gainCharismaExp(bigNumber);
|
||||
Player.gainIntelligenceExp(bigNumber);
|
||||
Player.updateSkillLevels();
|
||||
}
|
||||
|
||||
function resetAllExp(): void {
|
||||
props.player.exp.hacking = 0;
|
||||
props.player.exp.strength = 0;
|
||||
props.player.exp.defense = 0;
|
||||
props.player.exp.dexterity = 0;
|
||||
props.player.exp.agility = 0;
|
||||
props.player.exp.charisma = 0;
|
||||
props.player.exp.intelligence = 0;
|
||||
props.player.updateSkillLevels();
|
||||
Player.exp.hacking = 0;
|
||||
Player.exp.strength = 0;
|
||||
Player.exp.defense = 0;
|
||||
Player.exp.dexterity = 0;
|
||||
Player.exp.agility = 0;
|
||||
Player.exp.charisma = 0;
|
||||
Player.exp.intelligence = 0;
|
||||
Player.updateSkillLevels();
|
||||
}
|
||||
|
||||
function resetExperience(stat: string): () => void {
|
||||
return function () {
|
||||
switch (stat) {
|
||||
case "hacking":
|
||||
props.player.exp.hacking = 0;
|
||||
Player.exp.hacking = 0;
|
||||
break;
|
||||
case "strength":
|
||||
props.player.exp.strength = 0;
|
||||
Player.exp.strength = 0;
|
||||
break;
|
||||
case "defense":
|
||||
props.player.exp.defense = 0;
|
||||
Player.exp.defense = 0;
|
||||
break;
|
||||
case "dexterity":
|
||||
props.player.exp.dexterity = 0;
|
||||
Player.exp.dexterity = 0;
|
||||
break;
|
||||
case "agility":
|
||||
props.player.exp.agility = 0;
|
||||
Player.exp.agility = 0;
|
||||
break;
|
||||
case "charisma":
|
||||
props.player.exp.charisma = 0;
|
||||
Player.exp.charisma = 0;
|
||||
break;
|
||||
case "intelligence":
|
||||
props.player.exp.intelligence = 0;
|
||||
Player.exp.intelligence = 0;
|
||||
break;
|
||||
}
|
||||
props.player.updateSkillLevels();
|
||||
Player.updateSkillLevels();
|
||||
};
|
||||
}
|
||||
|
||||
function resetKarma(): () => void {
|
||||
return function () {
|
||||
props.player.karma = 0;
|
||||
Player.karma = 0;
|
||||
};
|
||||
}
|
||||
|
||||
function enableIntelligence(): void {
|
||||
if (props.player.skills.intelligence === 0) {
|
||||
props.player.skills.intelligence = 1;
|
||||
props.player.updateSkillLevels();
|
||||
if (Player.skills.intelligence === 0) {
|
||||
Player.skills.intelligence = 1;
|
||||
Player.updateSkillLevels();
|
||||
}
|
||||
}
|
||||
|
||||
function disableIntelligence(): void {
|
||||
props.player.exp.intelligence = 0;
|
||||
props.player.skills.intelligence = 0;
|
||||
props.player.updateSkillLevels();
|
||||
Player.exp.intelligence = 0;
|
||||
Player.skills.intelligence = 0;
|
||||
Player.updateSkillLevels();
|
||||
}
|
||||
|
||||
return (
|
||||
|
@ -7,22 +7,17 @@ import ExpandMoreIcon from "@mui/icons-material/ExpandMore";
|
||||
|
||||
import Typography from "@mui/material/Typography";
|
||||
import Button from "@mui/material/Button";
|
||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||
import { Player } from "../../Player";
|
||||
import { saveObject } from "../../SaveObject";
|
||||
import { IEngine } from "../../IEngine";
|
||||
import { Engine } from "../../engine";
|
||||
|
||||
// Update as additional BitNodes get implemented
|
||||
|
||||
interface IProps {
|
||||
player: IPlayer;
|
||||
engine: IEngine;
|
||||
}
|
||||
|
||||
export function TimeSkip(props: IProps): React.ReactElement {
|
||||
export function TimeSkip(): React.ReactElement {
|
||||
function timeskip(time: number) {
|
||||
return () => {
|
||||
props.player.lastUpdate -= time;
|
||||
props.engine._lastUpdate -= time;
|
||||
Player.lastUpdate -= time;
|
||||
Engine._lastUpdate -= time;
|
||||
saveObject.saveGame();
|
||||
setTimeout(() => location.reload(), 1000);
|
||||
};
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { Factions } from "./Faction/Factions";
|
||||
import { IPlayer } from "./PersonObjects/IPlayer";
|
||||
import { Player } from "./Player";
|
||||
|
||||
export let LastExportBonus = 0;
|
||||
|
||||
@ -9,9 +9,9 @@ export function canGetBonus(): boolean {
|
||||
return now - LastExportBonus > bonusTimer;
|
||||
}
|
||||
|
||||
export function onExport(p: IPlayer): void {
|
||||
export function onExport(): void {
|
||||
if (!canGetBonus()) return;
|
||||
for (const facName of p.factions) {
|
||||
for (const facName of Player.factions) {
|
||||
Factions[facName].favor++;
|
||||
}
|
||||
LastExportBonus = new Date().getTime();
|
||||
|
@ -7,7 +7,6 @@ import { BitNodeMultipliers } from "../BitNode/BitNodeMultipliers";
|
||||
import { Faction } from "./Faction";
|
||||
import { Factions } from "./Factions";
|
||||
import { Player } from "../Player";
|
||||
import { IPlayer } from "../PersonObjects/IPlayer";
|
||||
import { Settings } from "../Settings/Settings";
|
||||
import {
|
||||
getHackingWorkRepGain,
|
||||
@ -59,7 +58,7 @@ export function hasAugmentationPrereqs(aug: Augmentation): boolean {
|
||||
|
||||
export function purchaseAugmentation(aug: Augmentation, fac: Faction, sing = false): string {
|
||||
const hasPrereqs = hasAugmentationPrereqs(aug);
|
||||
const augCosts = aug.getCost(Player);
|
||||
const augCosts = aug.getCost();
|
||||
if (!hasPrereqs) {
|
||||
const txt = `You must first purchase or install ${aug.prereqs
|
||||
.filter((req) => !Player.hasAugmentation(req))
|
||||
@ -84,7 +83,7 @@ export function purchaseAugmentation(aug: Augmentation, fac: Faction, sing = fal
|
||||
} else if (augCosts.moneyCost === 0 || Player.money >= augCosts.moneyCost) {
|
||||
const queuedAugmentation = new PlayerOwnedAugmentation(aug.name);
|
||||
if (aug.name == AugmentationNames.NeuroFluxGovernor) {
|
||||
queuedAugmentation.level = aug.getLevel(Player);
|
||||
queuedAugmentation.level = aug.getLevel();
|
||||
}
|
||||
Player.queuedAugmentations.push(queuedAugmentation);
|
||||
|
||||
@ -134,20 +133,20 @@ export function processPassiveFactionRepGain(numCycles: number): void {
|
||||
}
|
||||
}
|
||||
|
||||
export const getFactionAugmentationsFiltered = (player: IPlayer, faction: Faction): string[] => {
|
||||
export const getFactionAugmentationsFiltered = (faction: Faction): string[] => {
|
||||
// If player has a gang with this faction, return (almost) all augmentations
|
||||
if (player.hasGangWith(faction.name)) {
|
||||
if (Player.hasGangWith(faction.name)) {
|
||||
let augs = Object.values(StaticAugmentations);
|
||||
|
||||
// Remove special augs
|
||||
augs = augs.filter((a) => !a.isSpecial && a.name !== AugmentationNames.CongruityImplant);
|
||||
|
||||
if (player.bitNodeN === 2) {
|
||||
if (Player.bitNodeN === 2) {
|
||||
// TRP is not available outside of BN2 for Gangs
|
||||
augs.push(StaticAugmentations[AugmentationNames.TheRedPill]);
|
||||
}
|
||||
|
||||
const rng = SFC32RNG(`BN${player.bitNodeN}.${player.sourceFileLvl(player.bitNodeN)}`);
|
||||
const rng = SFC32RNG(`BN${Player.bitNodeN}.${Player.sourceFileLvl(Player.bitNodeN)}`);
|
||||
// Remove faction-unique augs that don't belong to this faction
|
||||
const uniqueFilter = (a: Augmentation): boolean => {
|
||||
// Keep all the non-unique one
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { CONSTANTS } from "../../Constants";
|
||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||
import { IPerson } from "../../PersonObjects/IPerson";
|
||||
|
||||
export function repFromDonation(amt: number, player: IPlayer): number {
|
||||
return (amt / CONSTANTS.DonateMoneyToRepDivisor) * player.mults.faction_rep;
|
||||
export function repFromDonation(amt: number, person: IPerson): number {
|
||||
return (amt / CONSTANTS.DonateMoneyToRepDivisor) * person.mults.faction_rep;
|
||||
}
|
||||
|
@ -10,7 +10,7 @@ import { AugmentationNames } from "../../Augmentation/data/AugmentationNames";
|
||||
import { PurchasableAugmentations } from "../../Augmentation/ui/PurchasableAugmentations";
|
||||
import { PurchaseAugmentationsOrderSetting } from "../../Settings/SettingEnums";
|
||||
import { Settings } from "../../Settings/Settings";
|
||||
import { use } from "../../ui/Context";
|
||||
import { Player } from "../../Player";
|
||||
import { numeralWrapper } from "../../ui/numeralFormat";
|
||||
import { Favor } from "../../ui/React/Favor";
|
||||
import { Reputation } from "../../ui/React/Reputation";
|
||||
@ -24,8 +24,6 @@ type IProps = {
|
||||
};
|
||||
|
||||
export function AugmentationsPage(props: IProps): React.ReactElement {
|
||||
const player = use.Player();
|
||||
|
||||
const setRerender = useState(false)[1];
|
||||
|
||||
function rerender(): void {
|
||||
@ -33,7 +31,7 @@ export function AugmentationsPage(props: IProps): React.ReactElement {
|
||||
}
|
||||
|
||||
function getAugs(): string[] {
|
||||
return getFactionAugmentationsFiltered(player, props.faction);
|
||||
return getFactionAugmentationsFiltered(props.faction);
|
||||
}
|
||||
|
||||
function getAugsSorted(): string[] {
|
||||
@ -61,7 +59,7 @@ export function AugmentationsPage(props: IProps): React.ReactElement {
|
||||
throw new Error("Invalid Augmentation Names");
|
||||
}
|
||||
|
||||
return aug1.getCost(player).moneyCost - aug2.getCost(player).moneyCost;
|
||||
return aug1.getCost().moneyCost - aug2.getCost().moneyCost;
|
||||
});
|
||||
|
||||
return augs;
|
||||
@ -71,11 +69,11 @@ export function AugmentationsPage(props: IProps): React.ReactElement {
|
||||
const augs = getAugs();
|
||||
function canBuy(augName: string): boolean {
|
||||
const aug = StaticAugmentations[augName];
|
||||
const augCosts = aug.getCost(player);
|
||||
const augCosts = aug.getCost();
|
||||
const repCost = augCosts.repCost;
|
||||
const hasReq = props.faction.playerReputation >= repCost;
|
||||
const hasRep = hasAugmentationPrereqs(aug);
|
||||
const hasCost = augCosts.moneyCost !== 0 && player.money > augCosts.moneyCost;
|
||||
const hasCost = augCosts.moneyCost !== 0 && Player.money > augCosts.moneyCost;
|
||||
return hasCost && hasReq && hasRep;
|
||||
}
|
||||
const buy = augs.filter(canBuy).sort((augName1, augName2) => {
|
||||
@ -85,7 +83,7 @@ export function AugmentationsPage(props: IProps): React.ReactElement {
|
||||
throw new Error("Invalid Augmentation Names");
|
||||
}
|
||||
|
||||
return aug1.getCost(player).moneyCost - aug2.getCost(player).moneyCost;
|
||||
return aug1.getCost().moneyCost - aug2.getCost().moneyCost;
|
||||
});
|
||||
const cantBuy = augs
|
||||
.filter((aug) => !canBuy(aug))
|
||||
@ -95,7 +93,7 @@ export function AugmentationsPage(props: IProps): React.ReactElement {
|
||||
if (aug1 == null || aug2 == null) {
|
||||
throw new Error("Invalid Augmentation Names");
|
||||
}
|
||||
return aug1.getCost(player).repCost - aug2.getCost(player).repCost;
|
||||
return aug1.getCost().repCost - aug2.getCost().repCost;
|
||||
});
|
||||
|
||||
return buy.concat(cantBuy);
|
||||
@ -109,7 +107,7 @@ export function AugmentationsPage(props: IProps): React.ReactElement {
|
||||
if (aug1 == null || aug2 == null) {
|
||||
throw new Error("Invalid Augmentation Names");
|
||||
}
|
||||
return aug1.getCost(player).repCost - aug2.getCost(player).repCost;
|
||||
return aug1.getCost().repCost - aug2.getCost().repCost;
|
||||
});
|
||||
|
||||
return augs;
|
||||
@ -128,7 +126,7 @@ export function AugmentationsPage(props: IProps): React.ReactElement {
|
||||
const purchasable = augs.filter(
|
||||
(aug: string) =>
|
||||
aug === AugmentationNames.NeuroFluxGovernor ||
|
||||
(!player.augmentations.some((a) => a.name === aug) && !player.queuedAugmentations.some((a) => a.name === aug)),
|
||||
(!Player.augmentations.some((a) => a.name === aug) && !Player.queuedAugmentations.some((a) => a.name === aug)),
|
||||
);
|
||||
const owned = augs.filter((aug: string) => !purchasable.includes(aug));
|
||||
|
||||
@ -195,16 +193,15 @@ export function AugmentationsPage(props: IProps): React.ReactElement {
|
||||
<PurchasableAugmentations
|
||||
augNames={purchasable}
|
||||
ownedAugNames={owned}
|
||||
player={player}
|
||||
canPurchase={(player, aug) => {
|
||||
const costs = aug.getCost(player);
|
||||
canPurchase={(aug) => {
|
||||
const costs = aug.getCost();
|
||||
return (
|
||||
hasAugmentationPrereqs(aug) &&
|
||||
props.faction.playerReputation >= costs.repCost &&
|
||||
(costs.moneyCost === 0 || player.money > costs.moneyCost)
|
||||
(costs.moneyCost === 0 || Player.money > costs.moneyCost)
|
||||
);
|
||||
}}
|
||||
purchaseAugmentation={(player, aug, showModal) => {
|
||||
purchaseAugmentation={(aug, showModal) => {
|
||||
if (!Settings.SuppressBuyAugmentationConfirmation) {
|
||||
showModal(true);
|
||||
} else {
|
||||
|
@ -5,7 +5,7 @@ import React, { useState } from "react";
|
||||
|
||||
import { CONSTANTS } from "../../Constants";
|
||||
import { Faction } from "../Faction";
|
||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||
import { Player } from "../../Player";
|
||||
import { repFromDonation } from "../formulas/donation";
|
||||
import { Favor } from "../../ui/React/Favor";
|
||||
|
||||
@ -24,7 +24,6 @@ type IProps = {
|
||||
faction: Faction;
|
||||
disabled: boolean;
|
||||
favorToDonate: number;
|
||||
p: IPlayer;
|
||||
rerender: () => void;
|
||||
};
|
||||
|
||||
@ -35,7 +34,7 @@ export function DonateOption(props: IProps): React.ReactElement {
|
||||
function canDonate(): boolean {
|
||||
if (isNaN(donateAmt)) return false;
|
||||
if (isNaN(donateAmt) || donateAmt <= 0) return false;
|
||||
if (props.p.money < donateAmt) return false;
|
||||
if (Player.money < donateAmt) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -44,8 +43,8 @@ export function DonateOption(props: IProps): React.ReactElement {
|
||||
const amt = donateAmt;
|
||||
if (isNaN(amt)) return;
|
||||
if (!canDonate()) return;
|
||||
props.p.loseMoney(amt, "other");
|
||||
const repGain = repFromDonation(amt, props.p);
|
||||
Player.loseMoney(amt, "other");
|
||||
const repGain = repFromDonation(amt, Player);
|
||||
props.faction.playerReputation += repGain;
|
||||
dialogBoxCreate(
|
||||
<>
|
||||
@ -58,12 +57,12 @@ export function DonateOption(props: IProps): React.ReactElement {
|
||||
function Status(): React.ReactElement {
|
||||
if (isNaN(donateAmt)) return <></>;
|
||||
if (!canDonate()) {
|
||||
if (props.p.money < donateAmt) return <Typography>Insufficient funds</Typography>;
|
||||
if (Player.money < donateAmt) return <Typography>Insufficient funds</Typography>;
|
||||
return <Typography>Invalid donate amount entered!</Typography>;
|
||||
}
|
||||
return (
|
||||
<Typography>
|
||||
This donation will result in <Reputation reputation={repFromDonation(donateAmt, props.p)} /> reputation gain
|
||||
This donation will result in <Reputation reputation={repFromDonation(donateAmt, Player)} /> reputation gain
|
||||
</Typography>
|
||||
);
|
||||
}
|
||||
|
@ -15,7 +15,8 @@ import { CONSTANTS } from "../../Constants";
|
||||
import { BitNodeMultipliers } from "../../BitNode/BitNodeMultipliers";
|
||||
import { Faction } from "../Faction";
|
||||
|
||||
import { use } from "../../ui/Context";
|
||||
import { Router } from "../../ui/GameRoot";
|
||||
import { Player } from "../../Player";
|
||||
|
||||
import { Typography, Button } from "@mui/material";
|
||||
import { CovenantPurchasesRoot } from "../../PersonObjects/Sleeve/ui/CovenantPurchasesRoot";
|
||||
@ -58,18 +59,16 @@ interface IMainProps {
|
||||
}
|
||||
|
||||
function MainPage({ faction, rerender, onAugmentations }: IMainProps): React.ReactElement {
|
||||
const player = use.Player();
|
||||
const router = use.Router();
|
||||
const [sleevesOpen, setSleevesOpen] = useState(false);
|
||||
const factionInfo = faction.getInfo();
|
||||
|
||||
function startWork(): void {
|
||||
player.startFocusing();
|
||||
router.toWork();
|
||||
Player.startFocusing();
|
||||
Router.toWork();
|
||||
}
|
||||
|
||||
function startFieldWork(faction: Faction): void {
|
||||
player.startWork(
|
||||
Player.startWork(
|
||||
new FactionWork({
|
||||
singularity: false,
|
||||
faction: faction.name,
|
||||
@ -80,7 +79,7 @@ function MainPage({ faction, rerender, onAugmentations }: IMainProps): React.Rea
|
||||
}
|
||||
|
||||
function startHackingContracts(faction: Faction): void {
|
||||
player.startWork(
|
||||
Player.startWork(
|
||||
new FactionWork({
|
||||
singularity: false,
|
||||
faction: faction.name,
|
||||
@ -91,7 +90,7 @@ function MainPage({ faction, rerender, onAugmentations }: IMainProps): React.Rea
|
||||
}
|
||||
|
||||
function startSecurityWork(faction: Faction): void {
|
||||
player.startWork(
|
||||
Player.startWork(
|
||||
new FactionWork({
|
||||
singularity: false,
|
||||
faction: faction.name,
|
||||
@ -103,18 +102,18 @@ function MainPage({ faction, rerender, onAugmentations }: IMainProps): React.Rea
|
||||
|
||||
// We have a special flag for whether the player this faction is the player's
|
||||
// gang faction because if the player has a gang, they cannot do any other action
|
||||
const isPlayersGang = player.inGang() && player.getGangName() === faction.name;
|
||||
const isPlayersGang = Player.inGang() && Player.getGangName() === faction.name;
|
||||
|
||||
// Flags for whether special options (gang, sleeve purchases, donate, etc.)
|
||||
// should be shown
|
||||
const favorToDonate = Math.floor(CONSTANTS.BaseFavorToDonate * BitNodeMultipliers.RepToDonateToFaction);
|
||||
const canDonate = faction.favor >= favorToDonate;
|
||||
|
||||
const canPurchaseSleeves = faction.name === FactionNames.TheCovenant && player.bitNodeN === 10;
|
||||
const canPurchaseSleeves = faction.name === FactionNames.TheCovenant && Player.bitNodeN === 10;
|
||||
|
||||
return (
|
||||
<>
|
||||
<Button onClick={() => router.toFactions()}>Back</Button>
|
||||
<Button onClick={() => Router.toFactions()}>Back</Button>
|
||||
<Typography variant="h4" color="primary">
|
||||
{faction.name}
|
||||
</Typography>
|
||||
@ -134,13 +133,7 @@ function MainPage({ faction, rerender, onAugmentations }: IMainProps): React.Rea
|
||||
<Option buttonText={"Security Work"} infoText={securityWorkInfo} onClick={() => startSecurityWork(faction)} />
|
||||
)}
|
||||
{!isPlayersGang && factionInfo.offersWork() && (
|
||||
<DonateOption
|
||||
faction={faction}
|
||||
p={player}
|
||||
rerender={rerender}
|
||||
favorToDonate={favorToDonate}
|
||||
disabled={!canDonate}
|
||||
/>
|
||||
<DonateOption faction={faction} rerender={rerender} favorToDonate={favorToDonate} disabled={!canDonate} />
|
||||
)}
|
||||
<Option buttonText={"Purchase Augmentations"} infoText={augmentationsInfo} onClick={onAugmentations} />
|
||||
{canPurchaseSleeves && (
|
||||
@ -159,8 +152,6 @@ function MainPage({ faction, rerender, onAugmentations }: IMainProps): React.Rea
|
||||
|
||||
export function FactionRoot(props: IProps): React.ReactElement {
|
||||
const setRerender = useState(false)[1];
|
||||
const player = use.Player();
|
||||
const router = use.Router();
|
||||
const [purchasingAugs, setPurchasingAugs] = useState(props.augPage);
|
||||
|
||||
function rerender(): void {
|
||||
@ -174,13 +165,13 @@ export function FactionRoot(props: IProps): React.ReactElement {
|
||||
|
||||
const faction = props.faction;
|
||||
|
||||
if (player && !player.factions.includes(faction.name)) {
|
||||
if (!Player.factions.includes(faction.name)) {
|
||||
return (
|
||||
<>
|
||||
<Typography variant="h4" color="primary">
|
||||
You have not joined {faction.name} yet!
|
||||
</Typography>
|
||||
<Button onClick={() => router.toFactions()}>Back to Factions</Button>
|
||||
<Button onClick={() => Router.toFactions()}>Back to Factions</Button>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
@ -1,10 +1,10 @@
|
||||
import { Explore, Info, LastPage, LocalPolice, NewReleases, Report, SportsMma } from "@mui/icons-material";
|
||||
import { Box, Button, Container, Paper, Tooltip, Typography, useTheme } from "@mui/material";
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||
import { Player } from "../../Player";
|
||||
import { Settings } from "../../Settings/Settings";
|
||||
import { numeralWrapper } from "../../ui/numeralFormat";
|
||||
import { IRouter } from "../../ui/Router";
|
||||
import { Router } from "../../ui/GameRoot";
|
||||
import { FactionNames } from "../data/FactionNames";
|
||||
import { Faction } from "../Faction";
|
||||
import { getFactionAugmentationsFiltered, joinFaction } from "../FactionHelpers";
|
||||
@ -12,10 +12,10 @@ import { Factions } from "../Factions";
|
||||
|
||||
export const InvitationsSeen: string[] = [];
|
||||
|
||||
const getAugsLeft = (faction: Faction, player: IPlayer): number => {
|
||||
const augs = getFactionAugmentationsFiltered(player, faction);
|
||||
const getAugsLeft = (faction: Faction): number => {
|
||||
const augs = getFactionAugmentationsFiltered(faction);
|
||||
|
||||
return augs.filter((augmentation: string) => !player.hasAugmentation(augmentation)).length;
|
||||
return augs.filter((augmentation: string) => !Player.hasAugmentation(augmentation)).length;
|
||||
};
|
||||
|
||||
interface IWorkTypeProps {
|
||||
@ -50,8 +50,6 @@ const WorkTypesOffered = (props: IWorkTypeProps): React.ReactElement => {
|
||||
};
|
||||
|
||||
interface IFactionProps {
|
||||
player: IPlayer;
|
||||
router: IRouter;
|
||||
faction: Faction;
|
||||
|
||||
joined: boolean;
|
||||
@ -63,11 +61,11 @@ const FactionElement = (props: IFactionProps): React.ReactElement => {
|
||||
const facInfo = props.faction.getInfo();
|
||||
|
||||
function openFaction(faction: Faction): void {
|
||||
props.router.toFaction(faction);
|
||||
Router.toFaction(faction);
|
||||
}
|
||||
|
||||
function openFactionAugPage(faction: Faction): void {
|
||||
props.router.toFaction(faction, true);
|
||||
Router.toFaction(faction, true);
|
||||
}
|
||||
|
||||
function acceptInvitation(event: React.MouseEvent<HTMLButtonElement, MouseEvent>, faction: string): void {
|
||||
@ -124,7 +122,7 @@ const FactionElement = (props: IFactionProps): React.ReactElement => {
|
||||
</span>
|
||||
|
||||
<span style={{ display: "flex", alignItems: "center" }}>
|
||||
{props.player.hasGangWith(props.faction.name) && (
|
||||
{Player.hasGangWith(props.faction.name) && (
|
||||
<Tooltip title="You have a gang with this Faction">
|
||||
<SportsMma sx={{ color: Settings.theme.hp, ml: 1 }} />
|
||||
</Tooltip>
|
||||
@ -157,11 +155,11 @@ const FactionElement = (props: IFactionProps): React.ReactElement => {
|
||||
</Typography>
|
||||
|
||||
<span style={{ display: "flex", alignItems: "center" }}>
|
||||
{!props.player.hasGangWith(props.faction.name) && <WorkTypesOffered faction={props.faction} />}
|
||||
{!Player.hasGangWith(props.faction.name) && <WorkTypesOffered faction={props.faction} />}
|
||||
|
||||
{props.joined && (
|
||||
<Typography variant="body2" sx={{ display: "flex" }}>
|
||||
{getAugsLeft(props.faction, props.player)} Augmentations left
|
||||
{getAugsLeft(props.faction)} Augmentations left
|
||||
</Typography>
|
||||
)}
|
||||
</span>
|
||||
@ -182,12 +180,7 @@ const FactionElement = (props: IFactionProps): React.ReactElement => {
|
||||
);
|
||||
};
|
||||
|
||||
interface IProps {
|
||||
player: IPlayer;
|
||||
router: IRouter;
|
||||
}
|
||||
|
||||
export function FactionsRoot(props: IProps): React.ReactElement {
|
||||
export function FactionsRoot(): React.ReactElement {
|
||||
const theme = useTheme();
|
||||
const setRerender = useState(false)[1];
|
||||
function rerender(): void {
|
||||
@ -199,16 +192,16 @@ export function FactionsRoot(props: IProps): React.ReactElement {
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
props.player.factionInvitations.forEach((faction) => {
|
||||
Player.factionInvitations.forEach((faction) => {
|
||||
if (InvitationsSeen.includes(faction)) return;
|
||||
InvitationsSeen.push(faction);
|
||||
});
|
||||
}, []);
|
||||
|
||||
const allFactions = Object.values(FactionNames).map((faction) => faction as string);
|
||||
const allJoinedFactions = [...props.player.factions];
|
||||
const allJoinedFactions = [...Player.factions];
|
||||
allJoinedFactions.sort((a, b) => allFactions.indexOf(a) - allFactions.indexOf(b));
|
||||
const invitations = props.player.factionInvitations;
|
||||
const invitations = Player.factionInvitations;
|
||||
|
||||
return (
|
||||
<Container disableGutters maxWidth="lg" sx={{ mx: 0, mb: 10 }}>
|
||||
@ -249,16 +242,7 @@ export function FactionsRoot(props: IProps): React.ReactElement {
|
||||
<Box>
|
||||
{invitations.map((facName) => {
|
||||
if (!Factions.hasOwnProperty(facName)) return null;
|
||||
return (
|
||||
<FactionElement
|
||||
key={facName}
|
||||
faction={Factions[facName]}
|
||||
player={props.player}
|
||||
router={props.router}
|
||||
joined={false}
|
||||
rerender={rerender}
|
||||
/>
|
||||
);
|
||||
return <FactionElement key={facName} faction={Factions[facName]} joined={false} rerender={rerender} />;
|
||||
})}
|
||||
</Box>
|
||||
</span>
|
||||
@ -272,16 +256,7 @@ export function FactionsRoot(props: IProps): React.ReactElement {
|
||||
{allJoinedFactions.length > 0 ? (
|
||||
allJoinedFactions.map((facName) => {
|
||||
if (!Factions.hasOwnProperty(facName)) return null;
|
||||
return (
|
||||
<FactionElement
|
||||
key={facName}
|
||||
faction={Factions[facName]}
|
||||
player={props.player}
|
||||
router={props.router}
|
||||
joined={true}
|
||||
rerender={rerender}
|
||||
/>
|
||||
);
|
||||
return <FactionElement key={facName} faction={Factions[facName]} joined={true} rerender={rerender} />;
|
||||
})
|
||||
) : (
|
||||
<Typography>You have not yet joined any Factions.</Typography>
|
||||
|
@ -1,7 +1,5 @@
|
||||
import { Box, Container, Typography } from "@mui/material";
|
||||
import React, { useState } from "react";
|
||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||
import { IRouter } from "../../ui/Router";
|
||||
import { GameOptionsTab } from "../GameOptionsTab";
|
||||
import { GameOptionsSidebar } from "./GameOptionsSidebar";
|
||||
import { GameplayPage } from "./GameplayPage";
|
||||
@ -11,8 +9,6 @@ import { RemoteAPIPage } from "./RemoteAPIPage";
|
||||
import { SystemPage } from "./SystemPage";
|
||||
|
||||
interface IProps {
|
||||
player: IPlayer;
|
||||
router: IRouter;
|
||||
save: () => void;
|
||||
export: () => void;
|
||||
forceKill: () => void;
|
||||
@ -29,8 +25,6 @@ export function GameOptionsRoot(props: IProps): React.ReactElement {
|
||||
<GameOptionsSidebar
|
||||
tab={currentTab}
|
||||
setTab={setCurrentTab}
|
||||
player={props.player}
|
||||
router={props.router}
|
||||
save={props.save}
|
||||
export={props.export}
|
||||
forceKill={props.forceKill}
|
||||
|
@ -13,7 +13,6 @@ import {
|
||||
import { Box, Button, List, ListItemButton, Paper, Tooltip, Typography } from "@mui/material";
|
||||
import { default as React, useRef, useState } from "react";
|
||||
import { FileDiagnosticModal } from "../../Diagnostic/FileDiagnosticModal";
|
||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||
import { ImportData, saveObject } from "../../SaveObject";
|
||||
import { Settings } from "../../Settings/Settings";
|
||||
import { StyleEditorButton } from "../../Themes/ui/StyleEditorButton";
|
||||
@ -22,15 +21,13 @@ import { ConfirmationModal } from "../../ui/React/ConfirmationModal";
|
||||
import { DeleteGameButton } from "../../ui/React/DeleteGameButton";
|
||||
import { SnackbarEvents, ToastVariant } from "../../ui/React/Snackbar";
|
||||
import { SoftResetButton } from "../../ui/React/SoftResetButton";
|
||||
import { IRouter } from "../../ui/Router";
|
||||
import { Router } from "../../ui/GameRoot";
|
||||
import { convertTimeMsToTimeElapsedString } from "../../utils/StringHelperFunctions";
|
||||
import { GameOptionsTab } from "../GameOptionsTab";
|
||||
|
||||
interface IProps {
|
||||
tab: GameOptionsTab;
|
||||
setTab: (tab: GameOptionsTab) => void;
|
||||
player: IPlayer;
|
||||
router: IRouter;
|
||||
save: () => void;
|
||||
export: () => void;
|
||||
forceKill: () => void;
|
||||
@ -94,7 +91,7 @@ export const GameOptionsSidebar = (props: IProps): React.ReactElement => {
|
||||
|
||||
function compareSaveGame(): void {
|
||||
if (!importData) return;
|
||||
props.router.toImportSave(importData.base64);
|
||||
Router.toImportSave(importData.base64);
|
||||
setImportSaveOpen(false);
|
||||
setImportData(null);
|
||||
}
|
||||
@ -219,12 +216,12 @@ export const GameOptionsSidebar = (props: IProps): React.ReactElement => {
|
||||
</Button>
|
||||
</Tooltip>
|
||||
<Tooltip title="Head to the theme browser to see a collection of prebuilt themes.">
|
||||
<Button startIcon={<Palette />} onClick={() => props.router.toThemeBrowser()} sx={{ gridArea: "browse" }}>
|
||||
<Button startIcon={<Palette />} onClick={() => Router.toThemeBrowser()} sx={{ gridArea: "browse" }}>
|
||||
Theme Browser
|
||||
</Button>
|
||||
</Tooltip>
|
||||
<Box sx={{ gridArea: "theme", "& .MuiButton-root": { height: "100%", width: "100%" } }}>
|
||||
<ThemeEditorButton router={props.router} />
|
||||
<ThemeEditorButton />
|
||||
</Box>
|
||||
<Box sx={{ gridArea: "style", "& .MuiButton-root": { height: "100%", width: "100%" } }}>
|
||||
<StyleEditorButton />
|
||||
|
@ -1,21 +1,21 @@
|
||||
import { BitNodeMultipliers } from "./BitNode/BitNodeMultipliers";
|
||||
import { IPlayer } from "./PersonObjects/IPlayer";
|
||||
import { IPerson } from "./PersonObjects/IPerson";
|
||||
import { calculateIntelligenceBonus } from "./PersonObjects/formulas/intelligence";
|
||||
import { Server } from "./Server/Server";
|
||||
|
||||
/**
|
||||
* Returns the chance the player has to successfully hack a server
|
||||
* Returns the chance the person has to successfully hack a server
|
||||
*/
|
||||
export function calculateHackingChance(server: Server, player: IPlayer): number {
|
||||
export function calculateHackingChance(server: Server, person: IPerson): number {
|
||||
const hackFactor = 1.75;
|
||||
const difficultyMult = (100 - server.hackDifficulty) / 100;
|
||||
const skillMult = hackFactor * player.skills.hacking;
|
||||
const skillMult = hackFactor * person.skills.hacking;
|
||||
const skillChance = (skillMult - server.requiredHackingSkill) / skillMult;
|
||||
const chance =
|
||||
skillChance *
|
||||
difficultyMult *
|
||||
player.mults.hacking_chance *
|
||||
calculateIntelligenceBonus(player.skills.intelligence, 1);
|
||||
person.mults.hacking_chance *
|
||||
calculateIntelligenceBonus(person.skills.intelligence, 1);
|
||||
if (chance > 1) {
|
||||
return 1;
|
||||
}
|
||||
@ -27,10 +27,10 @@ export function calculateHackingChance(server: Server, player: IPlayer): number
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the amount of hacking experience the player will gain upon
|
||||
* Returns the amount of hacking experience the person will gain upon
|
||||
* successfully hacking a server
|
||||
*/
|
||||
export function calculateHackingExpGain(server: Server, player: IPlayer): number {
|
||||
export function calculateHackingExpGain(server: Server, person: IPerson): number {
|
||||
const baseExpGain = 3;
|
||||
const diffFactor = 0.3;
|
||||
if (server.baseDifficulty == null) {
|
||||
@ -39,21 +39,21 @@ export function calculateHackingExpGain(server: Server, player: IPlayer): number
|
||||
let expGain = baseExpGain;
|
||||
expGain += server.baseDifficulty * diffFactor;
|
||||
|
||||
return expGain * player.mults.hacking_exp * BitNodeMultipliers.HackExpGain;
|
||||
return expGain * person.mults.hacking_exp * BitNodeMultipliers.HackExpGain;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the percentage of money that will be stolen from a server if
|
||||
* it is successfully hacked (returns the decimal form, not the actual percent value)
|
||||
*/
|
||||
export function calculatePercentMoneyHacked(server: Server, player: IPlayer): number {
|
||||
export function calculatePercentMoneyHacked(server: Server, person: IPerson): number {
|
||||
// Adjust if needed for balancing. This is the divisor for the final calculation
|
||||
const balanceFactor = 240;
|
||||
|
||||
const difficultyMult = (100 - server.hackDifficulty) / 100;
|
||||
const skillMult = (player.skills.hacking - (server.requiredHackingSkill - 1)) / player.skills.hacking;
|
||||
const skillMult = (person.skills.hacking - (server.requiredHackingSkill - 1)) / person.skills.hacking;
|
||||
const percentMoneyHacked =
|
||||
(difficultyMult * skillMult * player.mults.hacking_money * BitNodeMultipliers.ScriptHackMoney) / balanceFactor;
|
||||
(difficultyMult * skillMult * person.mults.hacking_money * BitNodeMultipliers.ScriptHackMoney) / balanceFactor;
|
||||
if (percentMoneyHacked < 0) {
|
||||
return 0;
|
||||
}
|
||||
@ -67,7 +67,7 @@ export function calculatePercentMoneyHacked(server: Server, player: IPlayer): nu
|
||||
/**
|
||||
* Returns time it takes to complete a hack on a server, in seconds
|
||||
*/
|
||||
export function calculateHackingTime(server: Server, player: IPlayer): number {
|
||||
export function calculateHackingTime(server: Server, person: IPerson): number {
|
||||
const difficultyMult = server.requiredHackingSkill * server.hackDifficulty;
|
||||
|
||||
const baseDiff = 500;
|
||||
@ -75,12 +75,12 @@ export function calculateHackingTime(server: Server, player: IPlayer): number {
|
||||
const diffFactor = 2.5;
|
||||
let skillFactor = diffFactor * difficultyMult + baseDiff;
|
||||
// tslint:disable-next-line
|
||||
skillFactor /= player.skills.hacking + baseSkill;
|
||||
skillFactor /= person.skills.hacking + baseSkill;
|
||||
|
||||
const hackTimeMultiplier = 5;
|
||||
const hackingTime =
|
||||
(hackTimeMultiplier * skillFactor) /
|
||||
(player.mults.hacking_speed * calculateIntelligenceBonus(player.skills.intelligence, 1));
|
||||
(person.mults.hacking_speed * calculateIntelligenceBonus(person.skills.intelligence, 1));
|
||||
|
||||
return hackingTime;
|
||||
}
|
||||
@ -88,17 +88,17 @@ export function calculateHackingTime(server: Server, player: IPlayer): number {
|
||||
/**
|
||||
* Returns time it takes to complete a grow operation on a server, in seconds
|
||||
*/
|
||||
export function calculateGrowTime(server: Server, player: IPlayer): number {
|
||||
export function calculateGrowTime(server: Server, person: IPerson): number {
|
||||
const growTimeMultiplier = 3.2; // Relative to hacking time. 16/5 = 3.2
|
||||
|
||||
return growTimeMultiplier * calculateHackingTime(server, player);
|
||||
return growTimeMultiplier * calculateHackingTime(server, person);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns time it takes to complete a weaken operation on a server, in seconds
|
||||
*/
|
||||
export function calculateWeakenTime(server: Server, player: IPlayer): number {
|
||||
export function calculateWeakenTime(server: Server, person: IPerson): number {
|
||||
const weakenTimeMultiplier = 4; // Relative to hacking time
|
||||
|
||||
return weakenTimeMultiplier * calculateHackingTime(server, player);
|
||||
return weakenTimeMultiplier * calculateHackingTime(server, person);
|
||||
}
|
||||
|
@ -6,7 +6,7 @@
|
||||
*/
|
||||
import { IReturnStatus } from "../types";
|
||||
|
||||
import { IPlayer } from "../PersonObjects/IPlayer";
|
||||
import { Player } from "../Player";
|
||||
import { Server } from "../Server/Server";
|
||||
|
||||
function baseCheck(server: Server, fnName: string): IReturnStatus {
|
||||
@ -29,14 +29,14 @@ function baseCheck(server: Server, fnName: string): IReturnStatus {
|
||||
return { res: true };
|
||||
}
|
||||
|
||||
export function netscriptCanHack(server: Server, p: IPlayer): IReturnStatus {
|
||||
export function netscriptCanHack(server: Server): IReturnStatus {
|
||||
const initialCheck = baseCheck(server, "hack");
|
||||
if (!initialCheck.res) {
|
||||
return initialCheck;
|
||||
}
|
||||
|
||||
const s = server;
|
||||
if (s.requiredHackingSkill > p.skills.hacking) {
|
||||
if (s.requiredHackingSkill > Player.skills.hacking) {
|
||||
return {
|
||||
res: false,
|
||||
msg: `Cannot hack ${server.hostname} server because your hacking skill is not high enough`,
|
||||
|
@ -18,17 +18,17 @@ import { HashUpgrades } from "./HashUpgrades";
|
||||
|
||||
import { generateRandomContract } from "../CodingContractGenerator";
|
||||
import { iTutorialSteps, iTutorialNextStep, ITutorial } from "../InteractiveTutorial";
|
||||
import { IPlayer } from "../PersonObjects/IPlayer";
|
||||
import { Player } from "../Player";
|
||||
import { GetServer } from "../Server/AllServers";
|
||||
import { Server } from "../Server/Server";
|
||||
|
||||
// Returns a boolean indicating whether the player has Hacknet Servers
|
||||
// (the upgraded form of Hacknet Nodes)
|
||||
export function hasHacknetServers(player: IPlayer): boolean {
|
||||
return player.bitNodeN === 9 || player.sourceFileLvl(9) > 0;
|
||||
export function hasHacknetServers(): boolean {
|
||||
return Player.bitNodeN === 9 || Player.sourceFileLvl(9) > 0;
|
||||
}
|
||||
|
||||
export function purchaseHacknet(player: IPlayer): number {
|
||||
export function purchaseHacknet(): number {
|
||||
/* INTERACTIVE TUTORIAL */
|
||||
if (ITutorial.isRunning) {
|
||||
if (ITutorial.currStep === iTutorialSteps.HacknetNodesIntroduction) {
|
||||
@ -39,72 +39,68 @@ export function purchaseHacknet(player: IPlayer): number {
|
||||
}
|
||||
/* END INTERACTIVE TUTORIAL */
|
||||
|
||||
const numOwned = player.hacknetNodes.length;
|
||||
if (hasHacknetServers(player)) {
|
||||
const cost = getCostOfNextHacknetServer(player);
|
||||
const numOwned = Player.hacknetNodes.length;
|
||||
if (hasHacknetServers()) {
|
||||
const cost = getCostOfNextHacknetServer();
|
||||
if (isNaN(cost)) {
|
||||
throw new Error(`Calculated cost of purchasing HacknetServer is NaN`);
|
||||
}
|
||||
|
||||
if (!player.canAfford(cost) || numOwned >= HacknetServerConstants.MaxServers) {
|
||||
if (!Player.canAfford(cost) || numOwned >= HacknetServerConstants.MaxServers) {
|
||||
return -1;
|
||||
}
|
||||
player.loseMoney(cost, "hacknet_expenses");
|
||||
player.createHacknetServer();
|
||||
updateHashManagerCapacity(player);
|
||||
Player.loseMoney(cost, "hacknet_expenses");
|
||||
Player.createHacknetServer();
|
||||
updateHashManagerCapacity();
|
||||
|
||||
return numOwned;
|
||||
} else {
|
||||
const cost = getCostOfNextHacknetNode(player);
|
||||
const cost = getCostOfNextHacknetNode();
|
||||
if (isNaN(cost)) {
|
||||
throw new Error(`Calculated cost of purchasing HacknetNode is NaN`);
|
||||
}
|
||||
|
||||
if (!player.canAfford(cost)) {
|
||||
if (!Player.canAfford(cost)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Auto generate a name for the Node
|
||||
const name = "hacknet-node-" + numOwned;
|
||||
const node = new HacknetNode(name, player.mults.hacknet_node_money);
|
||||
const node = new HacknetNode(name, Player.mults.hacknet_node_money);
|
||||
|
||||
player.loseMoney(cost, "hacknet_expenses");
|
||||
player.hacknetNodes.push(node);
|
||||
Player.loseMoney(cost, "hacknet_expenses");
|
||||
Player.hacknetNodes.push(node);
|
||||
|
||||
return numOwned;
|
||||
}
|
||||
}
|
||||
|
||||
export function hasMaxNumberHacknetServers(player: IPlayer): boolean {
|
||||
return hasHacknetServers(player) && player.hacknetNodes.length >= HacknetServerConstants.MaxServers;
|
||||
export function hasMaxNumberHacknetServers(): boolean {
|
||||
return hasHacknetServers() && Player.hacknetNodes.length >= HacknetServerConstants.MaxServers;
|
||||
}
|
||||
|
||||
export function getCostOfNextHacknetNode(player: IPlayer): number {
|
||||
return calculateNodeCost(player.hacknetNodes.length + 1, player.mults.hacknet_node_purchase_cost);
|
||||
export function getCostOfNextHacknetNode(): number {
|
||||
return calculateNodeCost(Player.hacknetNodes.length + 1, Player.mults.hacknet_node_purchase_cost);
|
||||
}
|
||||
|
||||
export function getCostOfNextHacknetServer(player: IPlayer): number {
|
||||
return calculateServerCost(player.hacknetNodes.length + 1, player.mults.hacknet_node_purchase_cost);
|
||||
export function getCostOfNextHacknetServer(): number {
|
||||
return calculateServerCost(Player.hacknetNodes.length + 1, Player.mults.hacknet_node_purchase_cost);
|
||||
}
|
||||
|
||||
// Calculate the maximum number of times the Player can afford to upgrade a Hacknet Node's level
|
||||
export function getMaxNumberLevelUpgrades(
|
||||
player: IPlayer,
|
||||
nodeObj: HacknetNode | HacknetServer,
|
||||
maxLevel: number,
|
||||
): number {
|
||||
export function getMaxNumberLevelUpgrades(nodeObj: HacknetNode | HacknetServer, maxLevel: number): number {
|
||||
if (maxLevel == null) {
|
||||
throw new Error(`getMaxNumberLevelUpgrades() called without maxLevel arg`);
|
||||
}
|
||||
|
||||
if (player.money < nodeObj.calculateLevelUpgradeCost(1, player.mults.hacknet_node_level_cost)) {
|
||||
if (Player.money < nodeObj.calculateLevelUpgradeCost(1, Player.mults.hacknet_node_level_cost)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
let min = 1;
|
||||
let max = maxLevel - 1;
|
||||
const levelsToMax = maxLevel - nodeObj.level;
|
||||
if (player.money > nodeObj.calculateLevelUpgradeCost(levelsToMax, player.mults.hacknet_node_level_cost)) {
|
||||
if (Player.money > nodeObj.calculateLevelUpgradeCost(levelsToMax, Player.mults.hacknet_node_level_cost)) {
|
||||
return levelsToMax;
|
||||
}
|
||||
|
||||
@ -112,13 +108,13 @@ export function getMaxNumberLevelUpgrades(
|
||||
const curr = ((min + max) / 2) | 0;
|
||||
if (
|
||||
curr !== maxLevel &&
|
||||
player.money > nodeObj.calculateLevelUpgradeCost(curr, player.mults.hacknet_node_level_cost) &&
|
||||
player.money < nodeObj.calculateLevelUpgradeCost(curr + 1, player.mults.hacknet_node_level_cost)
|
||||
Player.money > nodeObj.calculateLevelUpgradeCost(curr, Player.mults.hacknet_node_level_cost) &&
|
||||
Player.money < nodeObj.calculateLevelUpgradeCost(curr + 1, Player.mults.hacknet_node_level_cost)
|
||||
) {
|
||||
return Math.min(levelsToMax, curr);
|
||||
} else if (player.money < nodeObj.calculateLevelUpgradeCost(curr, player.mults.hacknet_node_level_cost)) {
|
||||
} else if (Player.money < nodeObj.calculateLevelUpgradeCost(curr, Player.mults.hacknet_node_level_cost)) {
|
||||
max = curr - 1;
|
||||
} else if (player.money > nodeObj.calculateLevelUpgradeCost(curr, player.mults.hacknet_node_level_cost)) {
|
||||
} else if (Player.money > nodeObj.calculateLevelUpgradeCost(curr, Player.mults.hacknet_node_level_cost)) {
|
||||
min = curr + 1;
|
||||
} else {
|
||||
return Math.min(levelsToMax, curr);
|
||||
@ -128,16 +124,12 @@ export function getMaxNumberLevelUpgrades(
|
||||
}
|
||||
|
||||
// Calculate the maximum number of times the Player can afford to upgrade a Hacknet Node's RAM
|
||||
export function getMaxNumberRamUpgrades(
|
||||
player: IPlayer,
|
||||
nodeObj: HacknetNode | HacknetServer,
|
||||
maxLevel: number,
|
||||
): number {
|
||||
export function getMaxNumberRamUpgrades(nodeObj: HacknetNode | HacknetServer, maxLevel: number): number {
|
||||
if (maxLevel == null) {
|
||||
throw new Error(`getMaxNumberRamUpgrades() called without maxLevel arg`);
|
||||
}
|
||||
|
||||
if (player.money < nodeObj.calculateRamUpgradeCost(1, player.mults.hacknet_node_ram_cost)) {
|
||||
if (Player.money < nodeObj.calculateRamUpgradeCost(1, Player.mults.hacknet_node_ram_cost)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -147,13 +139,13 @@ export function getMaxNumberRamUpgrades(
|
||||
} else {
|
||||
levelsToMax = Math.round(Math.log2(maxLevel / nodeObj.ram));
|
||||
}
|
||||
if (player.money > nodeObj.calculateRamUpgradeCost(levelsToMax, player.mults.hacknet_node_ram_cost)) {
|
||||
if (Player.money > nodeObj.calculateRamUpgradeCost(levelsToMax, Player.mults.hacknet_node_ram_cost)) {
|
||||
return levelsToMax;
|
||||
}
|
||||
|
||||
//We'll just loop until we find the max
|
||||
for (let i = levelsToMax - 1; i >= 0; --i) {
|
||||
if (player.money > nodeObj.calculateRamUpgradeCost(i, player.mults.hacknet_node_ram_cost)) {
|
||||
if (Player.money > nodeObj.calculateRamUpgradeCost(i, Player.mults.hacknet_node_ram_cost)) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
@ -162,7 +154,6 @@ export function getMaxNumberRamUpgrades(
|
||||
|
||||
// Calculate the maximum number of times the Player can afford to upgrade a Hacknet Node's cores
|
||||
export function getMaxNumberCoreUpgrades(
|
||||
player: IPlayer,
|
||||
nodeObj: HacknetNode | HacknetServer,
|
||||
maxLevel: number,
|
||||
): number {
|
||||
@ -170,14 +161,14 @@ export function getMaxNumberCoreUpgrades(
|
||||
throw new Error(`getMaxNumberCoreUpgrades() called without maxLevel arg`);
|
||||
}
|
||||
|
||||
if (player.money < nodeObj.calculateCoreUpgradeCost(1, player.mults.hacknet_node_core_cost)) {
|
||||
if (Player.money < nodeObj.calculateCoreUpgradeCost(1, Player.mults.hacknet_node_core_cost)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
let min = 1;
|
||||
let max = maxLevel - 1;
|
||||
const levelsToMax = maxLevel - nodeObj.cores;
|
||||
if (player.money > nodeObj.calculateCoreUpgradeCost(levelsToMax, player.mults.hacknet_node_core_cost)) {
|
||||
if (Player.money > nodeObj.calculateCoreUpgradeCost(levelsToMax, Player.mults.hacknet_node_core_cost)) {
|
||||
return levelsToMax;
|
||||
}
|
||||
|
||||
@ -186,13 +177,13 @@ export function getMaxNumberCoreUpgrades(
|
||||
const curr = ((min + max) / 2) | 0;
|
||||
if (
|
||||
curr != maxLevel &&
|
||||
player.money > nodeObj.calculateCoreUpgradeCost(curr, player.mults.hacknet_node_core_cost) &&
|
||||
player.money < nodeObj.calculateCoreUpgradeCost(curr + 1, player.mults.hacknet_node_core_cost)
|
||||
Player.money > nodeObj.calculateCoreUpgradeCost(curr, Player.mults.hacknet_node_core_cost) &&
|
||||
Player.money < nodeObj.calculateCoreUpgradeCost(curr + 1, Player.mults.hacknet_node_core_cost)
|
||||
) {
|
||||
return Math.min(levelsToMax, curr);
|
||||
} else if (player.money < nodeObj.calculateCoreUpgradeCost(curr, player.mults.hacknet_node_core_cost)) {
|
||||
} else if (Player.money < nodeObj.calculateCoreUpgradeCost(curr, Player.mults.hacknet_node_core_cost)) {
|
||||
max = curr - 1;
|
||||
} else if (player.money > nodeObj.calculateCoreUpgradeCost(curr, player.mults.hacknet_node_core_cost)) {
|
||||
} else if (Player.money > nodeObj.calculateCoreUpgradeCost(curr, Player.mults.hacknet_node_core_cost)) {
|
||||
min = curr + 1;
|
||||
} else {
|
||||
return Math.min(levelsToMax, curr);
|
||||
@ -203,19 +194,19 @@ export function getMaxNumberCoreUpgrades(
|
||||
}
|
||||
|
||||
// Calculate the maximum number of times the Player can afford to upgrade a Hacknet Node's cache
|
||||
export function getMaxNumberCacheUpgrades(player: IPlayer, nodeObj: HacknetServer, maxLevel: number): number {
|
||||
export function getMaxNumberCacheUpgrades(nodeObj: HacknetServer, maxLevel: number): number {
|
||||
if (maxLevel == null) {
|
||||
throw new Error(`getMaxNumberCacheUpgrades() called without maxLevel arg`);
|
||||
}
|
||||
|
||||
if (!player.canAfford(nodeObj.calculateCacheUpgradeCost(1))) {
|
||||
if (!Player.canAfford(nodeObj.calculateCacheUpgradeCost(1))) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
let min = 1;
|
||||
let max = maxLevel - 1;
|
||||
const levelsToMax = maxLevel - nodeObj.cache;
|
||||
if (player.canAfford(nodeObj.calculateCacheUpgradeCost(levelsToMax))) {
|
||||
if (Player.canAfford(nodeObj.calculateCacheUpgradeCost(levelsToMax))) {
|
||||
return levelsToMax;
|
||||
}
|
||||
|
||||
@ -224,13 +215,13 @@ export function getMaxNumberCacheUpgrades(player: IPlayer, nodeObj: HacknetServe
|
||||
const curr = ((min + max) / 2) | 0;
|
||||
if (
|
||||
curr != maxLevel &&
|
||||
player.canAfford(nodeObj.calculateCacheUpgradeCost(curr)) &&
|
||||
!player.canAfford(nodeObj.calculateCacheUpgradeCost(curr + 1))
|
||||
Player.canAfford(nodeObj.calculateCacheUpgradeCost(curr)) &&
|
||||
!Player.canAfford(nodeObj.calculateCacheUpgradeCost(curr + 1))
|
||||
) {
|
||||
return Math.min(levelsToMax, curr);
|
||||
} else if (!player.canAfford(nodeObj.calculateCacheUpgradeCost(curr))) {
|
||||
} else if (!Player.canAfford(nodeObj.calculateCacheUpgradeCost(curr))) {
|
||||
max = curr - 1;
|
||||
} else if (player.canAfford(nodeObj.calculateCacheUpgradeCost(curr))) {
|
||||
} else if (Player.canAfford(nodeObj.calculateCacheUpgradeCost(curr))) {
|
||||
min = curr + 1;
|
||||
} else {
|
||||
return Math.min(levelsToMax, curr);
|
||||
@ -240,9 +231,9 @@ export function getMaxNumberCacheUpgrades(player: IPlayer, nodeObj: HacknetServe
|
||||
return 0;
|
||||
}
|
||||
|
||||
export function purchaseLevelUpgrade(player: IPlayer, node: HacknetNode | HacknetServer, levels = 1): boolean {
|
||||
export function purchaseLevelUpgrade(node: HacknetNode | HacknetServer, levels = 1): boolean {
|
||||
const sanitizedLevels = Math.round(levels);
|
||||
const cost = node.calculateLevelUpgradeCost(sanitizedLevels, player.mults.hacknet_node_level_cost);
|
||||
const cost = node.calculateLevelUpgradeCost(sanitizedLevels, Player.mults.hacknet_node_level_cost);
|
||||
if (isNaN(cost) || cost <= 0 || sanitizedLevels < 0) {
|
||||
return false;
|
||||
}
|
||||
@ -258,22 +249,22 @@ export function purchaseLevelUpgrade(player: IPlayer, node: HacknetNode | Hackne
|
||||
// the maximum number of upgrades and use that
|
||||
if (node.level + sanitizedLevels > (isServer ? HacknetServerConstants.MaxLevel : HacknetNodeConstants.MaxLevel)) {
|
||||
const diff = Math.max(0, (isServer ? HacknetServerConstants.MaxLevel : HacknetNodeConstants.MaxLevel) - node.level);
|
||||
return purchaseLevelUpgrade(player, node, diff);
|
||||
return purchaseLevelUpgrade(node, diff);
|
||||
}
|
||||
|
||||
if (!player.canAfford(cost)) {
|
||||
if (!Player.canAfford(cost)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
player.loseMoney(cost, "hacknet_expenses");
|
||||
node.upgradeLevel(sanitizedLevels, player.mults.hacknet_node_money);
|
||||
Player.loseMoney(cost, "hacknet_expenses");
|
||||
node.upgradeLevel(sanitizedLevels, Player.mults.hacknet_node_money);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
export function purchaseRamUpgrade(player: IPlayer, node: HacknetNode | HacknetServer, levels = 1): boolean {
|
||||
export function purchaseRamUpgrade(node: HacknetNode | HacknetServer, levels = 1): boolean {
|
||||
const sanitizedLevels = Math.round(levels);
|
||||
const cost = node.calculateRamUpgradeCost(sanitizedLevels, player.mults.hacknet_node_ram_cost);
|
||||
const cost = node.calculateRamUpgradeCost(sanitizedLevels, Player.mults.hacknet_node_ram_cost);
|
||||
if (isNaN(cost) || cost <= 0 || sanitizedLevels < 0) {
|
||||
return false;
|
||||
}
|
||||
@ -291,28 +282,28 @@ export function purchaseRamUpgrade(player: IPlayer, node: HacknetNode | HacknetS
|
||||
if (node instanceof HacknetServer) {
|
||||
if (node.maxRam * Math.pow(2, sanitizedLevels) > HacknetServerConstants.MaxRam) {
|
||||
const diff = Math.max(0, Math.log2(Math.round(HacknetServerConstants.MaxRam / node.maxRam)));
|
||||
return purchaseRamUpgrade(player, node, diff);
|
||||
return purchaseRamUpgrade(node, diff);
|
||||
}
|
||||
} else if (node instanceof HacknetNode) {
|
||||
if (node.ram * Math.pow(2, sanitizedLevels) > HacknetNodeConstants.MaxRam) {
|
||||
const diff = Math.max(0, Math.log2(Math.round(HacknetNodeConstants.MaxRam / node.ram)));
|
||||
return purchaseRamUpgrade(player, node, diff);
|
||||
return purchaseRamUpgrade(node, diff);
|
||||
}
|
||||
}
|
||||
|
||||
if (!player.canAfford(cost)) {
|
||||
if (!Player.canAfford(cost)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
player.loseMoney(cost, "hacknet_expenses");
|
||||
node.upgradeRam(sanitizedLevels, player.mults.hacknet_node_money);
|
||||
Player.loseMoney(cost, "hacknet_expenses");
|
||||
node.upgradeRam(sanitizedLevels, Player.mults.hacknet_node_money);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
export function purchaseCoreUpgrade(player: IPlayer, node: HacknetNode | HacknetServer, levels = 1): boolean {
|
||||
export function purchaseCoreUpgrade(node: HacknetNode | HacknetServer, levels = 1): boolean {
|
||||
const sanitizedLevels = Math.round(levels);
|
||||
const cost = node.calculateCoreUpgradeCost(sanitizedLevels, player.mults.hacknet_node_core_cost);
|
||||
const cost = node.calculateCoreUpgradeCost(sanitizedLevels, Player.mults.hacknet_node_core_cost);
|
||||
if (isNaN(cost) || cost <= 0 || sanitizedLevels < 0) {
|
||||
return false;
|
||||
}
|
||||
@ -328,20 +319,20 @@ export function purchaseCoreUpgrade(player: IPlayer, node: HacknetNode | Hacknet
|
||||
// the max possible number of upgrades and use that
|
||||
if (node.cores + sanitizedLevels > (isServer ? HacknetServerConstants.MaxCores : HacknetNodeConstants.MaxCores)) {
|
||||
const diff = Math.max(0, (isServer ? HacknetServerConstants.MaxCores : HacknetNodeConstants.MaxCores) - node.cores);
|
||||
return purchaseCoreUpgrade(player, node, diff);
|
||||
return purchaseCoreUpgrade(node, diff);
|
||||
}
|
||||
|
||||
if (!player.canAfford(cost)) {
|
||||
if (!Player.canAfford(cost)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
player.loseMoney(cost, "hacknet_expenses");
|
||||
node.upgradeCore(sanitizedLevels, player.mults.hacknet_node_money);
|
||||
Player.loseMoney(cost, "hacknet_expenses");
|
||||
node.upgradeCore(sanitizedLevels, Player.mults.hacknet_node_money);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
export function purchaseCacheUpgrade(player: IPlayer, node: HacknetServer, levels = 1): boolean {
|
||||
export function purchaseCacheUpgrade(node: HacknetServer, levels = 1): boolean {
|
||||
const sanitizedLevels = Math.round(levels);
|
||||
const cost = node.calculateCacheUpgradeCost(sanitizedLevels);
|
||||
if (isNaN(cost) || cost <= 0 || sanitizedLevels < 0) {
|
||||
@ -356,71 +347,71 @@ export function purchaseCacheUpgrade(player: IPlayer, node: HacknetServer, level
|
||||
// Fail if we're already at max
|
||||
if (node.cache + sanitizedLevels > HacknetServerConstants.MaxCache) {
|
||||
const diff = Math.max(0, HacknetServerConstants.MaxCache - node.cache);
|
||||
return purchaseCacheUpgrade(player, node, diff);
|
||||
return purchaseCacheUpgrade(node, diff);
|
||||
}
|
||||
|
||||
if (!player.canAfford(cost)) {
|
||||
if (!Player.canAfford(cost)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
player.loseMoney(cost, "hacknet_expenses");
|
||||
Player.loseMoney(cost, "hacknet_expenses");
|
||||
node.upgradeCache(sanitizedLevels);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
export function processHacknetEarnings(player: IPlayer, numCycles: number): number {
|
||||
export function processHacknetEarnings(numCycles: number): number {
|
||||
// Determine if player has Hacknet Nodes or Hacknet Servers, then
|
||||
// call the appropriate function
|
||||
if (player.hacknetNodes.length === 0) {
|
||||
if (Player.hacknetNodes.length === 0) {
|
||||
return 0;
|
||||
}
|
||||
if (hasHacknetServers(player)) {
|
||||
return processAllHacknetServerEarnings(player, numCycles);
|
||||
} else if (player.hacknetNodes[0] instanceof HacknetNode) {
|
||||
return processAllHacknetNodeEarnings(player, numCycles);
|
||||
if (hasHacknetServers()) {
|
||||
return processAllHacknetServerEarnings(numCycles);
|
||||
} else if (Player.hacknetNodes[0] instanceof HacknetNode) {
|
||||
return processAllHacknetNodeEarnings(numCycles);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
function processAllHacknetNodeEarnings(player: IPlayer, numCycles: number): number {
|
||||
function processAllHacknetNodeEarnings(numCycles: number): number {
|
||||
let total = 0;
|
||||
for (let i = 0; i < player.hacknetNodes.length; ++i) {
|
||||
const node = player.hacknetNodes[i];
|
||||
for (let i = 0; i < Player.hacknetNodes.length; ++i) {
|
||||
const node = Player.hacknetNodes[i];
|
||||
if (typeof node === "string") throw new Error("player node should not be ip string");
|
||||
total += processSingleHacknetNodeEarnings(player, numCycles, node);
|
||||
total += processSingleHacknetNodeEarnings(numCycles, node);
|
||||
}
|
||||
|
||||
return total;
|
||||
}
|
||||
|
||||
function processSingleHacknetNodeEarnings(player: IPlayer, numCycles: number, nodeObj: HacknetNode): number {
|
||||
function processSingleHacknetNodeEarnings(numCycles: number, nodeObj: HacknetNode): number {
|
||||
const totalEarnings = nodeObj.process(numCycles);
|
||||
player.gainMoney(totalEarnings, "hacknet");
|
||||
Player.gainMoney(totalEarnings, "hacknet");
|
||||
|
||||
return totalEarnings;
|
||||
}
|
||||
|
||||
function processAllHacknetServerEarnings(player: IPlayer, numCycles: number): number {
|
||||
if (!(player.hashManager instanceof HashManager)) {
|
||||
function processAllHacknetServerEarnings(numCycles: number): number {
|
||||
if (!(Player.hashManager instanceof HashManager)) {
|
||||
throw new Error(`Player does not have a HashManager (should be in 'hashManager' prop)`);
|
||||
}
|
||||
|
||||
let hashes = 0;
|
||||
for (let i = 0; i < player.hacknetNodes.length; ++i) {
|
||||
for (let i = 0; i < Player.hacknetNodes.length; ++i) {
|
||||
// hacknetNodes array only contains the IP addresses of the servers.
|
||||
// Also, update the hash rate before processing
|
||||
const ip = player.hacknetNodes[i];
|
||||
const ip = Player.hacknetNodes[i];
|
||||
if (ip instanceof HacknetNode) throw new Error(`player nodes should not be HacketNode`);
|
||||
const hserver = GetServer(ip);
|
||||
if (!(hserver instanceof HacknetServer)) throw new Error(`player nodes shoud not be Server`);
|
||||
hserver.updateHashRate(player.mults.hacknet_node_money);
|
||||
hserver.updateHashRate(Player.mults.hacknet_node_money);
|
||||
const h = hserver.process(numCycles);
|
||||
hashes += h;
|
||||
}
|
||||
|
||||
const wastedHashes = player.hashManager.storeHashes(hashes);
|
||||
const wastedHashes = Player.hashManager.storeHashes(hashes);
|
||||
if (wastedHashes > 0) {
|
||||
const upgrade = HashUpgrades["Sell for Money"];
|
||||
if (upgrade === null) throw new Error("Could not get the hash upgrade");
|
||||
@ -428,65 +419,65 @@ function processAllHacknetServerEarnings(player: IPlayer, numCycles: number): nu
|
||||
|
||||
const multiplier = wastedHashes / upgrade.cost;
|
||||
if (multiplier > 0) {
|
||||
player.gainMoney(upgrade.value * multiplier, "hacknet");
|
||||
Player.gainMoney(upgrade.value * multiplier, "hacknet");
|
||||
}
|
||||
}
|
||||
|
||||
return hashes;
|
||||
}
|
||||
|
||||
export function updateHashManagerCapacity(player: IPlayer): void {
|
||||
if (!(player.hashManager instanceof HashManager)) {
|
||||
export function updateHashManagerCapacity(): void {
|
||||
if (!(Player.hashManager instanceof HashManager)) {
|
||||
console.error(`Player does not have a HashManager`);
|
||||
return;
|
||||
}
|
||||
|
||||
const nodes = player.hacknetNodes;
|
||||
const nodes = Player.hacknetNodes;
|
||||
if (nodes.length === 0) {
|
||||
player.hashManager.updateCapacity(0);
|
||||
Player.hashManager.updateCapacity(0);
|
||||
return;
|
||||
}
|
||||
|
||||
let total = 0;
|
||||
for (let i = 0; i < nodes.length; ++i) {
|
||||
if (typeof nodes[i] !== "string") {
|
||||
player.hashManager.updateCapacity(0);
|
||||
Player.hashManager.updateCapacity(0);
|
||||
return;
|
||||
}
|
||||
const ip = nodes[i];
|
||||
if (ip instanceof HacknetNode) throw new Error(`player nodes should be string but isn't`);
|
||||
const h = GetServer(ip);
|
||||
if (!(h instanceof HacknetServer)) {
|
||||
player.hashManager.updateCapacity(0);
|
||||
Player.hashManager.updateCapacity(0);
|
||||
return;
|
||||
}
|
||||
|
||||
total += h.hashCapacity;
|
||||
}
|
||||
|
||||
player.hashManager.updateCapacity(total);
|
||||
Player.hashManager.updateCapacity(total);
|
||||
}
|
||||
|
||||
export function purchaseHashUpgrade(player: IPlayer, upgName: string, upgTarget: string, count = 1): boolean {
|
||||
if (!(player.hashManager instanceof HashManager)) {
|
||||
export function purchaseHashUpgrade(upgName: string, upgTarget: string, count = 1): boolean {
|
||||
if (!(Player.hashManager instanceof HashManager)) {
|
||||
console.error(`Player does not have a HashManager`);
|
||||
return false;
|
||||
}
|
||||
|
||||
// HashManager handles the transaction. This just needs to actually implement
|
||||
// the effects of the upgrade
|
||||
if (player.hashManager.upgrade(upgName, count)) {
|
||||
if (Player.hashManager.upgrade(upgName, count)) {
|
||||
const upg = HashUpgrades[upgName];
|
||||
|
||||
switch (upgName) {
|
||||
case "Sell for Money": {
|
||||
player.gainMoney(upg.value * count, "hacknet");
|
||||
Player.gainMoney(upg.value * count, "hacknet");
|
||||
break;
|
||||
}
|
||||
case "Sell for Corporation Funds": {
|
||||
const corp = player.corporation;
|
||||
const corp = Player.corporation;
|
||||
if (corp === null) {
|
||||
player.hashManager.refundUpgrade(upgName, count);
|
||||
Player.hashManager.refundUpgrade(upgName, count);
|
||||
return false;
|
||||
}
|
||||
corp.funds = corp.funds + upg.value * count;
|
||||
@ -503,7 +494,7 @@ export function purchaseHashUpgrade(player: IPlayer, upgName: string, upgTarget:
|
||||
|
||||
target.changeMinimumSecurity(upg.value ** count, true);
|
||||
} catch (e) {
|
||||
player.hashManager.refundUpgrade(upgName, count);
|
||||
Player.hashManager.refundUpgrade(upgName, count);
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
@ -522,7 +513,7 @@ export function purchaseHashUpgrade(player: IPlayer, upgName: string, upgTarget:
|
||||
target.changeMaximumMoney(upg.value);
|
||||
}
|
||||
} catch (e) {
|
||||
player.hashManager.refundUpgrade(upgName, count);
|
||||
Player.hashManager.refundUpgrade(upgName, count);
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
@ -537,9 +528,9 @@ export function purchaseHashUpgrade(player: IPlayer, upgName: string, upgTarget:
|
||||
}
|
||||
case "Exchange for Corporation Research": {
|
||||
// This will throw if player doesn't have a corporation
|
||||
const corp = player.corporation;
|
||||
const corp = Player.corporation;
|
||||
if (corp === null) {
|
||||
player.hashManager.refundUpgrade(upgName, count);
|
||||
Player.hashManager.refundUpgrade(upgName, count);
|
||||
return false;
|
||||
}
|
||||
for (const division of corp.divisions) {
|
||||
@ -549,19 +540,19 @@ export function purchaseHashUpgrade(player: IPlayer, upgName: string, upgTarget:
|
||||
}
|
||||
case "Exchange for Bladeburner Rank": {
|
||||
// This will throw if player isnt in Bladeburner
|
||||
const bladeburner = player.bladeburner;
|
||||
const bladeburner = Player.bladeburner;
|
||||
if (bladeburner === null) {
|
||||
player.hashManager.refundUpgrade(upgName, count);
|
||||
Player.hashManager.refundUpgrade(upgName, count);
|
||||
return false;
|
||||
}
|
||||
bladeburner.changeRank(player, upg.value * count);
|
||||
bladeburner.changeRank(Player, upg.value * count);
|
||||
break;
|
||||
}
|
||||
case "Exchange for Bladeburner SP": {
|
||||
// This will throw if player isnt in Bladeburner
|
||||
const bladeburner = player.bladeburner;
|
||||
const bladeburner = Player.bladeburner;
|
||||
if (bladeburner === null) {
|
||||
player.hashManager.refundUpgrade(upgName, count);
|
||||
Player.hashManager.refundUpgrade(upgName, count);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -14,7 +14,7 @@ import {
|
||||
purchaseCoreUpgrade,
|
||||
} from "../HacknetHelpers";
|
||||
|
||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||
import { Player } from "../../Player";
|
||||
import { HacknetNode } from "../HacknetNode";
|
||||
|
||||
import { Money } from "../../ui/React/Money";
|
||||
@ -36,7 +36,6 @@ interface IProps {
|
||||
node: HacknetNode;
|
||||
purchaseMultiplier: number | "MAX";
|
||||
rerender: () => void;
|
||||
player: IPlayer;
|
||||
}
|
||||
|
||||
export function HacknetNodeElem(props: IProps): React.ReactElement {
|
||||
@ -51,16 +50,16 @@ export function HacknetNodeElem(props: IProps): React.ReactElement {
|
||||
} else {
|
||||
let multiplier = 0;
|
||||
if (purchaseMult === "MAX") {
|
||||
multiplier = getMaxNumberLevelUpgrades(props.player, node, HacknetNodeConstants.MaxLevel);
|
||||
multiplier = getMaxNumberLevelUpgrades(node, HacknetNodeConstants.MaxLevel);
|
||||
} else {
|
||||
const levelsToMax = HacknetNodeConstants.MaxLevel - node.level;
|
||||
multiplier = Math.min(levelsToMax, purchaseMult);
|
||||
}
|
||||
|
||||
const increase =
|
||||
calculateMoneyGainRate(node.level + multiplier, node.ram, node.cores, props.player.mults.hacknet_node_money) -
|
||||
calculateMoneyGainRate(node.level + multiplier, node.ram, node.cores, Player.mults.hacknet_node_money) -
|
||||
node.moneyGainRatePerSecond;
|
||||
const upgradeLevelCost = node.calculateLevelUpgradeCost(multiplier, props.player.mults.hacknet_node_level_cost);
|
||||
const upgradeLevelCost = node.calculateLevelUpgradeCost(multiplier, Player.mults.hacknet_node_level_cost);
|
||||
upgradeLevelButton = (
|
||||
<Tooltip
|
||||
title={
|
||||
@ -71,7 +70,7 @@ export function HacknetNodeElem(props: IProps): React.ReactElement {
|
||||
>
|
||||
<Button onClick={upgradeLevelOnClick}>
|
||||
+{multiplier} -
|
||||
<Money money={upgradeLevelCost} player={props.player} />
|
||||
<Money money={upgradeLevelCost} forPurchase={true} />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
);
|
||||
@ -79,9 +78,9 @@ export function HacknetNodeElem(props: IProps): React.ReactElement {
|
||||
function upgradeLevelOnClick(): void {
|
||||
const numUpgrades =
|
||||
purchaseMult === "MAX"
|
||||
? getMaxNumberLevelUpgrades(props.player, node, HacknetNodeConstants.MaxLevel)
|
||||
? getMaxNumberLevelUpgrades(node, HacknetNodeConstants.MaxLevel)
|
||||
: purchaseMult;
|
||||
purchaseLevelUpgrade(props.player, node, numUpgrades);
|
||||
purchaseLevelUpgrade(node, numUpgrades);
|
||||
rerender();
|
||||
}
|
||||
|
||||
@ -91,7 +90,7 @@ export function HacknetNodeElem(props: IProps): React.ReactElement {
|
||||
} else {
|
||||
let multiplier = 0;
|
||||
if (purchaseMult === "MAX") {
|
||||
multiplier = getMaxNumberRamUpgrades(props.player, node, HacknetNodeConstants.MaxRam);
|
||||
multiplier = getMaxNumberRamUpgrades(node, HacknetNodeConstants.MaxRam);
|
||||
} else {
|
||||
const levelsToMax = Math.round(Math.log2(HacknetNodeConstants.MaxRam / node.ram));
|
||||
multiplier = Math.min(levelsToMax, purchaseMult);
|
||||
@ -102,9 +101,9 @@ export function HacknetNodeElem(props: IProps): React.ReactElement {
|
||||
node.level,
|
||||
node.ram * Math.pow(2, multiplier),
|
||||
node.cores,
|
||||
props.player.mults.hacknet_node_money,
|
||||
Player.mults.hacknet_node_money,
|
||||
) - node.moneyGainRatePerSecond;
|
||||
const upgradeRamCost = node.calculateRamUpgradeCost(multiplier, props.player.mults.hacknet_node_ram_cost);
|
||||
const upgradeRamCost = node.calculateRamUpgradeCost(multiplier, Player.mults.hacknet_node_ram_cost);
|
||||
upgradeRAMButton = (
|
||||
<Tooltip
|
||||
title={
|
||||
@ -115,24 +114,24 @@ export function HacknetNodeElem(props: IProps): React.ReactElement {
|
||||
>
|
||||
<Button onClick={upgradeRamOnClick}>
|
||||
+{multiplier} -
|
||||
<Money money={upgradeRamCost} player={props.player} />
|
||||
<Money money={upgradeRamCost} forPurchase={true} />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
);
|
||||
}
|
||||
function upgradeRamOnClick(): void {
|
||||
const numUpgrades =
|
||||
purchaseMult === "MAX" ? getMaxNumberRamUpgrades(props.player, node, HacknetNodeConstants.MaxRam) : purchaseMult;
|
||||
purchaseRamUpgrade(props.player, node, numUpgrades);
|
||||
purchaseMult === "MAX" ? getMaxNumberRamUpgrades(node, HacknetNodeConstants.MaxRam) : purchaseMult;
|
||||
purchaseRamUpgrade(node, numUpgrades);
|
||||
rerender();
|
||||
}
|
||||
|
||||
function upgradeCoresOnClick(): void {
|
||||
const numUpgrades =
|
||||
purchaseMult === "MAX"
|
||||
? getMaxNumberCoreUpgrades(props.player, node, HacknetNodeConstants.MaxCores)
|
||||
? getMaxNumberCoreUpgrades(node, HacknetNodeConstants.MaxCores)
|
||||
: purchaseMult;
|
||||
purchaseCoreUpgrade(props.player, node, numUpgrades);
|
||||
purchaseCoreUpgrade(node, numUpgrades);
|
||||
rerender();
|
||||
}
|
||||
let upgradeCoresButton;
|
||||
@ -141,16 +140,16 @@ export function HacknetNodeElem(props: IProps): React.ReactElement {
|
||||
} else {
|
||||
let multiplier = 0;
|
||||
if (purchaseMult === "MAX") {
|
||||
multiplier = getMaxNumberCoreUpgrades(props.player, node, HacknetNodeConstants.MaxCores);
|
||||
multiplier = getMaxNumberCoreUpgrades(node, HacknetNodeConstants.MaxCores);
|
||||
} else {
|
||||
const levelsToMax = HacknetNodeConstants.MaxCores - node.cores;
|
||||
multiplier = Math.min(levelsToMax, purchaseMult);
|
||||
}
|
||||
|
||||
const increase =
|
||||
calculateMoneyGainRate(node.level, node.ram, node.cores + multiplier, props.player.mults.hacknet_node_money) -
|
||||
calculateMoneyGainRate(node.level, node.ram, node.cores + multiplier, Player.mults.hacknet_node_money) -
|
||||
node.moneyGainRatePerSecond;
|
||||
const upgradeCoreCost = node.calculateCoreUpgradeCost(multiplier, props.player.mults.hacknet_node_core_cost);
|
||||
const upgradeCoreCost = node.calculateCoreUpgradeCost(multiplier, Player.mults.hacknet_node_core_cost);
|
||||
upgradeCoresButton = (
|
||||
<Tooltip
|
||||
title={
|
||||
@ -161,7 +160,7 @@ export function HacknetNodeElem(props: IProps): React.ReactElement {
|
||||
>
|
||||
<Button onClick={upgradeCoresOnClick}>
|
||||
+{multiplier} -
|
||||
<Money money={upgradeCoreCost} player={props.player} />
|
||||
<Money money={upgradeCoreCost} forPurchase={true} />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
);
|
||||
|
@ -21,7 +21,7 @@ import {
|
||||
purchaseHacknet,
|
||||
} from "../HacknetHelpers";
|
||||
|
||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||
import { Player } from "../../Player";
|
||||
import { GetServer } from "../../Server/AllServers";
|
||||
|
||||
import Typography from "@mui/material/Typography";
|
||||
@ -29,11 +29,7 @@ import Grid from "@mui/material/Grid";
|
||||
import Button from "@mui/material/Button";
|
||||
import { Box } from "@mui/material";
|
||||
|
||||
interface IProps {
|
||||
player: IPlayer;
|
||||
}
|
||||
|
||||
export function HacknetRoot(props: IProps): React.ReactElement {
|
||||
export function HacknetRoot(): React.ReactElement {
|
||||
const [open, setOpen] = useState(false);
|
||||
const setRerender = useState(false)[1];
|
||||
function rerender(): void {
|
||||
@ -47,9 +43,9 @@ export function HacknetRoot(props: IProps): React.ReactElement {
|
||||
}, []);
|
||||
|
||||
let totalProduction = 0;
|
||||
for (let i = 0; i < props.player.hacknetNodes.length; ++i) {
|
||||
const node = props.player.hacknetNodes[i];
|
||||
if (hasHacknetServers(props.player)) {
|
||||
for (let i = 0; i < Player.hacknetNodes.length; ++i) {
|
||||
const node = Player.hacknetNodes[i];
|
||||
if (hasHacknetServers()) {
|
||||
if (node instanceof HacknetNode) throw new Error("node was hacknet node"); // should never happen
|
||||
const hserver = GetServer(node);
|
||||
if (!(hserver instanceof HacknetServer)) throw new Error("node was not hacknet server"); // should never happen
|
||||
@ -65,16 +61,16 @@ export function HacknetRoot(props: IProps): React.ReactElement {
|
||||
}
|
||||
|
||||
function handlePurchaseButtonClick(): void {
|
||||
purchaseHacknet(props.player);
|
||||
purchaseHacknet();
|
||||
rerender();
|
||||
}
|
||||
|
||||
// Cost to purchase a new Hacknet Node
|
||||
let purchaseCost;
|
||||
if (hasHacknetServers(props.player)) {
|
||||
purchaseCost = getCostOfNextHacknetServer(props.player);
|
||||
if (hasHacknetServers()) {
|
||||
purchaseCost = getCostOfNextHacknetServer();
|
||||
} else {
|
||||
purchaseCost = getCostOfNextHacknetNode(props.player);
|
||||
purchaseCost = getCostOfNextHacknetNode();
|
||||
}
|
||||
|
||||
// onClick event handlers for purchase multiplier buttons
|
||||
@ -86,8 +82,8 @@ export function HacknetRoot(props: IProps): React.ReactElement {
|
||||
];
|
||||
|
||||
// HacknetNode components
|
||||
const nodes = props.player.hacknetNodes.map((node: string | HacknetNode) => {
|
||||
if (hasHacknetServers(props.player)) {
|
||||
const nodes = Player.hacknetNodes.map((node: string | HacknetNode) => {
|
||||
if (hasHacknetServers()) {
|
||||
if (node instanceof HacknetNode) throw new Error("node was hacknet node"); // should never happen
|
||||
const hserver = GetServer(node);
|
||||
if (hserver == null) {
|
||||
@ -96,7 +92,6 @@ export function HacknetRoot(props: IProps): React.ReactElement {
|
||||
if (!(hserver instanceof HacknetServer)) throw new Error("node was not hacknet server"); // should never happen
|
||||
return (
|
||||
<HacknetServerElem
|
||||
player={props.player}
|
||||
key={hserver.hostname}
|
||||
node={hserver}
|
||||
purchaseMultiplier={purchaseMultiplier}
|
||||
@ -106,21 +101,15 @@ export function HacknetRoot(props: IProps): React.ReactElement {
|
||||
} else {
|
||||
if (typeof node === "string") throw new Error("node was ip string"); // should never happen
|
||||
return (
|
||||
<HacknetNodeElem
|
||||
player={props.player}
|
||||
key={node.name}
|
||||
node={node}
|
||||
purchaseMultiplier={purchaseMultiplier}
|
||||
rerender={rerender}
|
||||
/>
|
||||
<HacknetNodeElem key={node.name} node={node} purchaseMultiplier={purchaseMultiplier} rerender={rerender} />
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
return (
|
||||
<>
|
||||
<Typography variant="h4">Hacknet {hasHacknetServers(props.player) ? "Servers" : "Nodes"}</Typography>
|
||||
<GeneralInfo hasHacknetServers={hasHacknetServers(props.player)} />
|
||||
<Typography variant="h4">Hacknet {hasHacknetServers() ? "Servers" : "Nodes"}</Typography>
|
||||
<GeneralInfo hasHacknetServers={hasHacknetServers()} />
|
||||
|
||||
<PurchaseButton cost={purchaseCost} multiplier={purchaseMultiplier} onClick={handlePurchaseButtonClick} />
|
||||
|
||||
@ -128,14 +117,14 @@ export function HacknetRoot(props: IProps): React.ReactElement {
|
||||
|
||||
<Grid container spacing={2}>
|
||||
<Grid item xs={6}>
|
||||
<PlayerInfo totalProduction={totalProduction} player={props.player} />
|
||||
<PlayerInfo totalProduction={totalProduction} />
|
||||
</Grid>
|
||||
<Grid item xs={6}>
|
||||
<MultiplierButtons onClicks={purchaseMultiplierOnClicks} purchaseMultiplier={purchaseMultiplier} />
|
||||
</Grid>
|
||||
</Grid>
|
||||
|
||||
{hasHacknetServers(props.player) && <Button onClick={() => setOpen(true)}>Spend Hashes on Upgrades</Button>}
|
||||
{hasHacknetServers() && <Button onClick={() => setOpen(true)}>Spend Hashes on Upgrades</Button>}
|
||||
|
||||
<Box sx={{ display: "grid", width: "fit-content", gridTemplateColumns: "repeat(3, 1fr)" }}>{nodes}</Box>
|
||||
<HashUpgradeModal open={open} onClose={() => setOpen(false)} />
|
||||
|
@ -17,7 +17,7 @@ import {
|
||||
updateHashManagerCapacity,
|
||||
} from "../HacknetHelpers";
|
||||
|
||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||
import { Player } from "../../Player";
|
||||
import { HacknetServer } from "../HacknetServer";
|
||||
|
||||
import { Money } from "../../ui/React/Money";
|
||||
@ -39,7 +39,6 @@ interface IProps {
|
||||
node: HacknetServer;
|
||||
purchaseMultiplier: number | string;
|
||||
rerender: () => void;
|
||||
player: IPlayer;
|
||||
}
|
||||
|
||||
export function HacknetServerElem(props: IProps): React.ReactElement {
|
||||
@ -54,7 +53,7 @@ export function HacknetServerElem(props: IProps): React.ReactElement {
|
||||
} else {
|
||||
let multiplier = 0;
|
||||
if (purchaseMult === "MAX") {
|
||||
multiplier = getMaxNumberLevelUpgrades(props.player, node, HacknetServerConstants.MaxLevel);
|
||||
multiplier = getMaxNumberLevelUpgrades(node, HacknetServerConstants.MaxLevel);
|
||||
} else {
|
||||
const levelsToMax = HacknetServerConstants.MaxLevel - node.level;
|
||||
multiplier = Math.min(levelsToMax, purchaseMult as number);
|
||||
@ -66,11 +65,11 @@ export function HacknetServerElem(props: IProps): React.ReactElement {
|
||||
0,
|
||||
node.maxRam,
|
||||
node.cores,
|
||||
props.player.mults.hacknet_node_money,
|
||||
) - calculateHashGainRate(node.level, 0, node.maxRam, node.cores, props.player.mults.hacknet_node_money);
|
||||
Player.mults.hacknet_node_money,
|
||||
) - calculateHashGainRate(node.level, 0, node.maxRam, node.cores, Player.mults.hacknet_node_money);
|
||||
const modded_increase = (base_increase * (node.maxRam - node.ramUsed)) / node.maxRam;
|
||||
|
||||
const upgradeLevelCost = node.calculateLevelUpgradeCost(multiplier, props.player.mults.hacknet_node_level_cost);
|
||||
const upgradeLevelCost = node.calculateLevelUpgradeCost(multiplier, Player.mults.hacknet_node_level_cost);
|
||||
upgradeLevelButton = (
|
||||
<Tooltip
|
||||
title={
|
||||
@ -86,7 +85,7 @@ export function HacknetServerElem(props: IProps): React.ReactElement {
|
||||
>
|
||||
<Button onClick={upgradeLevelOnClick}>
|
||||
+{multiplier} -
|
||||
<Money money={upgradeLevelCost} player={props.player} />
|
||||
<Money money={upgradeLevelCost} forPurchase={true} />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
);
|
||||
@ -94,18 +93,18 @@ export function HacknetServerElem(props: IProps): React.ReactElement {
|
||||
function upgradeLevelOnClick(): void {
|
||||
let numUpgrades = purchaseMult;
|
||||
if (purchaseMult === "MAX") {
|
||||
numUpgrades = getMaxNumberLevelUpgrades(props.player, node, HacknetServerConstants.MaxLevel);
|
||||
numUpgrades = getMaxNumberLevelUpgrades(node, HacknetServerConstants.MaxLevel);
|
||||
}
|
||||
purchaseLevelUpgrade(props.player, node, numUpgrades as number);
|
||||
purchaseLevelUpgrade(node, numUpgrades as number);
|
||||
rerender();
|
||||
}
|
||||
|
||||
function upgradeRamOnClick(): void {
|
||||
let numUpgrades = purchaseMult;
|
||||
if (purchaseMult === "MAX") {
|
||||
numUpgrades = getMaxNumberRamUpgrades(props.player, node, HacknetServerConstants.MaxRam);
|
||||
numUpgrades = getMaxNumberRamUpgrades(node, HacknetServerConstants.MaxRam);
|
||||
}
|
||||
purchaseRamUpgrade(props.player, node, numUpgrades as number);
|
||||
purchaseRamUpgrade(node, numUpgrades as number);
|
||||
rerender();
|
||||
}
|
||||
// Upgrade RAM Button
|
||||
@ -115,7 +114,7 @@ export function HacknetServerElem(props: IProps): React.ReactElement {
|
||||
} else {
|
||||
let multiplier = 0;
|
||||
if (purchaseMult === "MAX") {
|
||||
multiplier = getMaxNumberRamUpgrades(props.player, node, HacknetServerConstants.MaxRam);
|
||||
multiplier = getMaxNumberRamUpgrades(node, HacknetServerConstants.MaxRam);
|
||||
} else {
|
||||
const levelsToMax = Math.round(Math.log2(HacknetServerConstants.MaxRam / node.maxRam));
|
||||
multiplier = Math.min(levelsToMax, purchaseMult as number);
|
||||
@ -127,8 +126,8 @@ export function HacknetServerElem(props: IProps): React.ReactElement {
|
||||
0,
|
||||
node.maxRam * Math.pow(2, multiplier),
|
||||
node.cores,
|
||||
props.player.mults.hacknet_node_money,
|
||||
) - calculateHashGainRate(node.level, 0, node.maxRam, node.cores, props.player.mults.hacknet_node_money);
|
||||
Player.mults.hacknet_node_money,
|
||||
) - calculateHashGainRate(node.level, 0, node.maxRam, node.cores, Player.mults.hacknet_node_money);
|
||||
|
||||
const modded_increase =
|
||||
calculateHashGainRate(
|
||||
@ -136,11 +135,11 @@ export function HacknetServerElem(props: IProps): React.ReactElement {
|
||||
node.ramUsed,
|
||||
node.maxRam * Math.pow(2, multiplier),
|
||||
node.cores,
|
||||
props.player.mults.hacknet_node_money,
|
||||
Player.mults.hacknet_node_money,
|
||||
) -
|
||||
calculateHashGainRate(node.level, node.ramUsed, node.maxRam, node.cores, props.player.mults.hacknet_node_money);
|
||||
calculateHashGainRate(node.level, node.ramUsed, node.maxRam, node.cores, Player.mults.hacknet_node_money);
|
||||
|
||||
const upgradeRamCost = node.calculateRamUpgradeCost(multiplier, props.player.mults.hacknet_node_ram_cost);
|
||||
const upgradeRamCost = node.calculateRamUpgradeCost(multiplier, Player.mults.hacknet_node_ram_cost);
|
||||
upgradeRamButton = (
|
||||
<Tooltip
|
||||
title={
|
||||
@ -156,7 +155,7 @@ export function HacknetServerElem(props: IProps): React.ReactElement {
|
||||
>
|
||||
<Button onClick={upgradeRamOnClick}>
|
||||
+{multiplier} -
|
||||
<Money money={upgradeRamCost} player={props.player} />
|
||||
<Money money={upgradeRamCost} forPurchase={true} />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
);
|
||||
@ -165,9 +164,9 @@ export function HacknetServerElem(props: IProps): React.ReactElement {
|
||||
function upgradeCoresOnClick(): void {
|
||||
let numUpgrades = purchaseMult;
|
||||
if (purchaseMult === "MAX") {
|
||||
numUpgrades = getMaxNumberCoreUpgrades(props.player, node, HacknetServerConstants.MaxCores);
|
||||
numUpgrades = getMaxNumberCoreUpgrades(node, HacknetServerConstants.MaxCores);
|
||||
}
|
||||
purchaseCoreUpgrade(props.player, node, numUpgrades as number);
|
||||
purchaseCoreUpgrade(node, numUpgrades as number);
|
||||
rerender();
|
||||
}
|
||||
// Upgrade Cores Button
|
||||
@ -177,7 +176,7 @@ export function HacknetServerElem(props: IProps): React.ReactElement {
|
||||
} else {
|
||||
let multiplier = 0;
|
||||
if (purchaseMult === "MAX") {
|
||||
multiplier = getMaxNumberCoreUpgrades(props.player, node, HacknetServerConstants.MaxCores);
|
||||
multiplier = getMaxNumberCoreUpgrades(node, HacknetServerConstants.MaxCores);
|
||||
} else {
|
||||
const levelsToMax = HacknetServerConstants.MaxCores - node.cores;
|
||||
multiplier = Math.min(levelsToMax, purchaseMult as number);
|
||||
@ -189,11 +188,11 @@ export function HacknetServerElem(props: IProps): React.ReactElement {
|
||||
0,
|
||||
node.maxRam,
|
||||
node.cores + multiplier,
|
||||
props.player.mults.hacknet_node_money,
|
||||
) - calculateHashGainRate(node.level, 0, node.maxRam, node.cores, props.player.mults.hacknet_node_money);
|
||||
Player.mults.hacknet_node_money,
|
||||
) - calculateHashGainRate(node.level, 0, node.maxRam, node.cores, Player.mults.hacknet_node_money);
|
||||
const modded_increase = (base_increase * (node.maxRam - node.ramUsed)) / node.maxRam;
|
||||
|
||||
const upgradeCoreCost = node.calculateCoreUpgradeCost(multiplier, props.player.mults.hacknet_node_core_cost);
|
||||
const upgradeCoreCost = node.calculateCoreUpgradeCost(multiplier, Player.mults.hacknet_node_core_cost);
|
||||
upgradeCoresButton = (
|
||||
<Tooltip
|
||||
title={
|
||||
@ -209,7 +208,7 @@ export function HacknetServerElem(props: IProps): React.ReactElement {
|
||||
>
|
||||
<Button onClick={upgradeCoresOnClick}>
|
||||
+{multiplier} -
|
||||
<Money money={upgradeCoreCost} player={props.player} />
|
||||
<Money money={upgradeCoreCost} forPurchase={true} />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
);
|
||||
@ -222,7 +221,7 @@ export function HacknetServerElem(props: IProps): React.ReactElement {
|
||||
} else {
|
||||
let multiplier = 0;
|
||||
if (purchaseMult === "MAX") {
|
||||
multiplier = getMaxNumberCacheUpgrades(props.player, node, HacknetServerConstants.MaxCache);
|
||||
multiplier = getMaxNumberCacheUpgrades(node, HacknetServerConstants.MaxCache);
|
||||
} else {
|
||||
const levelsToMax = HacknetServerConstants.MaxCache - node.cache;
|
||||
multiplier = Math.min(levelsToMax, purchaseMult as number);
|
||||
@ -240,22 +239,22 @@ export function HacknetServerElem(props: IProps): React.ReactElement {
|
||||
>
|
||||
<Button onClick={upgradeCacheOnClick}>
|
||||
+{multiplier} -
|
||||
<Money money={upgradeCacheCost} player={props.player} />
|
||||
<Money money={upgradeCacheCost} forPurchase={true} />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
);
|
||||
if (props.player.money < upgradeCacheCost) {
|
||||
if (Player.money < upgradeCacheCost) {
|
||||
} else {
|
||||
}
|
||||
}
|
||||
function upgradeCacheOnClick(): void {
|
||||
let numUpgrades = purchaseMult;
|
||||
if (purchaseMult === "MAX") {
|
||||
numUpgrades = getMaxNumberCacheUpgrades(props.player, node, HacknetServerConstants.MaxCache);
|
||||
numUpgrades = getMaxNumberCacheUpgrades(node, HacknetServerConstants.MaxCache);
|
||||
}
|
||||
purchaseCacheUpgrade(props.player, node, numUpgrades as number);
|
||||
purchaseCacheUpgrade(node, numUpgrades as number);
|
||||
rerender();
|
||||
updateHashManagerCapacity(props.player);
|
||||
updateHashManagerCapacity();
|
||||
}
|
||||
|
||||
return (
|
||||
|
@ -4,8 +4,6 @@ import { purchaseHashUpgrade } from "../HacknetHelpers";
|
||||
import { HashManager } from "../HashManager";
|
||||
import { HashUpgrade } from "../HashUpgrade";
|
||||
|
||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||
|
||||
import { ServerDropdown, ServerType } from "../../ui/React/ServerDropdown";
|
||||
|
||||
import { dialogBoxCreate } from "../../ui/React/DialogBox";
|
||||
@ -19,7 +17,6 @@ import { SelectChangeEvent } from "@mui/material/Select";
|
||||
import { FactionNames } from "../../Faction/data/FactionNames";
|
||||
|
||||
interface IProps {
|
||||
player: IPlayer;
|
||||
hashManager: HashManager;
|
||||
upg: HashUpgrade;
|
||||
rerender: () => void;
|
||||
@ -39,7 +36,7 @@ export function HacknetUpgradeElem(props: IProps): React.ReactElement {
|
||||
function purchase(): void {
|
||||
const canPurchase = props.hashManager.hashes >= props.hashManager.getUpgradeCost(props.upg.name);
|
||||
if (canPurchase) {
|
||||
const res = purchaseHashUpgrade(props.player, props.upg.name, selectedServer);
|
||||
const res = purchaseHashUpgrade(props.upg.name, selectedServer);
|
||||
if (!res) {
|
||||
dialogBoxCreate(
|
||||
"Failed to purchase upgrade. This may be because you do not have enough hashes, " +
|
||||
|
@ -9,7 +9,7 @@ import { HashUpgrades } from "../HashUpgrades";
|
||||
import { Hashes } from "../../ui/React/Hashes";
|
||||
import { HacknetUpgradeElem } from "./HacknetUpgradeElem";
|
||||
import { Modal } from "../../ui/React/Modal";
|
||||
import { use } from "../../ui/Context";
|
||||
import { Player } from "../../Player";
|
||||
import Typography from "@mui/material/Typography";
|
||||
|
||||
interface IProps {
|
||||
@ -18,7 +18,6 @@ interface IProps {
|
||||
}
|
||||
|
||||
export function HashUpgradeModal(props: IProps): React.ReactElement {
|
||||
const player = use.Player();
|
||||
const setRerender = useState(false)[1];
|
||||
function rerender(): void {
|
||||
setRerender((old) => !old);
|
||||
@ -29,7 +28,7 @@ export function HashUpgradeModal(props: IProps): React.ReactElement {
|
||||
return () => clearInterval(id);
|
||||
}, []);
|
||||
|
||||
const hashManager = player.hashManager;
|
||||
const hashManager = Player.hashManager;
|
||||
if (!(hashManager instanceof HashManager)) {
|
||||
throw new Error(`Player does not have a HashManager)`);
|
||||
}
|
||||
@ -39,19 +38,11 @@ export function HashUpgradeModal(props: IProps): React.ReactElement {
|
||||
<>
|
||||
<Typography>Spend your hashes on a variety of different upgrades</Typography>
|
||||
<Typography>
|
||||
Hashes: <Hashes hashes={player.hashManager.hashes} />
|
||||
Hashes: <Hashes hashes={Player.hashManager.hashes} />
|
||||
</Typography>
|
||||
{Object.keys(HashUpgrades).map((upgName) => {
|
||||
const upg = HashUpgrades[upgName];
|
||||
return (
|
||||
<HacknetUpgradeElem
|
||||
player={player}
|
||||
upg={upg}
|
||||
hashManager={hashManager}
|
||||
key={upg.name}
|
||||
rerender={rerender}
|
||||
/>
|
||||
);
|
||||
return <HacknetUpgradeElem upg={upg} hashManager={hashManager} key={upg.name} rerender={rerender} />;
|
||||
})}
|
||||
</>
|
||||
</Modal>
|
||||
|
@ -7,7 +7,7 @@
|
||||
import React from "react";
|
||||
|
||||
import { hasHacknetServers } from "../HacknetHelpers";
|
||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||
import { Player } from "../../Player";
|
||||
import { Money } from "../../ui/React/Money";
|
||||
import { MoneyRate } from "../../ui/React/MoneyRate";
|
||||
import { HashRate } from "../../ui/React/HashRate";
|
||||
@ -16,11 +16,10 @@ import Typography from "@mui/material/Typography";
|
||||
|
||||
interface IProps {
|
||||
totalProduction: number;
|
||||
player: IPlayer;
|
||||
}
|
||||
|
||||
export function PlayerInfo(props: IProps): React.ReactElement {
|
||||
const hasServers = hasHacknetServers(props.player);
|
||||
const hasServers = hasHacknetServers();
|
||||
|
||||
let prod;
|
||||
if (hasServers) {
|
||||
@ -33,14 +32,13 @@ export function PlayerInfo(props: IProps): React.ReactElement {
|
||||
<>
|
||||
<Typography>
|
||||
Money:
|
||||
<Money money={props.player.money} />
|
||||
<Money money={Player.money} />
|
||||
</Typography>
|
||||
|
||||
{hasServers && (
|
||||
<>
|
||||
<Typography>
|
||||
Hashes: <Hashes hashes={props.player.hashManager.hashes} /> /{" "}
|
||||
<Hashes hashes={props.player.hashManager.capacity} />
|
||||
Hashes: <Hashes hashes={Player.hashManager.hashes} /> / <Hashes hashes={Player.hashManager.capacity} />
|
||||
</Typography>
|
||||
</>
|
||||
)}
|
||||
|
@ -18,14 +18,14 @@ interface IProps {
|
||||
export function PurchaseButton(props: IProps): React.ReactElement {
|
||||
const cost = props.cost;
|
||||
let text;
|
||||
if (hasHacknetServers(Player)) {
|
||||
if (hasMaxNumberHacknetServers(Player)) {
|
||||
if (hasHacknetServers()) {
|
||||
if (hasMaxNumberHacknetServers()) {
|
||||
text = <>Hacknet Server limit reached</>;
|
||||
} else {
|
||||
text = (
|
||||
<>
|
||||
Purchase Hacknet Server -
|
||||
<Money money={cost} player={Player} />
|
||||
<Money money={cost} forPurchase={true} />
|
||||
</>
|
||||
);
|
||||
}
|
||||
@ -33,7 +33,7 @@ export function PurchaseButton(props: IProps): React.ReactElement {
|
||||
text = (
|
||||
<>
|
||||
Purchase Hacknet Node -
|
||||
<Money money={cost} player={Player} />
|
||||
<Money money={cost} forPurchase={true} />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
@ -1,18 +1,18 @@
|
||||
import { IPlayer } from "../PersonObjects/IPlayer";
|
||||
import { Player } from "../Player";
|
||||
import { CONSTANTS } from "../Constants";
|
||||
|
||||
export function getHospitalizationCost(p: IPlayer): number {
|
||||
if (p.money < 0) {
|
||||
export function getHospitalizationCost(): number {
|
||||
if (Player.money < 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return Math.min(p.money * 0.1, (p.hp.max - p.hp.current) * CONSTANTS.HospitalCostPerHp);
|
||||
return Math.min(Player.money * 0.1, (Player.hp.max - Player.hp.current) * CONSTANTS.HospitalCostPerHp);
|
||||
}
|
||||
|
||||
export function calculateHospitalizationCost(p: IPlayer, damage: number): number {
|
||||
const oldhp = p.hp.current;
|
||||
p.hp.current -= damage;
|
||||
const cost = getHospitalizationCost(p);
|
||||
p.hp.current = oldhp;
|
||||
export function calculateHospitalizationCost(damage: number): number {
|
||||
const oldhp = Player.hp.current;
|
||||
Player.hp.current -= damage;
|
||||
const cost = getHospitalizationCost();
|
||||
Player.hp.current = oldhp;
|
||||
return cost;
|
||||
}
|
||||
|
@ -1,40 +0,0 @@
|
||||
/**
|
||||
* Location and traveling-related helper functions.
|
||||
* Mostly used for UI
|
||||
*/
|
||||
import { SpecialServers } from "../Server/data/SpecialServers";
|
||||
import { CONSTANTS } from "../Constants";
|
||||
|
||||
import { IPlayer } from "../PersonObjects/IPlayer";
|
||||
import { GetServer } from "../Server/AllServers";
|
||||
|
||||
import { dialogBoxCreate } from "../ui/React/DialogBox";
|
||||
|
||||
/**
|
||||
* Attempt to purchase a TOR router
|
||||
* @param {IPlayer} p - Player object
|
||||
*/
|
||||
export function purchaseTorRouter(p: IPlayer): void {
|
||||
if (p.hasTorRouter()) {
|
||||
dialogBoxCreate(`You already have a TOR Router!`);
|
||||
return;
|
||||
}
|
||||
if (!p.canAfford(CONSTANTS.TorRouterCost)) {
|
||||
dialogBoxCreate("You cannot afford to purchase the TOR router!");
|
||||
return;
|
||||
}
|
||||
p.loseMoney(CONSTANTS.TorRouterCost, "other");
|
||||
|
||||
const darkweb = GetServer(SpecialServers.DarkWeb);
|
||||
if (!darkweb) {
|
||||
throw new Error("Dark web is not a server.");
|
||||
}
|
||||
|
||||
p.getHomeComputer().serversOnNetwork.push(darkweb.hostname);
|
||||
darkweb.serversOnNetwork.push(p.getHomeComputer().hostname);
|
||||
dialogBoxCreate(
|
||||
"You have purchased a TOR router!\n" +
|
||||
"You now have access to the dark web from your home computer.\n" +
|
||||
"Use the scan/scan-analyze commands to search for the dark web connection.",
|
||||
);
|
||||
}
|
@ -9,7 +9,6 @@ import { Blackjack, DECK_COUNT } from "../../Casino/Blackjack";
|
||||
import { CoinFlip } from "../../Casino/CoinFlip";
|
||||
import { Roulette } from "../../Casino/Roulette";
|
||||
import { SlotMachine } from "../../Casino/SlotMachine";
|
||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||
import { Box } from "@mui/material";
|
||||
|
||||
enum GameType {
|
||||
@ -20,11 +19,7 @@ enum GameType {
|
||||
Blackjack = "blackjack",
|
||||
}
|
||||
|
||||
type IProps = {
|
||||
p: IPlayer;
|
||||
};
|
||||
|
||||
export function CasinoLocation(props: IProps): React.ReactElement {
|
||||
export function CasinoLocation(): React.ReactElement {
|
||||
const [game, setGame] = useState(GameType.None);
|
||||
|
||||
function updateGame(game: GameType): void {
|
||||
@ -44,10 +39,10 @@ export function CasinoLocation(props: IProps): React.ReactElement {
|
||||
{game !== GameType.None && (
|
||||
<>
|
||||
<Button onClick={() => updateGame(GameType.None)}>Stop playing</Button>
|
||||
{game === GameType.Coin && <CoinFlip p={props.p} />}
|
||||
{game === GameType.Slots && <SlotMachine p={props.p} />}
|
||||
{game === GameType.Roulette && <Roulette p={props.p} />}
|
||||
{game === GameType.Blackjack && <Blackjack p={props.p} />}
|
||||
{game === GameType.Coin && <CoinFlip />}
|
||||
{game === GameType.Slots && <SlotMachine />}
|
||||
{game === GameType.Roulette && <Roulette />}
|
||||
{game === GameType.Blackjack && <Blackjack />}
|
||||
</>
|
||||
)}
|
||||
</>
|
||||
|
@ -3,29 +3,28 @@ import Button from "@mui/material/Button";
|
||||
import Tooltip from "@mui/material/Tooltip";
|
||||
import Typography from "@mui/material/Typography";
|
||||
|
||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||
import { Player } from "../../Player";
|
||||
|
||||
import { Money } from "../../ui/React/Money";
|
||||
import { MathJaxWrapper } from "../../MathJaxWrapper";
|
||||
|
||||
type IProps = {
|
||||
p: IPlayer;
|
||||
rerender: () => void;
|
||||
};
|
||||
|
||||
export function CoresButton(props: IProps): React.ReactElement {
|
||||
const homeComputer = props.p.getHomeComputer();
|
||||
const homeComputer = Player.getHomeComputer();
|
||||
const maxCores = homeComputer.cpuCores >= 8;
|
||||
if (maxCores) {
|
||||
return <Button>Upgrade 'home' cores - MAX</Button>;
|
||||
}
|
||||
|
||||
const cost = props.p.getUpgradeHomeCoresCost();
|
||||
const cost = Player.getUpgradeHomeCoresCost();
|
||||
|
||||
function buy(): void {
|
||||
if (maxCores) return;
|
||||
if (!props.p.canAfford(cost)) return;
|
||||
props.p.loseMoney(cost, "servers");
|
||||
if (!Player.canAfford(cost)) return;
|
||||
Player.loseMoney(cost, "servers");
|
||||
homeComputer.cpuCores++;
|
||||
props.rerender();
|
||||
}
|
||||
@ -38,9 +37,9 @@ export function CoresButton(props: IProps): React.ReactElement {
|
||||
<i>"Cores increase the effectiveness of grow() and weaken() on 'home'"</i>
|
||||
</Typography>
|
||||
<br />
|
||||
<Button disabled={!props.p.canAfford(cost)} onClick={buy}>
|
||||
<Button disabled={!Player.canAfford(cost)} onClick={buy}>
|
||||
Upgrade 'home' cores ({homeComputer.cpuCores} -> {homeComputer.cpuCores + 1}) -
|
||||
<Money money={cost} player={props.p} />
|
||||
<Money money={cost} forPurchase={true} />
|
||||
</Button>
|
||||
</span>
|
||||
</Tooltip>
|
||||
|
@ -27,7 +27,7 @@ import { isBackdoorInstalled } from "../../Server/ServerHelpers";
|
||||
import { GetServer } from "../../Server/AllServers";
|
||||
|
||||
import { CorruptableText } from "../../ui/React/CorruptableText";
|
||||
import { use } from "../../ui/Context";
|
||||
import { Router } from "../../ui/GameRoot";
|
||||
import { serverMetadata } from "../../Server/data/servers";
|
||||
import { Tooltip } from "@mui/material";
|
||||
|
||||
@ -36,8 +36,6 @@ type IProps = {
|
||||
};
|
||||
|
||||
export function GenericLocation({ loc }: IProps): React.ReactElement {
|
||||
const router = use.Router();
|
||||
const player = use.Player();
|
||||
/**
|
||||
* Determine what needs to be rendered for this location based on the locations
|
||||
* type. Returns an array of React components that should be rendered
|
||||
@ -50,11 +48,11 @@ export function GenericLocation({ loc }: IProps): React.ReactElement {
|
||||
}
|
||||
|
||||
if (loc.types.includes(LocationType.Gym)) {
|
||||
content.push(<GymLocation key={"gymlocation"} router={router} loc={loc} p={player} />);
|
||||
content.push(<GymLocation key={"gymlocation"} loc={loc} />);
|
||||
}
|
||||
|
||||
if (loc.types.includes(LocationType.Hospital)) {
|
||||
content.push(<HospitalLocation key={"hospitallocation"} p={player} />);
|
||||
content.push(<HospitalLocation key={"hospitallocation"} />);
|
||||
}
|
||||
|
||||
if (loc.types.includes(LocationType.Slums)) {
|
||||
@ -70,7 +68,7 @@ export function GenericLocation({ loc }: IProps): React.ReactElement {
|
||||
}
|
||||
|
||||
if (loc.types.includes(LocationType.TravelAgency)) {
|
||||
content.push(<TravelAgencyRoot key={"travelagencylocation"} p={player} router={router} />);
|
||||
content.push(<TravelAgencyRoot key={"travelagencylocation"} />);
|
||||
}
|
||||
|
||||
if (loc.types.includes(LocationType.University)) {
|
||||
@ -78,7 +76,7 @@ export function GenericLocation({ loc }: IProps): React.ReactElement {
|
||||
}
|
||||
|
||||
if (loc.types.includes(LocationType.Casino)) {
|
||||
content.push(<CasinoLocation key={"casinoLocation"} p={player} />);
|
||||
content.push(<CasinoLocation key={"casinoLocation"} />);
|
||||
}
|
||||
|
||||
return content;
|
||||
@ -92,7 +90,7 @@ export function GenericLocation({ loc }: IProps): React.ReactElement {
|
||||
|
||||
return (
|
||||
<>
|
||||
<Button onClick={() => router.toCity()}>Return to World</Button>
|
||||
<Button onClick={() => Router.toCity()}>Return to World</Button>
|
||||
<Typography variant="h4" sx={{ mt: 1 }}>
|
||||
{backdoorInstalled && !Settings.DisableTextEffects ? (
|
||||
<Tooltip title={`Backdoor installed on ${loc.name}.`}>
|
||||
|
@ -8,31 +8,29 @@ import Button from "@mui/material/Button";
|
||||
|
||||
import { Location } from "../Location";
|
||||
|
||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||
import { Player } from "../../Player";
|
||||
|
||||
import { Money } from "../../ui/React/Money";
|
||||
import { IRouter } from "../../ui/Router";
|
||||
import { Router } from "../../ui/GameRoot";
|
||||
import { Box } from "@mui/material";
|
||||
import { ClassWork, ClassType, Classes } from "../../Work/ClassWork";
|
||||
import { calculateCost } from "../../Work/formulas/Class";
|
||||
|
||||
type IProps = {
|
||||
loc: Location;
|
||||
p: IPlayer;
|
||||
router: IRouter;
|
||||
};
|
||||
|
||||
export function GymLocation(props: IProps): React.ReactElement {
|
||||
function train(stat: ClassType): void {
|
||||
props.p.startWork(
|
||||
Player.startWork(
|
||||
new ClassWork({
|
||||
classType: stat,
|
||||
location: props.loc.name,
|
||||
singularity: false,
|
||||
}),
|
||||
);
|
||||
props.p.startFocusing();
|
||||
props.router.toWork();
|
||||
Player.startFocusing();
|
||||
Router.toWork();
|
||||
}
|
||||
|
||||
const cost = calculateCost(Classes[ClassType.GymStrength], props.loc);
|
||||
@ -40,16 +38,16 @@ export function GymLocation(props: IProps): React.ReactElement {
|
||||
return (
|
||||
<Box sx={{ display: "grid", width: "fit-content" }}>
|
||||
<Button onClick={() => train(ClassType.GymStrength)}>
|
||||
Train Strength (<Money money={cost} player={props.p} /> / sec)
|
||||
Train Strength (<Money money={cost} forPurchase={true} /> / sec)
|
||||
</Button>
|
||||
<Button onClick={() => train(ClassType.GymDefense)}>
|
||||
Train Defense (<Money money={cost} player={props.p} /> / sec)
|
||||
Train Defense (<Money money={cost} forPurchase={true} /> / sec)
|
||||
</Button>
|
||||
<Button onClick={() => train(ClassType.GymDexterity)}>
|
||||
Train Dexterity (<Money money={cost} player={props.p} /> / sec)
|
||||
Train Dexterity (<Money money={cost} forPurchase={true} /> / sec)
|
||||
</Button>
|
||||
<Button onClick={() => train(ClassType.GymAgility)}>
|
||||
Train Agility (<Money money={cost} player={props.p} /> / sec)
|
||||
Train Agility (<Money money={cost} forPurchase={true} /> / sec)
|
||||
</Button>
|
||||
</Box>
|
||||
);
|
||||
|
@ -6,16 +6,14 @@
|
||||
import * as React from "react";
|
||||
import Button from "@mui/material/Button";
|
||||
|
||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||
import { Player } from "../../Player";
|
||||
import { getHospitalizationCost } from "../../Hospital/Hospital";
|
||||
|
||||
import { Money } from "../../ui/React/Money";
|
||||
|
||||
import { dialogBoxCreate } from "../../ui/React/DialogBox";
|
||||
|
||||
type IProps = {
|
||||
p: IPlayer;
|
||||
};
|
||||
type IProps = {};
|
||||
|
||||
type IState = {
|
||||
currHp: number;
|
||||
@ -34,12 +32,12 @@ export class HospitalLocation extends React.Component<IProps, IState> {
|
||||
this.getHealed = this.getHealed.bind(this);
|
||||
|
||||
this.state = {
|
||||
currHp: this.props.p.hp.current,
|
||||
currHp: Player.hp.current,
|
||||
};
|
||||
}
|
||||
|
||||
getCost(): number {
|
||||
return getHospitalizationCost(this.props.p);
|
||||
return getHospitalizationCost();
|
||||
}
|
||||
|
||||
getHealed(e: React.MouseEvent<HTMLElement>): void {
|
||||
@ -47,20 +45,20 @@ export class HospitalLocation extends React.Component<IProps, IState> {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.props.p.hp.current < 0) {
|
||||
this.props.p.hp.current = 0;
|
||||
if (Player.hp.current < 0) {
|
||||
Player.hp.current = 0;
|
||||
}
|
||||
if (this.props.p.hp.current >= this.props.p.hp.max) {
|
||||
if (Player.hp.current >= Player.hp.max) {
|
||||
return;
|
||||
}
|
||||
|
||||
const cost = this.getCost();
|
||||
this.props.p.loseMoney(cost, "hospitalization");
|
||||
this.props.p.hp.current = this.props.p.hp.max;
|
||||
Player.loseMoney(cost, "hospitalization");
|
||||
Player.hp.current = Player.hp.max;
|
||||
|
||||
// This just forces a re-render to update the cost
|
||||
this.setState({
|
||||
currHp: this.props.p.hp.current,
|
||||
currHp: Player.hp.current,
|
||||
});
|
||||
|
||||
dialogBoxCreate(
|
||||
@ -75,7 +73,7 @@ export class HospitalLocation extends React.Component<IProps, IState> {
|
||||
|
||||
return (
|
||||
<Button onClick={this.getHealed} style={this.btnStyle}>
|
||||
Get treatment for wounds - <Money money={cost} player={this.props.p} />
|
||||
Get treatment for wounds - <Money money={cost} forPurchase={true} />
|
||||
</Button>
|
||||
);
|
||||
}
|
||||
|
@ -25,7 +25,7 @@ export function PurchaseServerModal(props: IProps): React.ReactElement {
|
||||
const [hostname, setHostname] = useState("");
|
||||
|
||||
function tryToPurchaseServer(): void {
|
||||
purchaseServer(hostname, props.ram, props.cost, player);
|
||||
purchaseServer(hostname, props.ram, props.cost);
|
||||
props.onClose();
|
||||
}
|
||||
|
||||
@ -41,7 +41,7 @@ export function PurchaseServerModal(props: IProps): React.ReactElement {
|
||||
<Modal open={props.open} onClose={props.onClose}>
|
||||
<Typography>
|
||||
Would you like to purchase a new server with {numeralWrapper.formatRAM(props.ram)} of RAM for{" "}
|
||||
<Money money={props.cost} player={player} />?
|
||||
<Money money={props.cost} forPurchase={true} />?
|
||||
</Typography>
|
||||
<br />
|
||||
<br />
|
||||
|
@ -4,7 +4,7 @@ import Tooltip from "@mui/material/Tooltip";
|
||||
import Typography from "@mui/material/Typography";
|
||||
|
||||
import { CONSTANTS } from "../../Constants";
|
||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||
import { Player } from "../../Player";
|
||||
import { purchaseRamForHomeComputer } from "../../Server/ServerPurchases";
|
||||
|
||||
import { Money } from "../../ui/React/Money";
|
||||
@ -14,20 +14,19 @@ import { MathJaxWrapper } from "../../MathJaxWrapper";
|
||||
import { BitNodeMultipliers } from "../../BitNode/BitNodeMultipliers";
|
||||
|
||||
type IProps = {
|
||||
p: IPlayer;
|
||||
rerender: () => void;
|
||||
};
|
||||
|
||||
export function RamButton(props: IProps): React.ReactElement {
|
||||
const homeComputer = props.p.getHomeComputer();
|
||||
const homeComputer = Player.getHomeComputer();
|
||||
if (homeComputer.maxRam >= CONSTANTS.HomeComputerMaxRam) {
|
||||
return <Button>Upgrade 'home' RAM - MAX</Button>;
|
||||
}
|
||||
|
||||
const cost = props.p.getUpgradeHomeRamCost();
|
||||
const cost = Player.getUpgradeHomeRamCost();
|
||||
|
||||
function buy(): void {
|
||||
purchaseRamForHomeComputer(props.p);
|
||||
purchaseRamForHomeComputer();
|
||||
props.rerender();
|
||||
}
|
||||
|
||||
@ -45,10 +44,10 @@ export function RamButton(props: IProps): React.ReactElement {
|
||||
<i>"More RAM means more scripts on 'home'"</i>
|
||||
</Typography>
|
||||
<br />
|
||||
<Button disabled={!props.p.canAfford(cost)} onClick={buy}>
|
||||
<Button disabled={!Player.canAfford(cost)} onClick={buy}>
|
||||
Upgrade 'home' RAM ({numeralWrapper.formatRAM(homeComputer.maxRam)} ->
|
||||
{numeralWrapper.formatRAM(homeComputer.maxRam * 2)}) -
|
||||
<Money money={cost} player={props.p} />
|
||||
<Money money={cost} forPurchase={true} />
|
||||
</Button>
|
||||
</span>
|
||||
</Tooltip>
|
||||
|
@ -15,7 +15,7 @@ import { CoresButton } from "./CoresButton";
|
||||
import { getPurchaseServerCost } from "../../Server/ServerPurchases";
|
||||
|
||||
import { Money } from "../../ui/React/Money";
|
||||
import { use } from "../../ui/Context";
|
||||
import { Player } from "../../Player";
|
||||
import { PurchaseServerModal } from "./PurchaseServerModal";
|
||||
import { numeralWrapper } from "../../ui/numeralFormat";
|
||||
import { Box } from "@mui/material";
|
||||
@ -27,13 +27,12 @@ interface IServerProps {
|
||||
|
||||
function ServerButton(props: IServerProps): React.ReactElement {
|
||||
const [open, setOpen] = useState(false);
|
||||
const player = use.Player();
|
||||
const cost = getPurchaseServerCost(props.ram);
|
||||
return (
|
||||
<>
|
||||
<Button onClick={() => setOpen(true)} disabled={!player.canAfford(cost)}>
|
||||
<Button onClick={() => setOpen(true)} disabled={!Player.canAfford(cost)}>
|
||||
Purchase {numeralWrapper.formatRAM(props.ram)} Server -
|
||||
<Money money={cost} player={player} />
|
||||
<Money money={cost} forPurchase={true} />
|
||||
</Button>
|
||||
<PurchaseServerModal
|
||||
open={open}
|
||||
@ -51,7 +50,6 @@ type IProps = {
|
||||
};
|
||||
|
||||
export function TechVendorLocation(props: IProps): React.ReactElement {
|
||||
const player = use.Player();
|
||||
const setRerender = useState(false)[1];
|
||||
function rerender(): void {
|
||||
setRerender((old) => !old);
|
||||
@ -76,11 +74,11 @@ export function TechVendorLocation(props: IProps): React.ReactElement {
|
||||
<i>"You can order bigger servers via scripts. We don't take custom orders in person."</i>
|
||||
</Typography>
|
||||
<br />
|
||||
<TorButton p={player} rerender={rerender} />
|
||||
<TorButton rerender={rerender} />
|
||||
<br />
|
||||
<RamButton p={player} rerender={rerender} />
|
||||
<RamButton rerender={rerender} />
|
||||
<br />
|
||||
<CoresButton p={player} rerender={rerender} />
|
||||
<CoresButton rerender={rerender} />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
@ -1,32 +1,62 @@
|
||||
import React from "react";
|
||||
import Button from "@mui/material/Button";
|
||||
|
||||
import { purchaseTorRouter } from "../LocationsHelpers";
|
||||
import { dialogBoxCreate } from "../../ui/React/DialogBox";
|
||||
import { GetServer } from "../../Server/AllServers";
|
||||
import { SpecialServers } from "../../Server/data/SpecialServers";
|
||||
|
||||
|
||||
import { CONSTANTS } from "../../Constants";
|
||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||
import { Player } from "../../Player";
|
||||
|
||||
import { Money } from "../../ui/React/Money";
|
||||
|
||||
/**
|
||||
* Attempt to purchase a TOR router using the button.
|
||||
*/
|
||||
export function purchaseTorRouter(): void {
|
||||
if (Player.hasTorRouter()) {
|
||||
dialogBoxCreate(`You already have a TOR Router!`);
|
||||
return;
|
||||
}
|
||||
if (!Player.canAfford(CONSTANTS.TorRouterCost)) {
|
||||
dialogBoxCreate("You cannot afford to purchase the TOR router!");
|
||||
return;
|
||||
}
|
||||
Player.loseMoney(CONSTANTS.TorRouterCost, "other");
|
||||
|
||||
const darkweb = GetServer(SpecialServers.DarkWeb);
|
||||
if (!darkweb) {
|
||||
throw new Error("Dark web is not a server.");
|
||||
}
|
||||
|
||||
Player.getHomeComputer().serversOnNetwork.push(darkweb.hostname);
|
||||
darkweb.serversOnNetwork.push(Player.getHomeComputer().hostname);
|
||||
dialogBoxCreate(
|
||||
"You have purchased a TOR router!\n" +
|
||||
"You now have access to the dark web from your home computer.\n" +
|
||||
"Use the scan/scan-analyze commands to search for the dark web connection.",
|
||||
);
|
||||
}
|
||||
|
||||
type IProps = {
|
||||
p: IPlayer;
|
||||
rerender: () => void;
|
||||
};
|
||||
|
||||
export function TorButton(props: IProps): React.ReactElement {
|
||||
function buy(): void {
|
||||
purchaseTorRouter(props.p);
|
||||
purchaseTorRouter();
|
||||
props.rerender();
|
||||
}
|
||||
|
||||
if (props.p.hasTorRouter()) {
|
||||
if (Player.hasTorRouter()) {
|
||||
return <Button>TOR Router - Purchased</Button>;
|
||||
}
|
||||
|
||||
return (
|
||||
<Button disabled={!props.p.canAfford(CONSTANTS.TorRouterCost)} onClick={buy}>
|
||||
<Button disabled={!Player.canAfford(CONSTANTS.TorRouterCost)} onClick={buy}>
|
||||
Purchase TOR router -
|
||||
<Money money={CONSTANTS.TorRouterCost} player={props.p} />
|
||||
<Money money={CONSTANTS.TorRouterCost} forPurchase={true} />
|
||||
</Button>
|
||||
);
|
||||
}
|
||||
|
@ -9,11 +9,10 @@ import { CityName } from "../data/CityNames";
|
||||
import { TravelConfirmationModal } from "./TravelConfirmationModal";
|
||||
|
||||
import { CONSTANTS } from "../../Constants";
|
||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||
import { IRouter } from "../../ui/Router";
|
||||
import { Player } from "../../Player";
|
||||
import { Router } from "../../ui/GameRoot";
|
||||
import { Settings } from "../../Settings/Settings";
|
||||
|
||||
import { use } from "../../ui/Context";
|
||||
import { Money } from "../../ui/React/Money";
|
||||
import { WorldMap } from "../../ui/React/WorldMap";
|
||||
import { dialogBoxCreate } from "../../ui/React/DialogBox";
|
||||
@ -22,26 +21,19 @@ import Typography from "@mui/material/Typography";
|
||||
import Box from "@mui/material/Box";
|
||||
import Button from "@mui/material/Button";
|
||||
|
||||
type IProps = {
|
||||
p: IPlayer;
|
||||
router: IRouter;
|
||||
};
|
||||
|
||||
function travel(p: IPlayer, router: IRouter, to: CityName): void {
|
||||
function travel(to: CityName): void {
|
||||
const cost = CONSTANTS.TravelCost;
|
||||
if (!p.canAfford(cost)) {
|
||||
if (!Player.canAfford(cost)) {
|
||||
return;
|
||||
}
|
||||
|
||||
p.loseMoney(cost, "other");
|
||||
p.travel(to);
|
||||
Player.loseMoney(cost, "other");
|
||||
Player.travel(to);
|
||||
dialogBoxCreate(`You are now in ${to}!`);
|
||||
router.toCity();
|
||||
Router.toCity();
|
||||
}
|
||||
|
||||
export function TravelAgencyRoot(props: IProps): React.ReactElement {
|
||||
const player = use.Player();
|
||||
const router = use.Router();
|
||||
export function TravelAgencyRoot(): React.ReactElement {
|
||||
const setRerender = useState(false)[1];
|
||||
const [open, setOpen] = useState(false);
|
||||
const [destination, setDestination] = useState(CityName.Sector12);
|
||||
@ -56,11 +48,11 @@ export function TravelAgencyRoot(props: IProps): React.ReactElement {
|
||||
|
||||
function startTravel(city: CityName): void {
|
||||
const cost = CONSTANTS.TravelCost;
|
||||
if (!player.canAfford(cost)) {
|
||||
if (!Player.canAfford(cost)) {
|
||||
return;
|
||||
}
|
||||
if (Settings.SuppressTravelConfirmation) {
|
||||
travel(player, router, city);
|
||||
travel(city);
|
||||
return;
|
||||
}
|
||||
setOpen(true);
|
||||
@ -73,12 +65,12 @@ export function TravelAgencyRoot(props: IProps): React.ReactElement {
|
||||
<Box mx={2}>
|
||||
<Typography>
|
||||
From here, you can travel to any other city! A ticket costs{" "}
|
||||
<Money money={CONSTANTS.TravelCost} player={props.p} />.
|
||||
<Money money={CONSTANTS.TravelCost} forPurchase={true} />.
|
||||
</Typography>
|
||||
{Settings.DisableASCIIArt ? (
|
||||
<>
|
||||
{Object.values(CityName)
|
||||
.filter((city: string) => city != props.p.city)
|
||||
.filter((city: string) => city != Player.city)
|
||||
.map((city: string) => {
|
||||
const match = Object.entries(CityName).find((entry) => entry[1] === city);
|
||||
if (match === undefined) throw new Error(`could not find key for city '${city}'`);
|
||||
@ -93,12 +85,12 @@ export function TravelAgencyRoot(props: IProps): React.ReactElement {
|
||||
})}
|
||||
</>
|
||||
) : (
|
||||
<WorldMap currentCity={props.p.city} onTravel={(city: CityName) => startTravel(city)} />
|
||||
<WorldMap currentCity={Player.city} onTravel={(city: CityName) => startTravel(city)} />
|
||||
)}
|
||||
</Box>
|
||||
<TravelConfirmationModal
|
||||
city={destination}
|
||||
travel={() => travel(player, router, destination)}
|
||||
travel={() => travel(destination)}
|
||||
open={open}
|
||||
onClose={() => setOpen(false)}
|
||||
/>
|
||||
|
@ -24,7 +24,7 @@ export function TravelConfirmationModal(props: IProps): React.ReactElement {
|
||||
return (
|
||||
<Modal open={props.open} onClose={props.onClose}>
|
||||
<Typography>
|
||||
Would you like to travel to {props.city}? The trip will cost <Money money={cost} player={player} />.
|
||||
Would you like to travel to {props.city}? The trip will cost <Money money={cost} forPurchase={true} />.
|
||||
</Typography>
|
||||
<br />
|
||||
<br />
|
||||
|
@ -53,31 +53,31 @@ export function UniversityLocation(props: IProps): React.ReactElement {
|
||||
<Tooltip title={earnHackingExpTooltip}>
|
||||
<Button onClick={() => take(ClassType.DataStructures)}>
|
||||
Take Data Structures course (
|
||||
<Money money={dataStructuresCost} player={player} /> / sec)
|
||||
<Money money={dataStructuresCost} forPurchase={true} /> / sec)
|
||||
</Button>
|
||||
</Tooltip>
|
||||
<Tooltip title={earnHackingExpTooltip}>
|
||||
<Button onClick={() => take(ClassType.Networks)}>
|
||||
Take Networks course (
|
||||
<Money money={networksCost} player={player} /> / sec)
|
||||
<Money money={networksCost} forPurchase={true} /> / sec)
|
||||
</Button>
|
||||
</Tooltip>
|
||||
<Tooltip title={earnHackingExpTooltip}>
|
||||
<Button onClick={() => take(ClassType.Algorithms)}>
|
||||
Take Algorithms course (
|
||||
<Money money={algorithmsCost} player={player} /> / sec)
|
||||
<Money money={algorithmsCost} forPurchase={true} /> / sec)
|
||||
</Button>
|
||||
</Tooltip>
|
||||
<Tooltip title={earnCharismaExpTooltip}>
|
||||
<Button onClick={() => take(ClassType.Management)}>
|
||||
Take Management course (
|
||||
<Money money={managementCost} player={player} /> / sec)
|
||||
<Money money={managementCost} forPurchase={true} /> / sec)
|
||||
</Button>
|
||||
</Tooltip>
|
||||
<Tooltip title={earnCharismaExpTooltip}>
|
||||
<Button onClick={() => take(ClassType.Leadership)}>
|
||||
Take Leadership course (
|
||||
<Money money={leadershipCost} player={player} /> / sec)
|
||||
<Money money={leadershipCost} forPurchase={true} /> / sec)
|
||||
</Button>
|
||||
</Tooltip>
|
||||
</Box>
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||
import { Player } from "../../Player";
|
||||
import { Milestones } from "../Milestones";
|
||||
import { Milestone } from "../Milestone";
|
||||
import * as React from "react";
|
||||
@ -6,26 +6,22 @@ import * as React from "react";
|
||||
import Typography from "@mui/material/Typography";
|
||||
import Box from "@mui/material/Box";
|
||||
|
||||
interface IProps {
|
||||
player: IPlayer;
|
||||
}
|
||||
|
||||
function highestMilestone(p: IPlayer, milestones: Milestone[]): number {
|
||||
function highestMilestone(milestones: Milestone[]): number {
|
||||
let n = -1;
|
||||
for (let i = 0; i < milestones.length; i++) {
|
||||
if (milestones[i].fulfilled(p)) n = i;
|
||||
if (milestones[i].fulfilled(Player)) n = i;
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
export function MilestonesRoot(props: IProps): JSX.Element {
|
||||
const n = highestMilestone(props.player, Milestones);
|
||||
export function MilestonesRoot(): JSX.Element {
|
||||
const n = highestMilestone(Milestones);
|
||||
const milestones = Milestones.map((milestone: Milestone, i: number) => {
|
||||
if (i <= n + 1) {
|
||||
return (
|
||||
<Typography key={i}>
|
||||
[{milestone.fulfilled(props.player) ? "x" : " "}] {milestone.title}
|
||||
[{milestone.fulfilled(Player) ? "x" : " "}] {milestone.title}
|
||||
</Typography>
|
||||
);
|
||||
}
|
||||
|
@ -390,7 +390,7 @@ function hack(
|
||||
const hackingTime = calculateHackingTime(server, Player); // This is in seconds
|
||||
|
||||
// No root access or skill level too low
|
||||
const canHack = netscriptCanHack(server, Player);
|
||||
const canHack = netscriptCanHack(server);
|
||||
if (!canHack.res) {
|
||||
throw makeRuntimeErrorMsg(ctx, canHack.msg || "");
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { Player as player } from "../Player";
|
||||
import { Player } from "../Player";
|
||||
import { Bladeburner } from "../Bladeburner/Bladeburner";
|
||||
import { BitNodeMultipliers } from "../BitNode/BitNodeMultipliers";
|
||||
import { Bladeburner as INetscriptBladeburner, BladeburnerCurAction } from "../ScriptEditor/NetscriptDefinitions";
|
||||
@ -8,29 +8,23 @@ import { BlackOperation } from "../Bladeburner/BlackOperation";
|
||||
import { helpers } from "../Netscript/NetscriptHelpers";
|
||||
|
||||
export function NetscriptBladeburner(): InternalAPI<INetscriptBladeburner> {
|
||||
const checkBladeburnerAccess = function (ctx: NetscriptContext, skipjoined = false): void {
|
||||
const bladeburner = player.bladeburner;
|
||||
if (bladeburner === null) throw new Error("Must have joined bladeburner");
|
||||
const apiAccess =
|
||||
player.bitNodeN === 7 ||
|
||||
player.sourceFiles.some((a) => {
|
||||
return a.n === 7;
|
||||
});
|
||||
const checkBladeburnerAccess = function (ctx: NetscriptContext): void {
|
||||
getBladeburner(ctx);
|
||||
return;
|
||||
};
|
||||
const getBladeburner = function (ctx: NetscriptContext): Bladeburner {
|
||||
const apiAccess = Player.bitNodeN === 7 || Player.sourceFiles.some((a) => a.n === 7);
|
||||
if (!apiAccess) {
|
||||
const apiDenied = `You do not currently have access to the Bladeburner API. You must either be in BitNode-7 or have Source-File 7.`;
|
||||
throw helpers.makeRuntimeErrorMsg(ctx, apiDenied);
|
||||
}
|
||||
if (!skipjoined) {
|
||||
const bladeburnerAccess = bladeburner instanceof Bladeburner;
|
||||
if (!bladeburnerAccess) {
|
||||
const bladeburnerDenied = `You must be a member of the Bladeburner division to use this API.`;
|
||||
throw helpers.makeRuntimeErrorMsg(ctx, bladeburnerDenied);
|
||||
}
|
||||
throw helpers.makeRuntimeErrorMsg(ctx, "You have not unlocked the bladeburner API.", "API ACCESS");
|
||||
}
|
||||
const bladeburner = Player.bladeburner;
|
||||
if (!bladeburner)
|
||||
throw helpers.makeRuntimeErrorMsg(ctx, "You must be a member of the Bladeburner division to use this API.");
|
||||
return bladeburner;
|
||||
};
|
||||
|
||||
const checkBladeburnerCity = function (ctx: NetscriptContext, city: string): void {
|
||||
const bladeburner = player.bladeburner;
|
||||
const bladeburner = Player.bladeburner;
|
||||
if (bladeburner === null) throw new Error("Must have joined bladeburner");
|
||||
if (!bladeburner.cities.hasOwnProperty(city)) {
|
||||
throw helpers.makeRuntimeErrorMsg(ctx, `Invalid city: ${city}`);
|
||||
@ -38,7 +32,7 @@ export function NetscriptBladeburner(): InternalAPI<INetscriptBladeburner> {
|
||||
};
|
||||
|
||||
const getBladeburnerActionObject = function (ctx: NetscriptContext, type: string, name: string): IAction {
|
||||
const bladeburner = player.bladeburner;
|
||||
const bladeburner = Player.bladeburner;
|
||||
if (bladeburner === null) throw new Error("Must have joined bladeburner");
|
||||
const actionId = bladeburner.getActionIdFromTypeAndName(type, name);
|
||||
if (!actionId) {
|
||||
@ -54,21 +48,15 @@ export function NetscriptBladeburner(): InternalAPI<INetscriptBladeburner> {
|
||||
|
||||
return {
|
||||
getContractNames: (ctx: NetscriptContext) => (): string[] => {
|
||||
checkBladeburnerAccess(ctx);
|
||||
const bladeburner = player.bladeburner;
|
||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||
const bladeburner = getBladeburner(ctx);
|
||||
return bladeburner.getContractNamesNetscriptFn();
|
||||
},
|
||||
getOperationNames: (ctx: NetscriptContext) => (): string[] => {
|
||||
checkBladeburnerAccess(ctx);
|
||||
const bladeburner = player.bladeburner;
|
||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||
const bladeburner = getBladeburner(ctx);
|
||||
return bladeburner.getOperationNamesNetscriptFn();
|
||||
},
|
||||
getBlackOpNames: (ctx: NetscriptContext) => (): string[] => {
|
||||
checkBladeburnerAccess(ctx);
|
||||
const bladeburner = player.bladeburner;
|
||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||
const bladeburner = getBladeburner(ctx);
|
||||
return bladeburner.getBlackOpNamesNetscriptFn();
|
||||
},
|
||||
getBlackOpRank:
|
||||
@ -81,15 +69,11 @@ export function NetscriptBladeburner(): InternalAPI<INetscriptBladeburner> {
|
||||
return action.reqdRank;
|
||||
},
|
||||
getGeneralActionNames: (ctx: NetscriptContext) => (): string[] => {
|
||||
checkBladeburnerAccess(ctx);
|
||||
const bladeburner = player.bladeburner;
|
||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||
const bladeburner = getBladeburner(ctx);
|
||||
return bladeburner.getGeneralActionNamesNetscriptFn();
|
||||
},
|
||||
getSkillNames: (ctx: NetscriptContext) => (): string[] => {
|
||||
checkBladeburnerAccess(ctx);
|
||||
const bladeburner = player.bladeburner;
|
||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||
const bladeburner = getBladeburner(ctx);
|
||||
return bladeburner.getSkillNamesNetscriptFn();
|
||||
},
|
||||
startAction:
|
||||
@ -97,25 +81,19 @@ export function NetscriptBladeburner(): InternalAPI<INetscriptBladeburner> {
|
||||
(_type: unknown, _name: unknown): boolean => {
|
||||
const type = helpers.string(ctx, "type", _type);
|
||||
const name = helpers.string(ctx, "name", _name);
|
||||
checkBladeburnerAccess(ctx);
|
||||
const bladeburner = player.bladeburner;
|
||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||
const bladeburner = getBladeburner(ctx);
|
||||
try {
|
||||
return bladeburner.startActionNetscriptFn(player, type, name, ctx.workerScript);
|
||||
return bladeburner.startActionNetscriptFn(type, name, ctx.workerScript);
|
||||
} catch (e: unknown) {
|
||||
throw helpers.makeRuntimeErrorMsg(ctx, String(e));
|
||||
}
|
||||
},
|
||||
stopBladeburnerAction: (ctx: NetscriptContext) => (): void => {
|
||||
checkBladeburnerAccess(ctx);
|
||||
const bladeburner = player.bladeburner;
|
||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||
const bladeburner = getBladeburner(ctx);
|
||||
return bladeburner.resetAction();
|
||||
},
|
||||
getCurrentAction: (ctx: NetscriptContext) => (): BladeburnerCurAction => {
|
||||
checkBladeburnerAccess(ctx);
|
||||
const bladeburner = player.bladeburner;
|
||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||
const bladeburner = getBladeburner(ctx);
|
||||
return bladeburner.getTypeAndNameFromActionId(bladeburner.action);
|
||||
},
|
||||
getActionTime:
|
||||
@ -123,11 +101,9 @@ export function NetscriptBladeburner(): InternalAPI<INetscriptBladeburner> {
|
||||
(_type: unknown, _name: unknown): number => {
|
||||
const type = helpers.string(ctx, "type", _type);
|
||||
const name = helpers.string(ctx, "name", _name);
|
||||
checkBladeburnerAccess(ctx);
|
||||
const bladeburner = player.bladeburner;
|
||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||
const bladeburner = getBladeburner(ctx);
|
||||
try {
|
||||
const time = bladeburner.getActionTimeNetscriptFn(player, type, name);
|
||||
const time = bladeburner.getActionTimeNetscriptFn(Player, type, name);
|
||||
if (typeof time === "string") {
|
||||
const errorLogText = `Invalid action: type='${type}' name='${name}'`;
|
||||
helpers.log(ctx, () => errorLogText);
|
||||
@ -140,9 +116,7 @@ export function NetscriptBladeburner(): InternalAPI<INetscriptBladeburner> {
|
||||
}
|
||||
},
|
||||
getActionCurrentTime: (ctx: NetscriptContext) => (): number => {
|
||||
checkBladeburnerAccess(ctx);
|
||||
const bladeburner = player.bladeburner;
|
||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||
const bladeburner = getBladeburner(ctx);
|
||||
try {
|
||||
const timecomputed =
|
||||
Math.min(bladeburner.actionTimeCurrent + bladeburner.actionTimeOverflow, bladeburner.actionTimeToComplete) *
|
||||
@ -157,11 +131,9 @@ export function NetscriptBladeburner(): InternalAPI<INetscriptBladeburner> {
|
||||
(_type: unknown, _name: unknown): [number, number] => {
|
||||
const type = helpers.string(ctx, "type", _type);
|
||||
const name = helpers.string(ctx, "name", _name);
|
||||
checkBladeburnerAccess(ctx);
|
||||
const bladeburner = player.bladeburner;
|
||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||
const bladeburner = getBladeburner(ctx);
|
||||
try {
|
||||
const chance = bladeburner.getActionEstimatedSuccessChanceNetscriptFn(player, type, name);
|
||||
const chance = bladeburner.getActionEstimatedSuccessChanceNetscriptFn(Player, type, name);
|
||||
if (typeof chance === "string") {
|
||||
const errorLogText = `Invalid action: type='${type}' name='${name}'`;
|
||||
helpers.log(ctx, () => errorLogText);
|
||||
@ -195,9 +167,7 @@ export function NetscriptBladeburner(): InternalAPI<INetscriptBladeburner> {
|
||||
(_type: unknown, _name: unknown): number => {
|
||||
const type = helpers.string(ctx, "type", _type);
|
||||
const name = helpers.string(ctx, "name", _name);
|
||||
checkBladeburnerAccess(ctx);
|
||||
const bladeburner = player.bladeburner;
|
||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||
const bladeburner = getBladeburner(ctx);
|
||||
try {
|
||||
return bladeburner.getActionCountRemainingNetscriptFn(type, name, ctx.workerScript);
|
||||
} catch (e: unknown) {
|
||||
@ -255,24 +225,18 @@ export function NetscriptBladeburner(): InternalAPI<INetscriptBladeburner> {
|
||||
action.level = level;
|
||||
},
|
||||
getRank: (ctx: NetscriptContext) => (): number => {
|
||||
checkBladeburnerAccess(ctx);
|
||||
const bladeburner = player.bladeburner;
|
||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||
const bladeburner = getBladeburner(ctx);
|
||||
return bladeburner.rank;
|
||||
},
|
||||
getSkillPoints: (ctx: NetscriptContext) => (): number => {
|
||||
checkBladeburnerAccess(ctx);
|
||||
const bladeburner = player.bladeburner;
|
||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||
const bladeburner = getBladeburner(ctx);
|
||||
return bladeburner.skillPoints;
|
||||
},
|
||||
getSkillLevel:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_skillName: unknown): number => {
|
||||
const skillName = helpers.string(ctx, "skillName", _skillName);
|
||||
checkBladeburnerAccess(ctx);
|
||||
const bladeburner = player.bladeburner;
|
||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||
const bladeburner = getBladeburner(ctx);
|
||||
try {
|
||||
return bladeburner.getSkillLevelNetscriptFn(skillName, ctx.workerScript);
|
||||
} catch (e: unknown) {
|
||||
@ -284,9 +248,7 @@ export function NetscriptBladeburner(): InternalAPI<INetscriptBladeburner> {
|
||||
(_skillName: unknown, _count: unknown = 1): number => {
|
||||
const skillName = helpers.string(ctx, "skillName", _skillName);
|
||||
const count = helpers.number(ctx, "count", _count);
|
||||
checkBladeburnerAccess(ctx);
|
||||
const bladeburner = player.bladeburner;
|
||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||
const bladeburner = getBladeburner(ctx);
|
||||
try {
|
||||
return bladeburner.getSkillUpgradeCostNetscriptFn(skillName, count, ctx.workerScript);
|
||||
} catch (e: unknown) {
|
||||
@ -298,9 +260,7 @@ export function NetscriptBladeburner(): InternalAPI<INetscriptBladeburner> {
|
||||
(_skillName: unknown, _count: unknown = 1): boolean => {
|
||||
const skillName = helpers.string(ctx, "skillName", _skillName);
|
||||
const count = helpers.number(ctx, "count", _count);
|
||||
checkBladeburnerAccess(ctx);
|
||||
const bladeburner = player.bladeburner;
|
||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||
const bladeburner = getBladeburner(ctx);
|
||||
try {
|
||||
return bladeburner.upgradeSkillNetscriptFn(skillName, count, ctx.workerScript);
|
||||
} catch (e: unknown) {
|
||||
@ -312,9 +272,7 @@ export function NetscriptBladeburner(): InternalAPI<INetscriptBladeburner> {
|
||||
(_type: unknown, _name: unknown): number => {
|
||||
const type = helpers.string(ctx, "type", _type);
|
||||
const name = helpers.string(ctx, "name", _name);
|
||||
checkBladeburnerAccess(ctx);
|
||||
const bladeburner = player.bladeburner;
|
||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||
const bladeburner = getBladeburner(ctx);
|
||||
try {
|
||||
return bladeburner.getTeamSizeNetscriptFn(type, name, ctx.workerScript);
|
||||
} catch (e: unknown) {
|
||||
@ -327,9 +285,7 @@ export function NetscriptBladeburner(): InternalAPI<INetscriptBladeburner> {
|
||||
const type = helpers.string(ctx, "type", _type);
|
||||
const name = helpers.string(ctx, "name", _name);
|
||||
const size = helpers.number(ctx, "size", _size);
|
||||
checkBladeburnerAccess(ctx);
|
||||
const bladeburner = player.bladeburner;
|
||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||
const bladeburner = getBladeburner(ctx);
|
||||
try {
|
||||
return bladeburner.setTeamSizeNetscriptFn(type, name, size, ctx.workerScript);
|
||||
} catch (e: unknown) {
|
||||
@ -342,7 +298,7 @@ export function NetscriptBladeburner(): InternalAPI<INetscriptBladeburner> {
|
||||
const cityName = helpers.string(ctx, "cityName", _cityName);
|
||||
checkBladeburnerAccess(ctx);
|
||||
checkBladeburnerCity(ctx, cityName);
|
||||
const bladeburner = player.bladeburner;
|
||||
const bladeburner = Player.bladeburner;
|
||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||
return bladeburner.cities[cityName].popEst;
|
||||
},
|
||||
@ -352,7 +308,7 @@ export function NetscriptBladeburner(): InternalAPI<INetscriptBladeburner> {
|
||||
const cityName = helpers.string(ctx, "cityName", _cityName);
|
||||
checkBladeburnerAccess(ctx);
|
||||
checkBladeburnerCity(ctx, cityName);
|
||||
const bladeburner = player.bladeburner;
|
||||
const bladeburner = Player.bladeburner;
|
||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||
return bladeburner.cities[cityName].comms;
|
||||
},
|
||||
@ -362,14 +318,12 @@ export function NetscriptBladeburner(): InternalAPI<INetscriptBladeburner> {
|
||||
const cityName = helpers.string(ctx, "cityName", _cityName);
|
||||
checkBladeburnerAccess(ctx);
|
||||
checkBladeburnerCity(ctx, cityName);
|
||||
const bladeburner = player.bladeburner;
|
||||
const bladeburner = Player.bladeburner;
|
||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||
return bladeburner.cities[cityName].chaos;
|
||||
},
|
||||
getCity: (ctx: NetscriptContext) => (): string => {
|
||||
checkBladeburnerAccess(ctx);
|
||||
const bladeburner = player.bladeburner;
|
||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||
const bladeburner = getBladeburner(ctx);
|
||||
return bladeburner.city;
|
||||
},
|
||||
switchCity:
|
||||
@ -378,37 +332,33 @@ export function NetscriptBladeburner(): InternalAPI<INetscriptBladeburner> {
|
||||
const cityName = helpers.string(ctx, "cityName", _cityName);
|
||||
checkBladeburnerAccess(ctx);
|
||||
checkBladeburnerCity(ctx, cityName);
|
||||
const bladeburner = player.bladeburner;
|
||||
const bladeburner = Player.bladeburner;
|
||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||
bladeburner.city = cityName;
|
||||
return true;
|
||||
},
|
||||
getStamina: (ctx: NetscriptContext) => (): [number, number] => {
|
||||
checkBladeburnerAccess(ctx);
|
||||
const bladeburner = player.bladeburner;
|
||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||
const bladeburner = getBladeburner(ctx);
|
||||
return [bladeburner.stamina, bladeburner.maxStamina];
|
||||
},
|
||||
joinBladeburnerFaction: (ctx: NetscriptContext) => (): boolean => {
|
||||
checkBladeburnerAccess(ctx, true);
|
||||
const bladeburner = player.bladeburner;
|
||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||
const bladeburner = getBladeburner(ctx);
|
||||
return bladeburner.joinBladeburnerFactionNetscriptFn(ctx.workerScript);
|
||||
},
|
||||
joinBladeburnerDivision: (ctx: NetscriptContext) => (): boolean => {
|
||||
if (player.bitNodeN === 7 || player.sourceFileLvl(7) > 0) {
|
||||
if (Player.bitNodeN === 7 || Player.sourceFileLvl(7) > 0) {
|
||||
if (BitNodeMultipliers.BladeburnerRank === 0) {
|
||||
return false; // Disabled in this bitnode
|
||||
}
|
||||
if (player.bladeburner instanceof Bladeburner) {
|
||||
if (Player.bladeburner instanceof Bladeburner) {
|
||||
return true; // Already member
|
||||
} else if (
|
||||
player.skills.strength >= 100 &&
|
||||
player.skills.defense >= 100 &&
|
||||
player.skills.dexterity >= 100 &&
|
||||
player.skills.agility >= 100
|
||||
Player.skills.strength >= 100 &&
|
||||
Player.skills.defense >= 100 &&
|
||||
Player.skills.dexterity >= 100 &&
|
||||
Player.skills.agility >= 100
|
||||
) {
|
||||
player.bladeburner = new Bladeburner(player);
|
||||
Player.bladeburner = new Bladeburner();
|
||||
helpers.log(ctx, () => "You have been accepted into the Bladeburner division");
|
||||
|
||||
return true;
|
||||
@ -420,9 +370,7 @@ export function NetscriptBladeburner(): InternalAPI<INetscriptBladeburner> {
|
||||
return false;
|
||||
},
|
||||
getBonusTime: (ctx: NetscriptContext) => (): number => {
|
||||
checkBladeburnerAccess(ctx);
|
||||
const bladeburner = player.bladeburner;
|
||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||
const bladeburner = getBladeburner(ctx);
|
||||
return Math.round(bladeburner.storedCycles / 5) * 1000;
|
||||
},
|
||||
};
|
||||
|
@ -1047,14 +1047,14 @@ export function NetscriptCorporation(): InternalAPI<NSCorporation> {
|
||||
(_numShares: unknown): number => {
|
||||
checkAccess(ctx);
|
||||
const numShares = helpers.number(ctx, "numShares", _numShares);
|
||||
return SellShares(getCorporation(), player, numShares);
|
||||
return SellShares(getCorporation(), numShares);
|
||||
},
|
||||
buyBackShares:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_numShares: unknown): boolean => {
|
||||
checkAccess(ctx);
|
||||
const numShares = helpers.number(ctx, "numShares", _numShares);
|
||||
return BuyBackShares(getCorporation(), player, numShares);
|
||||
return BuyBackShares(getCorporation(), numShares);
|
||||
},
|
||||
bribe:
|
||||
(ctx: NetscriptContext) =>
|
||||
|
@ -410,11 +410,11 @@ export function NetscriptFormulas(): InternalAPI<IFormulas> {
|
||||
},
|
||||
classGains:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_player: unknown, _classType: unknown, _locationName: unknown): WorkStats => {
|
||||
const target = helpers.player(ctx, _player);
|
||||
(_person: unknown, _classType: unknown, _locationName: unknown): WorkStats => {
|
||||
const person = helpers.player(ctx, _person);
|
||||
const classType = helpers.string(ctx, "classType", _classType);
|
||||
const locationName = helpers.string(ctx, "locationName", _locationName);
|
||||
return calculateClassEarnings(player, target, classType as ClassType, locationName as LocationName);
|
||||
return calculateClassEarnings(person, classType as ClassType, locationName as LocationName);
|
||||
},
|
||||
factionGains:
|
||||
(ctx: NetscriptContext) =>
|
||||
|
@ -26,7 +26,7 @@ export function NetscriptGrafting(): InternalAPI<IGrafting> {
|
||||
(_augName: unknown): number => {
|
||||
const augName = helpers.string(ctx, "augName", _augName);
|
||||
checkGraftingAPIAccess(ctx);
|
||||
if (!getGraftingAvailableAugs(player).includes(augName) || !StaticAugmentations.hasOwnProperty(augName)) {
|
||||
if (!getGraftingAvailableAugs().includes(augName) || !StaticAugmentations.hasOwnProperty(augName)) {
|
||||
throw helpers.makeRuntimeErrorMsg(ctx, `Invalid aug: ${augName}`);
|
||||
}
|
||||
const graftableAug = new GraftableAugmentation(StaticAugmentations[augName]);
|
||||
@ -38,16 +38,16 @@ export function NetscriptGrafting(): InternalAPI<IGrafting> {
|
||||
(_augName: string): number => {
|
||||
const augName = helpers.string(ctx, "augName", _augName);
|
||||
checkGraftingAPIAccess(ctx);
|
||||
if (!getGraftingAvailableAugs(player).includes(augName) || !StaticAugmentations.hasOwnProperty(augName)) {
|
||||
if (!getGraftingAvailableAugs().includes(augName) || !StaticAugmentations.hasOwnProperty(augName)) {
|
||||
throw helpers.makeRuntimeErrorMsg(ctx, `Invalid aug: ${augName}`);
|
||||
}
|
||||
const graftableAug = new GraftableAugmentation(StaticAugmentations[augName]);
|
||||
return calculateGraftingTimeWithBonus(player, graftableAug);
|
||||
return calculateGraftingTimeWithBonus(graftableAug);
|
||||
},
|
||||
|
||||
getGraftableAugmentations: (ctx: NetscriptContext) => (): string[] => {
|
||||
checkGraftingAPIAccess(ctx);
|
||||
const graftableAugs = getGraftingAvailableAugs(player);
|
||||
const graftableAugs = getGraftingAvailableAugs();
|
||||
return graftableAugs;
|
||||
},
|
||||
|
||||
@ -60,7 +60,7 @@ export function NetscriptGrafting(): InternalAPI<IGrafting> {
|
||||
if (player.city !== CityName.NewTokyo) {
|
||||
throw helpers.makeRuntimeErrorMsg(ctx, "You must be in New Tokyo to begin grafting an Augmentation.");
|
||||
}
|
||||
if (!getGraftingAvailableAugs(player).includes(augName) || !StaticAugmentations.hasOwnProperty(augName)) {
|
||||
if (!getGraftingAvailableAugs().includes(augName) || !StaticAugmentations.hasOwnProperty(augName)) {
|
||||
helpers.log(ctx, () => `Invalid aug: ${augName}`);
|
||||
return false;
|
||||
}
|
||||
@ -82,7 +82,6 @@ export function NetscriptGrafting(): InternalAPI<IGrafting> {
|
||||
new GraftingWork({
|
||||
singularity: true,
|
||||
augmentation: augName,
|
||||
player: player,
|
||||
}),
|
||||
);
|
||||
|
||||
|
@ -29,7 +29,7 @@ export function NetscriptHacknet(): InternalAPI<IHacknet> {
|
||||
throw helpers.makeRuntimeErrorMsg(ctx, "Index specified for Hacknet Node is out-of-bounds: " + i);
|
||||
}
|
||||
|
||||
if (hasHacknetServers(player)) {
|
||||
if (hasHacknetServers()) {
|
||||
const hi = player.hacknetNodes[i];
|
||||
if (typeof hi !== "string") throw new Error("hacknet node was not a string");
|
||||
const hserver = GetServer(hi);
|
||||
@ -54,19 +54,19 @@ export function NetscriptHacknet(): InternalAPI<IHacknet> {
|
||||
return player.hacknetNodes.length;
|
||||
},
|
||||
maxNumNodes: () => (): number => {
|
||||
if (hasHacknetServers(player)) {
|
||||
if (hasHacknetServers()) {
|
||||
return HacknetServerConstants.MaxServers;
|
||||
}
|
||||
return Infinity;
|
||||
},
|
||||
purchaseNode: () => (): number => {
|
||||
return purchaseHacknet(player);
|
||||
return purchaseHacknet();
|
||||
},
|
||||
getPurchaseNodeCost: () => (): number => {
|
||||
if (hasHacknetServers(player)) {
|
||||
return getCostOfNextHacknetServer(player);
|
||||
if (hasHacknetServers()) {
|
||||
return getCostOfNextHacknetServer();
|
||||
} else {
|
||||
return getCostOfNextHacknetNode(player);
|
||||
return getCostOfNextHacknetNode();
|
||||
}
|
||||
},
|
||||
getNodeStats:
|
||||
@ -74,7 +74,7 @@ export function NetscriptHacknet(): InternalAPI<IHacknet> {
|
||||
(_i: unknown): NodeStats => {
|
||||
const i = helpers.number(ctx, "i", _i);
|
||||
const node = getHacknetNode(ctx, i);
|
||||
const hasUpgraded = hasHacknetServers(player);
|
||||
const hasUpgraded = hasHacknetServers();
|
||||
const res: NodeStats = {
|
||||
name: node instanceof HacknetServer ? node.hostname : node.name,
|
||||
level: node.level,
|
||||
@ -99,7 +99,7 @@ export function NetscriptHacknet(): InternalAPI<IHacknet> {
|
||||
const i = helpers.number(ctx, "i", _i);
|
||||
const n = helpers.number(ctx, "n", _n);
|
||||
const node = getHacknetNode(ctx, i);
|
||||
return purchaseLevelUpgrade(player, node, n);
|
||||
return purchaseLevelUpgrade(node, n);
|
||||
},
|
||||
upgradeRam:
|
||||
(ctx: NetscriptContext) =>
|
||||
@ -107,7 +107,7 @@ export function NetscriptHacknet(): InternalAPI<IHacknet> {
|
||||
const i = helpers.number(ctx, "i", _i);
|
||||
const n = helpers.number(ctx, "n", _n);
|
||||
const node = getHacknetNode(ctx, i);
|
||||
return purchaseRamUpgrade(player, node, n);
|
||||
return purchaseRamUpgrade(node, n);
|
||||
},
|
||||
upgradeCore:
|
||||
(ctx: NetscriptContext) =>
|
||||
@ -115,14 +115,14 @@ export function NetscriptHacknet(): InternalAPI<IHacknet> {
|
||||
const i = helpers.number(ctx, "i", _i);
|
||||
const n = helpers.number(ctx, "n", _n);
|
||||
const node = getHacknetNode(ctx, i);
|
||||
return purchaseCoreUpgrade(player, node, n);
|
||||
return purchaseCoreUpgrade(node, n);
|
||||
},
|
||||
upgradeCache:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_i: unknown, _n: unknown = 1): boolean => {
|
||||
const i = helpers.number(ctx, "i", _i);
|
||||
const n = helpers.number(ctx, "n", _n);
|
||||
if (!hasHacknetServers(player)) {
|
||||
if (!hasHacknetServers()) {
|
||||
return false;
|
||||
}
|
||||
const node = getHacknetNode(ctx, i);
|
||||
@ -130,9 +130,9 @@ export function NetscriptHacknet(): InternalAPI<IHacknet> {
|
||||
helpers.log(ctx, () => "Can only be called on hacknet servers");
|
||||
return false;
|
||||
}
|
||||
const res = purchaseCacheUpgrade(player, node, n);
|
||||
const res = purchaseCacheUpgrade(node, n);
|
||||
if (res) {
|
||||
updateHashManagerCapacity(player);
|
||||
updateHashManagerCapacity();
|
||||
}
|
||||
return res;
|
||||
},
|
||||
@ -165,7 +165,7 @@ export function NetscriptHacknet(): InternalAPI<IHacknet> {
|
||||
(_i: unknown, _n: unknown = 1): number => {
|
||||
const i = helpers.number(ctx, "i", _i);
|
||||
const n = helpers.number(ctx, "n", _n);
|
||||
if (!hasHacknetServers(player)) {
|
||||
if (!hasHacknetServers()) {
|
||||
return Infinity;
|
||||
}
|
||||
const node = getHacknetNode(ctx, i);
|
||||
@ -176,13 +176,13 @@ export function NetscriptHacknet(): InternalAPI<IHacknet> {
|
||||
return node.calculateCacheUpgradeCost(n);
|
||||
},
|
||||
numHashes: () => (): number => {
|
||||
if (!hasHacknetServers(player)) {
|
||||
if (!hasHacknetServers()) {
|
||||
return 0;
|
||||
}
|
||||
return player.hashManager.hashes;
|
||||
},
|
||||
hashCapacity: () => (): number => {
|
||||
if (!hasHacknetServers(player)) {
|
||||
if (!hasHacknetServers()) {
|
||||
return 0;
|
||||
}
|
||||
return player.hashManager.capacity;
|
||||
@ -192,7 +192,7 @@ export function NetscriptHacknet(): InternalAPI<IHacknet> {
|
||||
(_upgName: unknown, _count: unknown = 1): number => {
|
||||
const upgName = helpers.string(ctx, "upgName", _upgName);
|
||||
const count = helpers.number(ctx, "count", _count);
|
||||
if (!hasHacknetServers(player)) {
|
||||
if (!hasHacknetServers()) {
|
||||
return Infinity;
|
||||
}
|
||||
|
||||
@ -204,13 +204,13 @@ export function NetscriptHacknet(): InternalAPI<IHacknet> {
|
||||
const upgName = helpers.string(ctx, "upgName", _upgName);
|
||||
const upgTarget = helpers.string(ctx, "upgTarget", _upgTarget);
|
||||
const count = helpers.number(ctx, "count", _count);
|
||||
if (!hasHacknetServers(player)) {
|
||||
if (!hasHacknetServers()) {
|
||||
return false;
|
||||
}
|
||||
return purchaseHashUpgrade(player, upgName, upgTarget, count);
|
||||
return purchaseHashUpgrade(upgName, upgTarget, count);
|
||||
},
|
||||
getHashUpgrades: () => (): string[] => {
|
||||
if (!hasHacknetServers(player)) {
|
||||
if (!hasHacknetServers()) {
|
||||
return [];
|
||||
}
|
||||
return Object.values(HashUpgrades).map((upgrade: HashUpgrade) => upgrade.name);
|
||||
@ -226,13 +226,13 @@ export function NetscriptHacknet(): InternalAPI<IHacknet> {
|
||||
return level;
|
||||
},
|
||||
getStudyMult: () => (): number => {
|
||||
if (!hasHacknetServers(player)) {
|
||||
if (!hasHacknetServers()) {
|
||||
return 1;
|
||||
}
|
||||
return player.hashManager.getStudyMult();
|
||||
},
|
||||
getTrainingMult: () => (): number => {
|
||||
if (!hasHacknetServers(player)) {
|
||||
if (!hasHacknetServers()) {
|
||||
return 1;
|
||||
}
|
||||
return player.hashManager.getTrainingMult();
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,4 +1,4 @@
|
||||
import { Player as player } from "../Player";
|
||||
import { Player } from "../Player";
|
||||
import { findSleevePurchasableAugs } from "../PersonObjects/Sleeve/SleeveHelpers";
|
||||
import { StaticAugmentations } from "../Augmentation/StaticAugmentations";
|
||||
import { CityName } from "../Locations/data/CityNames";
|
||||
@ -21,7 +21,7 @@ import { helpers } from "../Netscript/NetscriptHelpers";
|
||||
|
||||
export function NetscriptSleeve(): InternalAPI<ISleeve> {
|
||||
const checkSleeveAPIAccess = function (ctx: NetscriptContext): void {
|
||||
if (player.bitNodeN !== 10 && !player.sourceFileLvl(10)) {
|
||||
if (Player.bitNodeN !== 10 && !Player.sourceFileLvl(10)) {
|
||||
throw helpers.makeRuntimeErrorMsg(
|
||||
ctx,
|
||||
"You do not currently have access to the Sleeve API. This is either because you are not in BitNode-10 or because you do not have Source-File 10",
|
||||
@ -30,7 +30,7 @@ export function NetscriptSleeve(): InternalAPI<ISleeve> {
|
||||
};
|
||||
|
||||
const checkSleeveNumber = function (ctx: NetscriptContext, sleeveNumber: number): void {
|
||||
if (sleeveNumber >= player.sleeves.length || sleeveNumber < 0) {
|
||||
if (sleeveNumber >= Player.sleeves.length || sleeveNumber < 0) {
|
||||
const msg = `Invalid sleeve number: ${sleeveNumber}`;
|
||||
helpers.log(ctx, () => msg);
|
||||
throw helpers.makeRuntimeErrorMsg(ctx, msg);
|
||||
@ -38,7 +38,7 @@ export function NetscriptSleeve(): InternalAPI<ISleeve> {
|
||||
};
|
||||
|
||||
const getSleeveStats = function (sleeveNumber: number): SleeveSkills {
|
||||
const sl = player.sleeves[sleeveNumber];
|
||||
const sl = Player.sleeves[sleeveNumber];
|
||||
return {
|
||||
shock: 100 - sl.shock,
|
||||
sync: sl.sync,
|
||||
@ -55,7 +55,7 @@ export function NetscriptSleeve(): InternalAPI<ISleeve> {
|
||||
return {
|
||||
getNumSleeves: (ctx: NetscriptContext) => (): number => {
|
||||
checkSleeveAPIAccess(ctx);
|
||||
return player.sleeves.length;
|
||||
return Player.sleeves.length;
|
||||
},
|
||||
setToShockRecovery:
|
||||
(ctx: NetscriptContext) =>
|
||||
@ -63,7 +63,7 @@ export function NetscriptSleeve(): InternalAPI<ISleeve> {
|
||||
const sleeveNumber = helpers.number(ctx, "sleeveNumber", _sleeveNumber);
|
||||
checkSleeveAPIAccess(ctx);
|
||||
checkSleeveNumber(ctx, sleeveNumber);
|
||||
return player.sleeves[sleeveNumber].shockRecovery(player);
|
||||
return Player.sleeves[sleeveNumber].shockRecovery();
|
||||
},
|
||||
setToSynchronize:
|
||||
(ctx: NetscriptContext) =>
|
||||
@ -71,7 +71,7 @@ export function NetscriptSleeve(): InternalAPI<ISleeve> {
|
||||
const sleeveNumber = helpers.number(ctx, "sleeveNumber", _sleeveNumber);
|
||||
checkSleeveAPIAccess(ctx);
|
||||
checkSleeveNumber(ctx, sleeveNumber);
|
||||
return player.sleeves[sleeveNumber].synchronize(player);
|
||||
return Player.sleeves[sleeveNumber].synchronize();
|
||||
},
|
||||
setToCommitCrime:
|
||||
(ctx: NetscriptContext) =>
|
||||
@ -84,7 +84,7 @@ export function NetscriptSleeve(): InternalAPI<ISleeve> {
|
||||
if (crime === null) {
|
||||
return false;
|
||||
}
|
||||
return player.sleeves[sleeveNumber].commitCrime(player, crime.name);
|
||||
return Player.sleeves[sleeveNumber].commitCrime(crime.name);
|
||||
},
|
||||
setToUniversityCourse:
|
||||
(ctx: NetscriptContext) =>
|
||||
@ -94,7 +94,7 @@ export function NetscriptSleeve(): InternalAPI<ISleeve> {
|
||||
const className = helpers.string(ctx, "className", _className);
|
||||
checkSleeveAPIAccess(ctx);
|
||||
checkSleeveNumber(ctx, sleeveNumber);
|
||||
return player.sleeves[sleeveNumber].takeUniversityCourse(player, universityName, className);
|
||||
return Player.sleeves[sleeveNumber].takeUniversityCourse(universityName, className);
|
||||
},
|
||||
travel:
|
||||
(ctx: NetscriptContext) =>
|
||||
@ -104,7 +104,7 @@ export function NetscriptSleeve(): InternalAPI<ISleeve> {
|
||||
checkSleeveAPIAccess(ctx);
|
||||
checkSleeveNumber(ctx, sleeveNumber);
|
||||
if (checkEnum(CityName, cityName)) {
|
||||
return player.sleeves[sleeveNumber].travel(player, cityName);
|
||||
return Player.sleeves[sleeveNumber].travel(cityName);
|
||||
} else {
|
||||
throw helpers.makeRuntimeErrorMsg(ctx, `Invalid city name: '${cityName}'.`);
|
||||
}
|
||||
@ -118,11 +118,11 @@ export function NetscriptSleeve(): InternalAPI<ISleeve> {
|
||||
checkSleeveNumber(ctx, sleeveNumber);
|
||||
|
||||
// Cannot work at the same company that another sleeve is working at
|
||||
for (let i = 0; i < player.sleeves.length; ++i) {
|
||||
for (let i = 0; i < Player.sleeves.length; ++i) {
|
||||
if (i === sleeveNumber) {
|
||||
continue;
|
||||
}
|
||||
const other = player.sleeves[i];
|
||||
const other = Player.sleeves[i];
|
||||
if (isSleeveCompanyWork(other.currentWork) && other.currentWork.companyName === companyName) {
|
||||
throw helpers.makeRuntimeErrorMsg(
|
||||
ctx,
|
||||
@ -131,7 +131,7 @@ export function NetscriptSleeve(): InternalAPI<ISleeve> {
|
||||
}
|
||||
}
|
||||
|
||||
return player.sleeves[sleeveNumber].workForCompany(player, companyName);
|
||||
return Player.sleeves[sleeveNumber].workForCompany(companyName);
|
||||
},
|
||||
setToFactionWork:
|
||||
(ctx: NetscriptContext) =>
|
||||
@ -143,11 +143,11 @@ export function NetscriptSleeve(): InternalAPI<ISleeve> {
|
||||
checkSleeveNumber(ctx, sleeveNumber);
|
||||
|
||||
// Cannot work at the same faction that another sleeve is working at
|
||||
for (let i = 0; i < player.sleeves.length; ++i) {
|
||||
for (let i = 0; i < Player.sleeves.length; ++i) {
|
||||
if (i === sleeveNumber) {
|
||||
continue;
|
||||
}
|
||||
const other = player.sleeves[i];
|
||||
const other = Player.sleeves[i];
|
||||
if (isSleeveFactionWork(other.currentWork) && other.currentWork.factionName === factionName) {
|
||||
throw helpers.makeRuntimeErrorMsg(
|
||||
ctx,
|
||||
@ -156,14 +156,14 @@ export function NetscriptSleeve(): InternalAPI<ISleeve> {
|
||||
}
|
||||
}
|
||||
|
||||
if (player.gang && player.gang.facName == factionName) {
|
||||
if (Player.gang && Player.gang.facName == factionName) {
|
||||
throw helpers.makeRuntimeErrorMsg(
|
||||
ctx,
|
||||
`Sleeve ${sleeveNumber} cannot work for faction ${factionName} because you have started a gang with them.`,
|
||||
);
|
||||
}
|
||||
|
||||
return player.sleeves[sleeveNumber].workForFaction(player, factionName, workType);
|
||||
return Player.sleeves[sleeveNumber].workForFaction(factionName, workType);
|
||||
},
|
||||
setToGymWorkout:
|
||||
(ctx: NetscriptContext) =>
|
||||
@ -174,7 +174,7 @@ export function NetscriptSleeve(): InternalAPI<ISleeve> {
|
||||
checkSleeveAPIAccess(ctx);
|
||||
checkSleeveNumber(ctx, sleeveNumber);
|
||||
|
||||
return player.sleeves[sleeveNumber].workoutAtGym(player, gymName, stat);
|
||||
return Player.sleeves[sleeveNumber].workoutAtGym(gymName, stat);
|
||||
},
|
||||
getSleeveStats:
|
||||
(ctx: NetscriptContext) =>
|
||||
@ -191,7 +191,7 @@ export function NetscriptSleeve(): InternalAPI<ISleeve> {
|
||||
checkSleeveAPIAccess(ctx);
|
||||
checkSleeveNumber(ctx, sleeveNumber);
|
||||
|
||||
const sl = player.sleeves[sleeveNumber];
|
||||
const sl = Player.sleeves[sleeveNumber];
|
||||
if (sl.currentWork === null) return null;
|
||||
return sl.currentWork.APICopy();
|
||||
},
|
||||
@ -202,13 +202,13 @@ export function NetscriptSleeve(): InternalAPI<ISleeve> {
|
||||
checkSleeveAPIAccess(ctx);
|
||||
checkSleeveNumber(ctx, sleeveNumber);
|
||||
|
||||
const sl = player.sleeves[sleeveNumber];
|
||||
const sl = Player.sleeves[sleeveNumber];
|
||||
return {
|
||||
tor: false,
|
||||
city: sl.city,
|
||||
hp: sl.hp,
|
||||
jobs: Object.keys(player.jobs), // technically sleeves have the same jobs as the player.
|
||||
jobTitle: Object.values(player.jobs),
|
||||
jobs: Object.keys(Player.jobs), // technically sleeves have the same jobs as the player.
|
||||
jobTitle: Object.values(Player.jobs),
|
||||
|
||||
mult: {
|
||||
agility: sl.mults.agility,
|
||||
@ -239,8 +239,8 @@ export function NetscriptSleeve(): InternalAPI<ISleeve> {
|
||||
checkSleeveNumber(ctx, sleeveNumber);
|
||||
|
||||
const augs = [];
|
||||
for (let i = 0; i < player.sleeves[sleeveNumber].augmentations.length; i++) {
|
||||
augs.push(player.sleeves[sleeveNumber].augmentations[i].name);
|
||||
for (let i = 0; i < Player.sleeves[sleeveNumber].augmentations.length; i++) {
|
||||
augs.push(Player.sleeves[sleeveNumber].augmentations[i].name);
|
||||
}
|
||||
return augs;
|
||||
},
|
||||
@ -251,7 +251,7 @@ export function NetscriptSleeve(): InternalAPI<ISleeve> {
|
||||
checkSleeveAPIAccess(ctx);
|
||||
checkSleeveNumber(ctx, sleeveNumber);
|
||||
|
||||
const purchasableAugs = findSleevePurchasableAugs(player.sleeves[sleeveNumber], player);
|
||||
const purchasableAugs = findSleevePurchasableAugs(Player.sleeves[sleeveNumber]);
|
||||
const augs = [];
|
||||
for (let i = 0; i < purchasableAugs.length; i++) {
|
||||
const aug = purchasableAugs[i];
|
||||
@ -280,7 +280,7 @@ export function NetscriptSleeve(): InternalAPI<ISleeve> {
|
||||
throw helpers.makeRuntimeErrorMsg(ctx, `Invalid aug: ${augName}`);
|
||||
}
|
||||
|
||||
return player.sleeves[sleeveNumber].tryBuyAugmentation(player, aug);
|
||||
return Player.sleeves[sleeveNumber].tryBuyAugmentation(aug);
|
||||
},
|
||||
getSleeveAugmentationPrice:
|
||||
(ctx: NetscriptContext) =>
|
||||
@ -296,7 +296,7 @@ export function NetscriptSleeve(): InternalAPI<ISleeve> {
|
||||
checkSleeveAPIAccess(ctx);
|
||||
const augName = helpers.string(ctx, "augName", _augName);
|
||||
const aug: Augmentation = StaticAugmentations[augName];
|
||||
return aug.getCost(player).repCost;
|
||||
return aug.getCost().repCost;
|
||||
},
|
||||
setToBladeburnerAction:
|
||||
(ctx: NetscriptContext) =>
|
||||
@ -314,11 +314,11 @@ export function NetscriptSleeve(): InternalAPI<ISleeve> {
|
||||
|
||||
// Cannot Take on Contracts if another sleeve is performing that action
|
||||
if (action === "Take on contracts") {
|
||||
for (let i = 0; i < player.sleeves.length; ++i) {
|
||||
for (let i = 0; i < Player.sleeves.length; ++i) {
|
||||
if (i === sleeveNumber) {
|
||||
continue;
|
||||
}
|
||||
const other = player.sleeves[i];
|
||||
const other = Player.sleeves[i];
|
||||
if (isSleeveBladeburnerWork(other.currentWork) && other.currentWork.actionName === contract) {
|
||||
throw helpers.makeRuntimeErrorMsg(
|
||||
ctx,
|
||||
@ -328,7 +328,7 @@ export function NetscriptSleeve(): InternalAPI<ISleeve> {
|
||||
}
|
||||
}
|
||||
|
||||
return player.sleeves[sleeveNumber].bladeburner(player, action, contract);
|
||||
return Player.sleeves[sleeveNumber].bladeburner(action, contract);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user