mirror of
https://github.com/bitburner-official/bitburner-src.git
synced 2025-03-07 11:04:36 +01:00
TYPESAFETY: FactionName (#644)
This commit is contained in:
@ -23,7 +23,7 @@ import { BladeburnerConstants } from "./data/Constants";
|
||||
import { formatExp, formatMoney, formatPercent, formatBigNumber, formatStamina } from "../ui/formatNumber";
|
||||
import { currentNodeMults } from "../BitNode/BitNodeMultipliers";
|
||||
import { addOffset } from "../utils/helpers/addOffset";
|
||||
import { Factions, factionExists } from "../Faction/Factions";
|
||||
import { Factions } from "../Faction/Factions";
|
||||
import { calculateHospitalizationCost } from "../Hospital/Hospital";
|
||||
import { dialogBoxCreate } from "../ui/React/DialogBox";
|
||||
import { Settings } from "../Settings/Settings";
|
||||
@ -1608,18 +1608,11 @@ export class Bladeburner {
|
||||
this.maxRank = Math.max(this.rank, this.maxRank);
|
||||
|
||||
const bladeburnersFactionName = FactionName.Bladeburners;
|
||||
if (factionExists(bladeburnersFactionName)) {
|
||||
const bladeburnerFac = Factions[bladeburnersFactionName];
|
||||
if (!bladeburnerFac) {
|
||||
throw new Error(
|
||||
`Could not properly get ${FactionName.Bladeburners} Faction object in ${FactionName.Bladeburners} UI Overview Faction button`,
|
||||
);
|
||||
}
|
||||
if (bladeburnerFac.isMember) {
|
||||
const favorBonus = 1 + bladeburnerFac.favor / 100;
|
||||
bladeburnerFac.playerReputation +=
|
||||
BladeburnerConstants.RankToFactionRepFactor * change * person.mults.faction_rep * favorBonus;
|
||||
}
|
||||
const bladeburnerFac = Factions[bladeburnersFactionName];
|
||||
if (bladeburnerFac.isMember) {
|
||||
const favorBonus = 1 + bladeburnerFac.favor / 100;
|
||||
bladeburnerFac.playerReputation +=
|
||||
BladeburnerConstants.RankToFactionRepFactor * change * person.mults.faction_rep * favorBonus;
|
||||
}
|
||||
|
||||
// Gain skill points
|
||||
|
@ -124,38 +124,29 @@ function getRandomProblemType(): string {
|
||||
}
|
||||
|
||||
function getRandomReward(): ICodingContractReward {
|
||||
const reward: ICodingContractReward = {
|
||||
name: "",
|
||||
type: getRandomInt(0, CodingContractRewardType.Money),
|
||||
};
|
||||
reward.type = sanitizeRewardType(reward.type);
|
||||
const rewardType = sanitizeRewardType(getRandomInt(0, CodingContractRewardType.Money));
|
||||
|
||||
// Add additional information based on the reward type
|
||||
const factionsThatAllowHacking = Player.factions.filter((fac) => Factions[fac].getInfo().offerHackingWork);
|
||||
|
||||
switch (reward.type) {
|
||||
switch (rewardType) {
|
||||
case CodingContractRewardType.FactionReputation: {
|
||||
// Get a random faction that player is a part of. That
|
||||
// faction must allow hacking contracts
|
||||
const numFactions = factionsThatAllowHacking.length;
|
||||
const randFaction = factionsThatAllowHacking[getRandomInt(0, numFactions - 1)];
|
||||
reward.name = randFaction;
|
||||
break;
|
||||
return { type: rewardType, name: randFaction };
|
||||
}
|
||||
case CodingContractRewardType.CompanyReputation: {
|
||||
const allJobs = Object.keys(Player.jobs);
|
||||
if (allJobs.length > 0) {
|
||||
reward.name = allJobs[getRandomInt(0, allJobs.length - 1)];
|
||||
} else {
|
||||
reward.type = CodingContractRewardType.Money;
|
||||
return { type: CodingContractRewardType.CompanyReputation, name: allJobs[getRandomInt(0, allJobs.length - 1)] };
|
||||
}
|
||||
break;
|
||||
return { type: CodingContractRewardType.Money };
|
||||
}
|
||||
default:
|
||||
break;
|
||||
return { type: rewardType };
|
||||
}
|
||||
|
||||
return reward;
|
||||
}
|
||||
|
||||
function getRandomServer(): BaseServer {
|
||||
@ -182,7 +173,7 @@ function getRandomServer(): BaseServer {
|
||||
|
||||
function getRandomFilename(
|
||||
server: BaseServer,
|
||||
reward: ICodingContractReward = { name: "", type: 0 },
|
||||
reward: ICodingContractReward = { type: CodingContractRewardType.Money },
|
||||
): ContractFilePath {
|
||||
let contractFn = `contract-${getRandomInt(0, 1e6)}`;
|
||||
|
||||
@ -197,7 +188,7 @@ function getRandomFilename(
|
||||
contractFn = `contract-${getRandomInt(0, 1e6)}`;
|
||||
}
|
||||
|
||||
if (reward.name) {
|
||||
if ("name" in reward) {
|
||||
// Only alphanumeric characters in the reward name.
|
||||
contractFn += `-${reward.name.replace(/[^a-zA-Z0-9]/g, "")}`;
|
||||
}
|
||||
|
@ -1,3 +1,4 @@
|
||||
import type { FactionName } from "@enums";
|
||||
import { codingContractTypesMetadata, DescriptionFunc, GeneratorFunc, SolverFunc } from "./data/codingcontracttypes";
|
||||
|
||||
import { Generic_fromJSON, Generic_toJSON, IReviverValue, constructorsForReviver } from "./utils/JSONReviver";
|
||||
@ -73,11 +74,21 @@ export enum CodingContractResult {
|
||||
}
|
||||
|
||||
/** A class that represents the type of reward a contract gives */
|
||||
export interface ICodingContractReward {
|
||||
/* Name of Company/Faction name for reward, if applicable */
|
||||
name?: string;
|
||||
type: CodingContractRewardType;
|
||||
}
|
||||
export type ICodingContractReward =
|
||||
| {
|
||||
type: CodingContractRewardType.Money;
|
||||
}
|
||||
| {
|
||||
type: CodingContractRewardType.FactionReputationAll;
|
||||
}
|
||||
| {
|
||||
type: CodingContractRewardType.CompanyReputation;
|
||||
name: string;
|
||||
}
|
||||
| {
|
||||
type: CodingContractRewardType.FactionReputation;
|
||||
name: FactionName;
|
||||
};
|
||||
|
||||
/**
|
||||
* A Coding Contract is a file that poses a programming-related problem to the Player.
|
||||
|
@ -1,17 +1,17 @@
|
||||
import type { FactionName } from "@enums";
|
||||
|
||||
import React, { useState } from "react";
|
||||
import { Box, Button, MenuItem, Select, SelectChangeEvent, Typography } from "@mui/material";
|
||||
|
||||
import { Player } from "@player";
|
||||
import { Factions } from "../../../Faction/Factions";
|
||||
import * as corpConstants from "../../data/Constants";
|
||||
import { formatReputation } from "../../../ui/formatNumber";
|
||||
import { dialogBoxCreate } from "../../../ui/React/DialogBox";
|
||||
import { Modal } from "../../../ui/React/Modal";
|
||||
import { Player } from "@player";
|
||||
import { useCorporation } from "../Context";
|
||||
import Typography from "@mui/material/Typography";
|
||||
import Button from "@mui/material/Button";
|
||||
import MenuItem from "@mui/material/MenuItem";
|
||||
import { NumberInput } from "../../../ui/React/NumberInput";
|
||||
import Box from "@mui/material/Box";
|
||||
import Select, { SelectChangeEvent } from "@mui/material/Select";
|
||||
import { getEnumHelper } from "../../../utils/EnumHelper";
|
||||
|
||||
interface IProps {
|
||||
open: boolean;
|
||||
@ -19,7 +19,7 @@ interface IProps {
|
||||
}
|
||||
|
||||
export function BribeFactionModal(props: IProps): React.ReactElement {
|
||||
const factions = Player.factions.filter((name: string) => {
|
||||
const factions = Player.factions.filter((name) => {
|
||||
const info = Factions[name].getInfo();
|
||||
if (!info.offersWork()) return false;
|
||||
if (Player.hasGangWith(name)) return false;
|
||||
@ -27,10 +27,11 @@ export function BribeFactionModal(props: IProps): React.ReactElement {
|
||||
});
|
||||
const corp = useCorporation();
|
||||
const [money, setMoney] = useState<number>(NaN);
|
||||
const [selectedFaction, setSelectedFaction] = useState(factions.length > 0 ? factions[0] : "");
|
||||
const [selectedFaction, setSelectedFaction] = useState<FactionName | "">(factions.length > 0 ? factions[0] : "");
|
||||
const disabled = money === 0 || isNaN(money) || money < 0 || corp.funds < money;
|
||||
|
||||
function changeFaction(event: SelectChangeEvent): void {
|
||||
if (!getEnumHelper("FactionName").isMember(event.target.value)) return;
|
||||
setSelectedFaction(event.target.value);
|
||||
}
|
||||
|
||||
@ -52,6 +53,7 @@ export function BribeFactionModal(props: IProps): React.ReactElement {
|
||||
}
|
||||
|
||||
function bribe(money: number): void {
|
||||
if (!selectedFaction) return;
|
||||
const fac = Factions[selectedFaction];
|
||||
if (disabled) return;
|
||||
const rep = repGain(money);
|
||||
@ -69,7 +71,7 @@ export function BribeFactionModal(props: IProps): React.ReactElement {
|
||||
<Box display="flex" alignItems="center">
|
||||
<Typography>Faction:</Typography>
|
||||
<Select value={selectedFaction} onChange={changeFaction}>
|
||||
{factions.map((name: string) => {
|
||||
{factions.map((name) => {
|
||||
const info = Factions[name].getInfo();
|
||||
if (!info.offersWork()) return;
|
||||
if (Player.hasGangWith(name)) return;
|
||||
|
@ -5,7 +5,7 @@ import React, { useEffect } from "react";
|
||||
|
||||
import { General } from "./DevMenu/ui/General";
|
||||
import { Stats } from "./DevMenu/ui/Stats";
|
||||
import { Factions } from "./DevMenu/ui/Factions";
|
||||
import { FactionsDev } from "./DevMenu/ui/FactionsDev";
|
||||
import { Augmentations } from "./DevMenu/ui/Augmentations";
|
||||
import { SourceFiles } from "./DevMenu/ui/SourceFiles";
|
||||
import { Programs } from "./DevMenu/ui/Programs";
|
||||
@ -34,7 +34,7 @@ export function DevMenuRoot(): React.ReactElement {
|
||||
<Typography>Development Menu - Only meant to be used for testing/debugging</Typography>
|
||||
<General />
|
||||
<Stats />
|
||||
<Factions />
|
||||
<FactionsDev />
|
||||
<Augmentations />
|
||||
<SourceFiles />
|
||||
<Programs />
|
||||
|
@ -1,7 +1,4 @@
|
||||
import React, { useState } from "react";
|
||||
|
||||
import { Player } from "@player";
|
||||
import { FactionName } from "@enums";
|
||||
import {
|
||||
Accordion,
|
||||
AccordionSummary,
|
||||
@ -11,27 +8,33 @@ import {
|
||||
IconButton,
|
||||
InputLabel,
|
||||
MenuItem,
|
||||
Select,
|
||||
SelectChangeEvent,
|
||||
Typography,
|
||||
} from "@mui/material";
|
||||
import ExpandMoreIcon from "@mui/icons-material/ExpandMore";
|
||||
|
||||
import Select, { SelectChangeEvent } from "@mui/material/Select";
|
||||
import { Adjuster } from "./Adjuster";
|
||||
import { Factions as AllFaction } from "../../Faction/Factions";
|
||||
import ReplyAllIcon from "@mui/icons-material/ReplyAll";
|
||||
import ReplyIcon from "@mui/icons-material/Reply";
|
||||
|
||||
import { Player } from "@player";
|
||||
import { FactionName } from "@enums";
|
||||
import { Adjuster } from "./Adjuster";
|
||||
import { Factions } from "../../Faction/Factions";
|
||||
import { getRecordValues } from "../../Types/Record";
|
||||
import { getEnumHelper } from "../../utils/EnumHelper";
|
||||
|
||||
const bigNumber = 1e12;
|
||||
|
||||
export function Factions(): React.ReactElement {
|
||||
const [faction, setFaction] = useState(FactionName.Illuminati as string);
|
||||
export function FactionsDev(): React.ReactElement {
|
||||
const [factionName, setFactionName] = useState(FactionName.Illuminati);
|
||||
|
||||
function setFactionDropdown(event: SelectChangeEvent): void {
|
||||
setFaction(event.target.value);
|
||||
if (!getEnumHelper("FactionName").isMember(event.target.value)) return;
|
||||
setFactionName(event.target.value);
|
||||
}
|
||||
|
||||
function receiveInvite(): void {
|
||||
Player.receiveInvite(faction);
|
||||
Player.receiveInvite(factionName);
|
||||
}
|
||||
|
||||
function receiveAllInvites(): void {
|
||||
@ -40,57 +43,53 @@ export function Factions(): React.ReactElement {
|
||||
|
||||
function modifyFactionRep(modifier: number): (x: number) => void {
|
||||
return function (reputation: number): void {
|
||||
const fac = AllFaction[faction];
|
||||
if (fac != null && !isNaN(reputation)) {
|
||||
const fac = Factions[factionName];
|
||||
if (!isNaN(reputation)) {
|
||||
fac.playerReputation += reputation * modifier;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function resetFactionRep(): void {
|
||||
const fac = AllFaction[faction];
|
||||
if (fac != null) {
|
||||
fac.playerReputation = 0;
|
||||
}
|
||||
const fac = Factions[factionName];
|
||||
fac.playerReputation = 0;
|
||||
}
|
||||
|
||||
function modifyFactionFavor(modifier: number): (x: number) => void {
|
||||
return function (favor: number): void {
|
||||
const fac = AllFaction[faction];
|
||||
if (fac != null && !isNaN(favor)) {
|
||||
const fac = Factions[factionName];
|
||||
if (!isNaN(favor)) {
|
||||
fac.favor += favor * modifier;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function resetFactionFavor(): void {
|
||||
const fac = AllFaction[faction];
|
||||
if (fac != null) {
|
||||
fac.favor = 0;
|
||||
}
|
||||
const fac = Factions[factionName];
|
||||
fac.favor = 0;
|
||||
}
|
||||
|
||||
function tonsOfRep(): void {
|
||||
for (const i of Object.keys(AllFaction)) {
|
||||
AllFaction[i].playerReputation = bigNumber;
|
||||
for (const faction of getRecordValues(Factions)) {
|
||||
faction.playerReputation = bigNumber;
|
||||
}
|
||||
}
|
||||
|
||||
function resetAllRep(): void {
|
||||
for (const i of Object.keys(AllFaction)) {
|
||||
AllFaction[i].playerReputation = 0;
|
||||
for (const faction of getRecordValues(Factions)) {
|
||||
faction.playerReputation = 0;
|
||||
}
|
||||
}
|
||||
|
||||
function tonsOfFactionFavor(): void {
|
||||
for (const i of Object.keys(AllFaction)) {
|
||||
AllFaction[i].favor = bigNumber;
|
||||
for (const faction of getRecordValues(Factions)) {
|
||||
faction.favor = bigNumber;
|
||||
}
|
||||
}
|
||||
|
||||
function resetAllFactionFavor(): void {
|
||||
for (const i of Object.keys(AllFaction)) {
|
||||
AllFaction[i].favor = 0;
|
||||
for (const faction of getRecordValues(Factions)) {
|
||||
faction.favor = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -113,7 +112,7 @@ export function Factions(): React.ReactElement {
|
||||
labelId="factions-select"
|
||||
id="factions-dropdown"
|
||||
onChange={setFactionDropdown}
|
||||
value={faction}
|
||||
value={factionName}
|
||||
startAdornment={
|
||||
<>
|
||||
<IconButton onClick={receiveAllInvites} size="large" arial-label="receive-all-invitation">
|
||||
@ -125,7 +124,7 @@ export function Factions(): React.ReactElement {
|
||||
</>
|
||||
}
|
||||
>
|
||||
{Object.values(AllFaction).map((faction) => (
|
||||
{Object.values(Factions).map((faction) => (
|
||||
<MenuItem key={faction.name} value={faction.name}>
|
||||
{faction.name}
|
||||
</MenuItem>
|
@ -1,24 +1,31 @@
|
||||
import React, { useEffect, useState } from "react";
|
||||
import Accordion from "@mui/material/Accordion";
|
||||
import AccordionSummary from "@mui/material/AccordionSummary";
|
||||
import AccordionDetails from "@mui/material/AccordionDetails";
|
||||
import {
|
||||
Accordion,
|
||||
AccordionSummary,
|
||||
AccordionDetails,
|
||||
Button,
|
||||
MenuItem,
|
||||
Select,
|
||||
SelectChangeEvent,
|
||||
TextField,
|
||||
Typography,
|
||||
} from "@mui/material";
|
||||
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 { Player } from "@player";
|
||||
import { FactionName } from "@enums";
|
||||
import { Money } from "../../ui/React/Money";
|
||||
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 { FactionName } from "@enums";
|
||||
import { checkForMessagesToSend } from "../../Message/MessageHelpers";
|
||||
import { ThemeEvents } from "../../Themes/ui/Theme";
|
||||
import { getEnumHelper } from "../../utils/EnumHelper";
|
||||
|
||||
export function General(): React.ReactElement {
|
||||
const [error, setError] = useState(false);
|
||||
const [corporationName, setCorporationName] = useState("");
|
||||
const [gangFaction, setGangFaction] = useState("Slum Snakes");
|
||||
const [gangFaction, setGangFaction] = useState(FactionName.SlumSnakes);
|
||||
const [devMoney, setDevMoney] = useState(0);
|
||||
|
||||
// Money functions
|
||||
@ -71,7 +78,11 @@ export function General(): React.ReactElement {
|
||||
// Rerender so the gang menu option will be removed immediately on the devmenu page selection
|
||||
ThemeEvents.emit();
|
||||
};
|
||||
const setGangFactionDropdown = (event: SelectChangeEvent) => setGangFaction(event.target.value);
|
||||
const setGangFactionDropdown = (event: SelectChangeEvent) => {
|
||||
// Todo: Make this a more specific check when a GangName enumlike is added
|
||||
if (!getEnumHelper("FactionName").isMember(event.target.value)) return;
|
||||
setGangFaction(event.target.value);
|
||||
};
|
||||
|
||||
// Misc functions
|
||||
const checkMessages = () => checkForMessagesToSend();
|
||||
|
@ -1,8 +1,8 @@
|
||||
import type { AugmentationName } from "@enums";
|
||||
import { AugmentationName, FactionName } from "@enums";
|
||||
import { FactionInfo, FactionInfos } from "./FactionInfo";
|
||||
import { favorToRep, repToFavor } from "./formulas/favor";
|
||||
import { Generic_fromJSON, Generic_toJSON, IReviverValue, constructorsForReviver } from "../utils/JSONReviver";
|
||||
import { getEnumHelper } from "../utils/EnumHelper";
|
||||
import { getKeyList } from "../utils/helpers/getKeyList";
|
||||
|
||||
export class Faction {
|
||||
/**
|
||||
@ -24,12 +24,12 @@ export class Faction {
|
||||
isMember = false;
|
||||
|
||||
/** Name of faction */
|
||||
name = "";
|
||||
name: FactionName;
|
||||
|
||||
/** Amount of reputation player has with this faction */
|
||||
playerReputation = 0;
|
||||
|
||||
constructor(name = "") {
|
||||
constructor(name = FactionName.Sector12) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@ -44,11 +44,24 @@ export class Faction {
|
||||
return info;
|
||||
}
|
||||
|
||||
gainFavor(): void {
|
||||
if (this.favor == null) {
|
||||
this.favor = 0;
|
||||
}
|
||||
prestigeSourceFile() {
|
||||
// Reset favor, reputation, and flags
|
||||
this.favor = 0;
|
||||
this.playerReputation = 0;
|
||||
this.alreadyInvited = false;
|
||||
this.isMember = false;
|
||||
this.isBanned = false;
|
||||
}
|
||||
|
||||
prestigeAugmentation(): void {
|
||||
// Gain favor
|
||||
if (this.favor == null) this.favor = 0;
|
||||
this.favor += this.getFavorGain();
|
||||
// Reset reputation and flags
|
||||
this.playerReputation = 0;
|
||||
this.alreadyInvited = false;
|
||||
this.isMember = false;
|
||||
this.isBanned = false;
|
||||
}
|
||||
|
||||
//Returns an array with [How much favor would be gained, how much rep would be left over]
|
||||
@ -62,21 +75,16 @@ export class Faction {
|
||||
return newFavor - this.favor;
|
||||
}
|
||||
|
||||
static savedKeys = getKeyList(Faction, { removedKeys: ["augmentations", "name"] });
|
||||
|
||||
/** Serialize the current object to a JSON save state. */
|
||||
toJSON(): IReviverValue {
|
||||
return Generic_toJSON("Faction", this);
|
||||
return Generic_toJSON("Faction", this, Faction.savedKeys);
|
||||
}
|
||||
|
||||
/** Initializes a Faction object from a JSON save state. */
|
||||
static fromJSON(value: IReviverValue): Faction {
|
||||
const faction = Generic_fromJSON(Faction, value.data);
|
||||
if (!Array.isArray(faction.augmentations)) faction.augmentations = [];
|
||||
// Remove invalid augs from faction. Augs are repopulated with correct augs during any reset.
|
||||
const augHelper = getEnumHelper("AugmentationName");
|
||||
faction.augmentations = faction.augmentations.filter((augName) => augHelper.isMember(augName));
|
||||
// Fix broken saves, this will soon be removed when better fix is implemented
|
||||
faction.augmentations = [...new Set(faction.augmentations)];
|
||||
return faction;
|
||||
return Generic_fromJSON(Faction, value.data, Faction.savedKeys);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,12 +1,13 @@
|
||||
import type { Augmentation } from "../Augmentation/Augmentation";
|
||||
import type { Faction } from "./Faction";
|
||||
|
||||
import { Augmentations } from "../Augmentation/Augmentations";
|
||||
import { Augmentation } from "../Augmentation/Augmentation";
|
||||
import { PlayerOwnedAugmentation } from "../Augmentation/PlayerOwnedAugmentation";
|
||||
import { AugmentationName, FactionName } from "@enums";
|
||||
import { currentNodeMults } from "../BitNode/BitNodeMultipliers";
|
||||
|
||||
import { Faction } from "./Faction";
|
||||
import { Factions } from "./Factions";
|
||||
import { Player } from "@player";
|
||||
import { Factions } from "./Factions";
|
||||
import { Settings } from "../Settings/Settings";
|
||||
import {
|
||||
getHackingWorkRepGain,
|
||||
@ -19,6 +20,7 @@ import { InvitationEvent } from "./ui/InvitationModal";
|
||||
import { SFC32RNG } from "../Casino/RNG";
|
||||
import { isFactionWork } from "../Work/FactionWork";
|
||||
import { getAugCost } from "../Augmentation/AugmentationHelpers";
|
||||
import { createEnumKeyedRecord, getRecordKeys } from "../Types/Record";
|
||||
|
||||
export function inviteToFaction(faction: Faction): void {
|
||||
Player.receiveInvite(faction.name);
|
||||
@ -32,8 +34,9 @@ export function joinFaction(faction: Faction): void {
|
||||
if (faction.isMember) return;
|
||||
faction.isMember = true;
|
||||
Player.factions.push(faction.name);
|
||||
const allFactions = Object.values(FactionName).map((faction) => faction as string);
|
||||
Player.factions.sort((a, b) => allFactions.indexOf(a) - allFactions.indexOf(b));
|
||||
let i = 0;
|
||||
const factionIndexes = createEnumKeyedRecord(FactionName, (__) => i++);
|
||||
Player.factions.sort((a, b) => factionIndexes[a] - factionIndexes[b]);
|
||||
const factionInfo = faction.getInfo();
|
||||
|
||||
//Determine what factions you are banned from now that you have joined this faction
|
||||
@ -108,9 +111,8 @@ export function purchaseAugmentation(aug: Augmentation, fac: Faction, sing = fal
|
||||
|
||||
export function processPassiveFactionRepGain(numCycles: number): void {
|
||||
if (Player.bitNodeN === 2) return;
|
||||
for (const name of Object.keys(Factions)) {
|
||||
for (const name of getRecordKeys(Factions)) {
|
||||
if (isFactionWork(Player.currentWork) && name === Player.currentWork.factionName) continue;
|
||||
if (!Object.hasOwn(Factions, name)) continue;
|
||||
const faction = Factions[name];
|
||||
if (!faction.isMember) continue;
|
||||
// No passive rep for special factions
|
||||
|
@ -7,7 +7,7 @@ import { Typography } from "@mui/material";
|
||||
|
||||
interface FactionInfoParams {
|
||||
infoText?: JSX.Element;
|
||||
enemies?: string[];
|
||||
enemies?: FactionName[];
|
||||
offerHackingWork?: boolean;
|
||||
offerFieldWork?: boolean;
|
||||
offerSecurityWork?: boolean;
|
||||
@ -19,7 +19,7 @@ interface FactionInfoParams {
|
||||
/** Contains the "information" property for all the Factions, which is just a description of each faction */
|
||||
export class FactionInfo {
|
||||
/** The names of all other factions considered to be enemies to this faction. */
|
||||
enemies: string[];
|
||||
enemies: FactionName[];
|
||||
|
||||
/** The descriptive text to show on the faction's page. */
|
||||
infoText: JSX.Element;
|
||||
@ -60,7 +60,7 @@ export class FactionInfo {
|
||||
}
|
||||
|
||||
/** A map of all factions and associated info to them. */
|
||||
export const FactionInfos: Record<string, FactionInfo> = {
|
||||
export const FactionInfos: Record<FactionName, FactionInfo> = {
|
||||
// Endgame
|
||||
[FactionName.Illuminati]: new FactionInfo({
|
||||
infoText: (
|
||||
|
@ -2,63 +2,42 @@
|
||||
* Initialization and manipulation of the Factions object, which stores data
|
||||
* about all Factions in the game
|
||||
*/
|
||||
import { FactionName } from "@enums";
|
||||
import { Faction } from "./Faction";
|
||||
import { FactionInfos } from "./FactionInfo";
|
||||
|
||||
import { Reviver } from "../utils/JSONReviver";
|
||||
import { getRecordValues } from "../Types/Record";
|
||||
import { Augmentations, initCircadianModulator } from "../Augmentation/Augmentations";
|
||||
import { Reviver, assertLoadingType } from "../utils/JSONReviver";
|
||||
import { createEnumKeyedRecord, getRecordValues } from "../Types/Record";
|
||||
import { Augmentations } from "../Augmentation/Augmentations";
|
||||
import { getEnumHelper } from "../utils/EnumHelper";
|
||||
|
||||
export let Factions: Record<string, Faction> = {};
|
||||
/** The static list of all factions. Initialized once and never modified. */
|
||||
export const Factions = createEnumKeyedRecord(FactionName, (name) => new Faction(name));
|
||||
// Add the associated augs to every faction
|
||||
for (const aug of getRecordValues(Augmentations)) {
|
||||
for (const factionName of aug.factions) {
|
||||
const faction = Factions[factionName];
|
||||
faction.augmentations.push(aug.name);
|
||||
}
|
||||
}
|
||||
|
||||
export function loadFactions(saveString: string): void {
|
||||
Factions = JSON.parse(saveString, Reviver);
|
||||
// safety check for when we load older save file that don't have newer factions
|
||||
for (const faction of Object.keys(Factions)) {
|
||||
try {
|
||||
Factions[faction].getInfo();
|
||||
} catch (err) {
|
||||
console.error("deleting " + faction);
|
||||
delete Factions[faction];
|
||||
}
|
||||
// The only information that should be loaded from player save is
|
||||
const loadedFactions = JSON.parse(saveString, Reviver) as unknown;
|
||||
// This loading method allows invalid data in player save, but just ignores anything invalid
|
||||
if (!loadedFactions) return;
|
||||
if (typeof loadedFactions !== "object") return;
|
||||
for (const [loadedFactionName, loadedFaction] of Object.entries(loadedFactions) as [string, unknown][]) {
|
||||
if (!getEnumHelper("FactionName").isMember(loadedFactionName)) continue;
|
||||
if (!loadedFaction) continue;
|
||||
const faction = Factions[loadedFactionName];
|
||||
if (typeof loadedFaction !== "object") continue;
|
||||
assertLoadingType<Faction>(loadedFaction);
|
||||
const { playerReputation: loadedRep, favor: loadedFavor } = loadedFaction;
|
||||
if (typeof loadedRep === "number" && loadedRep > 0) faction.playerReputation = loadedRep;
|
||||
if (typeof loadedFavor === "number" && loadedFavor > 0) faction.favor = loadedFavor;
|
||||
// Todo, these 3 will be removed from Faction object and savedata after a separate PR changes some data structures on Player to make this unnecessary info to save
|
||||
if (loadedFaction.alreadyInvited) faction.alreadyInvited = true;
|
||||
if (loadedFaction.isBanned) faction.isBanned = true;
|
||||
if (loadedFaction.isMember) faction.isMember = true;
|
||||
}
|
||||
}
|
||||
|
||||
function AddToFactions(faction: Faction): void {
|
||||
const name: string = faction.name;
|
||||
Factions[name] = faction;
|
||||
}
|
||||
|
||||
export function factionExists(name: string): boolean {
|
||||
return Object.hasOwn(Factions, name);
|
||||
}
|
||||
|
||||
export function initFactions(): void {
|
||||
for (const name of Object.keys(FactionInfos)) {
|
||||
resetFaction(new Faction(name));
|
||||
}
|
||||
// All factions are added, this is a good place to add augs back to factions.
|
||||
initCircadianModulator();
|
||||
for (const aug of getRecordValues(Augmentations)) {
|
||||
for (const factionName of aug.factions) {
|
||||
const faction = Factions[factionName];
|
||||
if (!faction) {
|
||||
console.error(`Faction ${factionName} did not exist while adding augs to factions`);
|
||||
continue;
|
||||
}
|
||||
faction.augmentations.push(aug.name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Resets a faction during (re-)initialization. Saves the favor in the new
|
||||
//Faction object and deletes the old Faction Object from "Factions". Then
|
||||
//reinserts the new Faction object
|
||||
function resetFaction(newFactionObject: Faction): void {
|
||||
const factionName: string = newFactionObject.name;
|
||||
if (factionExists(factionName)) {
|
||||
newFactionObject.favor = Factions[factionName].favor;
|
||||
delete Factions[factionName];
|
||||
}
|
||||
AddToFactions(newFactionObject);
|
||||
}
|
||||
|
@ -11,7 +11,7 @@ import { FactionName } from "@enums";
|
||||
interface IProps {
|
||||
open: boolean;
|
||||
onClose: () => void;
|
||||
facName: string;
|
||||
facName: FactionName;
|
||||
}
|
||||
|
||||
/** React Component for the popup used to create a new gang. */
|
||||
@ -27,7 +27,7 @@ export function CreateGangModal(props: IProps): React.ReactElement {
|
||||
"is not as important.";
|
||||
|
||||
function isHacking(): boolean {
|
||||
return [FactionName.NiteSec as string, FactionName.TheBlackHand as string].includes(props.facName);
|
||||
return [FactionName.NiteSec, FactionName.TheBlackHand].includes(props.facName);
|
||||
}
|
||||
|
||||
function createGang(): void {
|
||||
|
@ -1,12 +1,13 @@
|
||||
import type { Faction } from "../Faction";
|
||||
|
||||
import React, { useEffect } from "react";
|
||||
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 } from "react";
|
||||
import { Player } from "@player";
|
||||
import { Settings } from "../../Settings/Settings";
|
||||
import { formatFavor, formatReputation } from "../../ui/formatNumber";
|
||||
import { Router } from "../../ui/GameRoot";
|
||||
import { FactionName } from "@enums";
|
||||
import { Faction } from "../Faction";
|
||||
import { getFactionAugmentationsFiltered, joinFaction } from "../FactionHelpers";
|
||||
import { Factions } from "../Factions";
|
||||
import { useRerender } from "../../ui/React/hooks";
|
||||
@ -59,7 +60,7 @@ const FactionElement = (props: FactionElementProps): React.ReactElement => {
|
||||
Router.toFaction(faction, true);
|
||||
}
|
||||
|
||||
function acceptInvitation(event: React.MouseEvent<HTMLButtonElement>, faction: string): void {
|
||||
function acceptInvitation(event: React.MouseEvent<HTMLButtonElement>, faction: FactionName): void {
|
||||
if (!event.isTrusted) return;
|
||||
joinFaction(Factions[faction]);
|
||||
props.rerender();
|
||||
|
@ -23,9 +23,10 @@ import { GangMember } from "./GangMember";
|
||||
import { WorkerScript } from "../Netscript/WorkerScript";
|
||||
import { Player } from "@player";
|
||||
import { PowerMultiplier } from "./data/power";
|
||||
import { FactionName } from "@enums";
|
||||
|
||||
export class Gang {
|
||||
facName: string;
|
||||
facName: FactionName;
|
||||
members: GangMember[];
|
||||
wanted: number;
|
||||
respect: number;
|
||||
@ -48,7 +49,7 @@ export class Gang {
|
||||
|
||||
notifyMemberDeath: boolean;
|
||||
|
||||
constructor(facName = "", hacking = false) {
|
||||
constructor(facName = FactionName.SlumSnakes, hacking = false) {
|
||||
this.facName = facName;
|
||||
this.members = [];
|
||||
this.wanted = 1;
|
||||
|
@ -1,11 +1,13 @@
|
||||
import { Box, Button, MenuItem, Paper, Select, SelectChangeEvent, Typography } from "@mui/material";
|
||||
import React, { useState } from "react";
|
||||
import { Box, Button, MenuItem, Paper, Select, SelectChangeEvent, Typography } from "@mui/material";
|
||||
|
||||
import { Player } from "@player";
|
||||
import { FactionName } from "@enums";
|
||||
|
||||
import { inviteToFaction } from "../../Faction/FactionHelpers";
|
||||
import { Factions } from "../../Faction/Factions";
|
||||
import { Router } from "../../ui/GameRoot";
|
||||
import { Page } from "../../ui/Router";
|
||||
import { Player } from "@player";
|
||||
import { Money } from "../../ui/React/Money";
|
||||
import { Reputation } from "../../ui/React/Reputation";
|
||||
import { formatNumberNoSuffix } from "../../ui/formatNumber";
|
||||
@ -14,6 +16,7 @@ import {
|
||||
calculateSellInformationCashReward,
|
||||
calculateTradeInformationRepReward,
|
||||
} from "../formulas/victory";
|
||||
import { getEnumHelper } from "../../utils/EnumHelper";
|
||||
|
||||
interface IProps {
|
||||
StartingDifficulty: number;
|
||||
@ -23,7 +26,7 @@ interface IProps {
|
||||
}
|
||||
|
||||
export function Victory(props: IProps): React.ReactElement {
|
||||
const [faction, setFaction] = useState("none");
|
||||
const [factionName, setFactionName] = useState("none");
|
||||
|
||||
function quitInfiltration(): void {
|
||||
handleInfiltrators();
|
||||
@ -43,13 +46,13 @@ export function Victory(props: IProps): React.ReactElement {
|
||||
}
|
||||
|
||||
function trade(): void {
|
||||
if (faction === "none") return;
|
||||
Factions[faction].playerReputation += repGain;
|
||||
if (!getEnumHelper("FactionName").isMember(factionName)) return;
|
||||
Factions[factionName].playerReputation += repGain;
|
||||
quitInfiltration();
|
||||
}
|
||||
|
||||
function changeDropdown(event: SelectChangeEvent): void {
|
||||
setFaction(event.target.value);
|
||||
setFactionName(event.target.value);
|
||||
}
|
||||
|
||||
function handleInfiltrators(): void {
|
||||
@ -75,7 +78,7 @@ export function Victory(props: IProps): React.ReactElement {
|
||||
</Typography>
|
||||
<Box sx={{ width: "fit-content" }}>
|
||||
<Box sx={{ width: "100%" }}>
|
||||
<Select value={faction} onChange={changeDropdown} sx={{ mr: 1 }}>
|
||||
<Select value={factionName} onChange={changeDropdown} sx={{ mr: 1 }}>
|
||||
<MenuItem key={"none"} value={"none"}>
|
||||
{"none"}
|
||||
</MenuItem>
|
||||
|
@ -3,15 +3,15 @@ import { Player } from "@player";
|
||||
import { Factions } from "../Faction/Factions";
|
||||
import { Faction } from "../Faction/Faction";
|
||||
import { GetServer } from "../Server/AllServers";
|
||||
import { FactionName } from "@enums";
|
||||
import { AugmentationName, FactionName } from "@enums";
|
||||
import { Server } from "../Server/Server";
|
||||
|
||||
function allFactionAugs(f: Faction): boolean {
|
||||
const factionAugs = f.augmentations.slice().filter((aug) => aug !== "NeuroFlux Governor");
|
||||
for (const factionAug of factionAugs) {
|
||||
function allFactionAugs(faction: Faction): boolean {
|
||||
for (const factionAugName of faction.augmentations) {
|
||||
if (factionAugName === AugmentationName.NeuroFluxGovernor) continue;
|
||||
if (
|
||||
!Player.augmentations.some((aug) => {
|
||||
return aug.name == factionAug;
|
||||
return aug.name == factionAugName;
|
||||
})
|
||||
)
|
||||
return false;
|
||||
|
@ -51,7 +51,7 @@ import {
|
||||
} from "../Corporation/Actions";
|
||||
import { CorpUnlocks } from "../Corporation/data/CorporationUnlocks";
|
||||
import { CorpUpgrades } from "../Corporation/data/CorporationUpgrades";
|
||||
import { CorpUnlockName, CorpUpgradeName, CorpEmployeeJob, CityName } from "@enums";
|
||||
import { CorpUnlockName, CorpUpgradeName, CorpEmployeeJob, CityName, FactionName } from "@enums";
|
||||
import { IndustriesData, IndustryResearchTrees } from "../Corporation/data/IndustryData";
|
||||
import * as corpConstants from "../Corporation/data/Constants";
|
||||
import { ResearchMap } from "../Corporation/ResearchMap";
|
||||
@ -174,8 +174,7 @@ export function NetscriptCorporation(): InternalAPI<NSCorporation> {
|
||||
return division.researched.has(researchName);
|
||||
}
|
||||
|
||||
function bribe(factionName: string, amountCash: number): boolean {
|
||||
if (!player.factions.includes(factionName)) throw new Error("Invalid faction name");
|
||||
function bribe(factionName: FactionName, amountCash: number): boolean {
|
||||
if (isNaN(amountCash) || amountCash < 0)
|
||||
throw new Error("Invalid value for amount field! Must be numeric, greater than 0.");
|
||||
|
||||
@ -825,7 +824,7 @@ export function NetscriptCorporation(): InternalAPI<NSCorporation> {
|
||||
},
|
||||
bribe: (ctx) => (_factionName, _amountCash) => {
|
||||
checkAccess(ctx);
|
||||
const factionName = helpers.string(ctx, "factionName", _factionName);
|
||||
const factionName = getEnumHelper("FactionName").nsGetMember(ctx, _factionName);
|
||||
const amountCash = helpers.number(ctx, "amountCash", _amountCash);
|
||||
return bribe(factionName, amountCash);
|
||||
},
|
||||
|
@ -1,16 +1,17 @@
|
||||
import type { Gang as IGang, EquipmentStats, GangOtherInfoObject } from "@nsdefs";
|
||||
import type { Gang } from "../Gang/Gang";
|
||||
import type { GangMember } from "../Gang/GangMember";
|
||||
import type { GangMemberTask } from "../Gang/GangMemberTask";
|
||||
import type { InternalAPI, NetscriptContext } from "../Netscript/APIWrapper";
|
||||
|
||||
import { Player } from "@player";
|
||||
import { FactionName } from "@enums";
|
||||
import { GangConstants } from "../Gang/data/Constants";
|
||||
import { Player } from "@player";
|
||||
import { Gang } from "../Gang/Gang";
|
||||
import { AllGangs } from "../Gang/AllGangs";
|
||||
import { GangMemberTasks } from "../Gang/GangMemberTasks";
|
||||
import { GangMemberUpgrades } from "../Gang/GangMemberUpgrades";
|
||||
import { GangMember } from "../Gang/GangMember";
|
||||
import { GangMemberTask } from "../Gang/GangMemberTask";
|
||||
import { helpers } from "../Netscript/NetscriptHelpers";
|
||||
|
||||
import { Gang as IGang, EquipmentStats, GangOtherInfoObject } from "@nsdefs";
|
||||
import { InternalAPI, NetscriptContext } from "../Netscript/APIWrapper";
|
||||
import { getEnumHelper } from "../utils/EnumHelper";
|
||||
|
||||
export function NetscriptGang(): InternalAPI<IGang> {
|
||||
/** Functions as an API check and also returns the gang object */
|
||||
@ -36,9 +37,7 @@ export function NetscriptGang(): InternalAPI<IGang> {
|
||||
|
||||
return {
|
||||
createGang: (ctx) => (_faction) => {
|
||||
const faction = helpers.string(ctx, "faction", _faction);
|
||||
// this list is copied from Faction/ui/Root.tsx
|
||||
|
||||
const faction = getEnumHelper("FactionName").nsGetMember(ctx, _faction);
|
||||
if (!Player.canAccessGang() || !GangConstants.Names.includes(faction)) return false;
|
||||
if (Player.gang) return false;
|
||||
if (!Player.factions.includes(faction)) return false;
|
||||
|
@ -1,6 +1,5 @@
|
||||
import type { Singularity as ISingularity } from "@nsdefs";
|
||||
import type { Company } from "../Company/Company";
|
||||
import type { Faction } from "../Faction/Faction";
|
||||
|
||||
import { Player } from "@player";
|
||||
import {
|
||||
@ -33,7 +32,7 @@ import { formatMoney, formatRam, formatReputation } from "../ui/formatNumber";
|
||||
import { currentNodeMults } from "../BitNode/BitNodeMultipliers";
|
||||
import { Companies } from "../Company/Companies";
|
||||
import { companiesMetadata } from "../Company/data/CompaniesMetadata";
|
||||
import { Factions, factionExists } from "../Faction/Factions";
|
||||
import { Factions } from "../Faction/Factions";
|
||||
import { helpers } from "../Netscript/NetscriptHelpers";
|
||||
import { convertTimeMsToTimeElapsedString } from "../utils/StringHelperFunctions";
|
||||
import { getServerOnNetwork } from "../Server/ServerHelpers";
|
||||
@ -59,14 +58,6 @@ import { ScriptFilePath, resolveScriptFilePath } from "../Paths/ScriptFilePath";
|
||||
import { root } from "../Paths/Directory";
|
||||
|
||||
export function NetscriptSingularity(): InternalAPI<ISingularity> {
|
||||
const getFaction = function (ctx: NetscriptContext, name: string): Faction {
|
||||
if (!factionExists(name)) {
|
||||
throw helpers.makeRuntimeErrorMsg(ctx, `Invalid faction name: '${name}`);
|
||||
}
|
||||
|
||||
return Factions[name];
|
||||
};
|
||||
|
||||
const getCompany = function (ctx: NetscriptContext, name: string): Company {
|
||||
const company = Companies[name];
|
||||
if (!company) throw helpers.makeRuntimeErrorMsg(ctx, `Invalid company name: '${name}'`);
|
||||
@ -112,9 +103,8 @@ export function NetscriptSingularity(): InternalAPI<ISingularity> {
|
||||
},
|
||||
getAugmentationsFromFaction: (ctx) => (_facName) => {
|
||||
helpers.checkSingularityAccess(ctx);
|
||||
const facName = helpers.string(ctx, "facName", _facName);
|
||||
const faction = getFaction(ctx, facName);
|
||||
|
||||
const facName = getEnumHelper("FactionName").nsGetMember(ctx, _facName);
|
||||
const faction = Factions[facName];
|
||||
return getFactionAugmentationsFiltered(faction);
|
||||
},
|
||||
getAugmentationPrereq: (ctx) => (_augName) => {
|
||||
@ -149,19 +139,19 @@ export function NetscriptSingularity(): InternalAPI<ISingularity> {
|
||||
},
|
||||
purchaseAugmentation: (ctx) => (_facName, _augName) => {
|
||||
helpers.checkSingularityAccess(ctx);
|
||||
const facName = helpers.string(ctx, "facName", _facName);
|
||||
const facName = getEnumHelper("FactionName").nsGetMember(ctx, _facName);
|
||||
const augName = getEnumHelper("AugmentationName").nsGetMember(ctx, _augName);
|
||||
const fac = getFaction(ctx, facName);
|
||||
const fac = Factions[facName];
|
||||
const aug = Augmentations[augName];
|
||||
|
||||
const augs = getFactionAugmentationsFiltered(fac);
|
||||
const factionAugs = getFactionAugmentationsFiltered(fac);
|
||||
|
||||
if (!Player.factions.includes(fac.name)) {
|
||||
if (!Player.factions.includes(facName)) {
|
||||
helpers.log(ctx, () => `You can't purchase augmentations from '${facName}' because you aren't a member`);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!augs.includes(augName)) {
|
||||
if (!factionAugs.includes(augName)) {
|
||||
helpers.log(ctx, () => `Faction '${facName}' does not have the '${augName}' augmentation.`);
|
||||
return false;
|
||||
}
|
||||
@ -867,8 +857,7 @@ export function NetscriptSingularity(): InternalAPI<ISingularity> {
|
||||
},
|
||||
joinFaction: (ctx) => (_facName) => {
|
||||
helpers.checkSingularityAccess(ctx);
|
||||
const facName = helpers.string(ctx, "facName", _facName);
|
||||
getFaction(ctx, facName);
|
||||
const facName = getEnumHelper("FactionName").nsGetMember(ctx, _facName);
|
||||
|
||||
if (!Player.factionInvitations.includes(facName)) {
|
||||
helpers.log(ctx, () => `You have not been invited by faction '${facName}'`);
|
||||
@ -892,10 +881,10 @@ export function NetscriptSingularity(): InternalAPI<ISingularity> {
|
||||
(ctx) =>
|
||||
(_facName, _type, _focus = true) => {
|
||||
helpers.checkSingularityAccess(ctx);
|
||||
const facName = helpers.string(ctx, "facName", _facName);
|
||||
const facName = getEnumHelper("FactionName").nsGetMember(ctx, _facName);
|
||||
const type = helpers.string(ctx, "type", _type);
|
||||
const focus = !!_focus;
|
||||
const faction = getFaction(ctx, facName);
|
||||
const faction = Factions[facName];
|
||||
|
||||
// if the player is in a gang and the target faction is any of the gang faction, fail
|
||||
if (Player.gang && faction.name === Player.getGangFaction().name) {
|
||||
@ -987,27 +976,27 @@ export function NetscriptSingularity(): InternalAPI<ISingularity> {
|
||||
},
|
||||
getFactionRep: (ctx) => (_facName) => {
|
||||
helpers.checkSingularityAccess(ctx);
|
||||
const facName = helpers.string(ctx, "facName", _facName);
|
||||
const faction = getFaction(ctx, facName);
|
||||
const facName = getEnumHelper("FactionName").nsGetMember(ctx, _facName);
|
||||
const faction = Factions[facName];
|
||||
return faction.playerReputation;
|
||||
},
|
||||
getFactionFavor: (ctx) => (_facName) => {
|
||||
helpers.checkSingularityAccess(ctx);
|
||||
const facName = helpers.string(ctx, "facName", _facName);
|
||||
const faction = getFaction(ctx, facName);
|
||||
const facName = getEnumHelper("FactionName").nsGetMember(ctx, _facName);
|
||||
const faction = Factions[facName];
|
||||
return faction.favor;
|
||||
},
|
||||
getFactionFavorGain: (ctx) => (_facName) => {
|
||||
helpers.checkSingularityAccess(ctx);
|
||||
const facName = helpers.string(ctx, "facName", _facName);
|
||||
const faction = getFaction(ctx, facName);
|
||||
const facName = getEnumHelper("FactionName").nsGetMember(ctx, _facName);
|
||||
const faction = Factions[facName];
|
||||
return faction.getFavorGain();
|
||||
},
|
||||
donateToFaction: (ctx) => (_facName, _amt) => {
|
||||
helpers.checkSingularityAccess(ctx);
|
||||
const facName = helpers.string(ctx, "facName", _facName);
|
||||
const facName = getEnumHelper("FactionName").nsGetMember(ctx, _facName);
|
||||
const amt = helpers.number(ctx, "amt", _amt);
|
||||
const faction = getFaction(ctx, facName);
|
||||
const faction = Factions[facName];
|
||||
if (!Player.factions.includes(faction.name)) {
|
||||
helpers.log(ctx, () => `You can't donate to '${facName}' because you aren't a member`);
|
||||
return false;
|
||||
|
@ -17,7 +17,7 @@ import * as serverMethods from "./PlayerObjectServerMethods";
|
||||
import * as workMethods from "./PlayerObjectWorkMethods";
|
||||
|
||||
import { setPlayer } from "../../Player";
|
||||
import { LocationName } from "@enums";
|
||||
import { FactionName, LocationName } from "@enums";
|
||||
import { HashManager } from "../../Hacknet/HashManager";
|
||||
import { MoneySourceTracker } from "../../utils/MoneySourceTracker";
|
||||
import { constructorsForReviver, Generic_toJSON, Generic_fromJSON, IReviverValue } from "../../utils/JSONReviver";
|
||||
@ -35,8 +35,8 @@ export class PlayerObject extends Person implements IPlayer {
|
||||
gang: Gang | null = null;
|
||||
bladeburner: Bladeburner | null = null;
|
||||
currentServer = "";
|
||||
factions: string[] = [];
|
||||
factionInvitations: string[] = [];
|
||||
factions: FactionName[] = [];
|
||||
factionInvitations: FactionName[] = [];
|
||||
hacknetNodes: (HacknetNode | string)[] = []; // HacknetNode object or hostname of Hacknet Server
|
||||
has4SData = false;
|
||||
has4SDataTixApi = false;
|
||||
|
@ -1,11 +1,12 @@
|
||||
import type { PlayerObject } from "./PlayerObject";
|
||||
import type { FactionName } from "@enums";
|
||||
import type { Faction } from "../../Faction/Faction";
|
||||
|
||||
import { Factions } from "../../Faction/Factions";
|
||||
import { Faction } from "../../Faction/Faction";
|
||||
import { Gang } from "../../Gang/Gang";
|
||||
import { GangConstants } from "../../Gang/data/Constants";
|
||||
import { isFactionWork } from "../../Work/FactionWork";
|
||||
|
||||
import type { PlayerObject } from "./PlayerObject";
|
||||
|
||||
export function canAccessGang(this: PlayerObject): boolean {
|
||||
if (this.bitNodeN === 2) {
|
||||
return true;
|
||||
@ -36,12 +37,12 @@ export function getGangName(this: PlayerObject): string {
|
||||
return gang ? gang.facName : "";
|
||||
}
|
||||
|
||||
export function hasGangWith(this: PlayerObject, facName: string): boolean {
|
||||
export function hasGangWith(this: PlayerObject, facName: FactionName): boolean {
|
||||
const gang = this.gang;
|
||||
return gang ? gang.facName === facName : false;
|
||||
}
|
||||
|
||||
export function startGang(this: PlayerObject, factionName: string, hacking: boolean): void {
|
||||
export function startGang(this: PlayerObject, factionName: FactionName, hacking: boolean): void {
|
||||
// isFactionWork handles null internally, finishWork might need to be run with true
|
||||
if (isFactionWork(this.currentWork) && this.currentWork.factionName === factionName) this.finishWork(false);
|
||||
|
||||
|
@ -158,7 +158,7 @@ export function prestigeSourceFile(this: PlayerObject): void {
|
||||
this.augmentations = [];
|
||||
}
|
||||
|
||||
export function receiveInvite(this: PlayerObject, factionName: string): void {
|
||||
export function receiveInvite(this: PlayerObject, factionName: FactionName): void {
|
||||
if (this.factionInvitations.includes(factionName) || this.factions.includes(factionName)) {
|
||||
return;
|
||||
}
|
||||
@ -1099,34 +1099,34 @@ export function gainCodingContractReward(
|
||||
reward: ICodingContractReward | null,
|
||||
difficulty = 1,
|
||||
): string {
|
||||
if (reward == null || reward.type == null) {
|
||||
return `No reward for this contract`;
|
||||
}
|
||||
if (!reward) return `No reward for this contract`;
|
||||
|
||||
/* eslint-disable no-case-declarations */
|
||||
switch (reward.type) {
|
||||
case CodingContractRewardType.FactionReputation:
|
||||
if (reward.name == null || !Factions[reward.name]) {
|
||||
// If no/invalid faction was designated, just give rewards to all factions
|
||||
reward.type = CodingContractRewardType.FactionReputationAll;
|
||||
return this.gainCodingContractReward(reward);
|
||||
case CodingContractRewardType.FactionReputation: {
|
||||
if (!Factions[reward.name]) {
|
||||
return this.gainCodingContractReward({ type: CodingContractRewardType.FactionReputationAll });
|
||||
}
|
||||
const repGain = CONSTANTS.CodingContractBaseFactionRepGain * difficulty;
|
||||
Factions[reward.name].playerReputation += repGain;
|
||||
return `Gained ${repGain} faction reputation for ${reward.name}`;
|
||||
case CodingContractRewardType.FactionReputationAll:
|
||||
}
|
||||
case CodingContractRewardType.FactionReputationAll: {
|
||||
const totalGain = CONSTANTS.CodingContractBaseFactionRepGain * difficulty;
|
||||
|
||||
// Ignore Bladeburners and other special factions for this calculation
|
||||
const specialFactions = [FactionName.Bladeburners as string];
|
||||
const specialFactions = [
|
||||
FactionName.Bladeburners,
|
||||
FactionName.ShadowsOfAnarchy,
|
||||
FactionName.ChurchOfTheMachineGod,
|
||||
];
|
||||
const factions = this.factions.slice().filter((f) => {
|
||||
return !specialFactions.includes(f);
|
||||
});
|
||||
|
||||
// If the player was only part of the special factions, we'll just give money
|
||||
if (factions.length == 0) {
|
||||
reward.type = CodingContractRewardType.Money;
|
||||
return this.gainCodingContractReward(reward, difficulty);
|
||||
return this.gainCodingContractReward({ type: CodingContractRewardType.Money }, difficulty);
|
||||
}
|
||||
|
||||
const gainPerFaction = Math.floor(totalGain / factions.length);
|
||||
@ -1135,11 +1135,11 @@ export function gainCodingContractReward(
|
||||
Factions[facName].playerReputation += gainPerFaction;
|
||||
}
|
||||
return `Gained ${gainPerFaction} reputation for each of the following factions: ${factions.join(", ")}`;
|
||||
}
|
||||
case CodingContractRewardType.CompanyReputation: {
|
||||
if (reward.name == null || !Companies[reward.name]) {
|
||||
if (!Companies[reward.name]) {
|
||||
//If no/invalid company was designated, just give rewards to all factions
|
||||
reward.type = CodingContractRewardType.FactionReputationAll;
|
||||
return this.gainCodingContractReward(reward);
|
||||
return this.gainCodingContractReward({ type: CodingContractRewardType.FactionReputationAll });
|
||||
}
|
||||
const repGain = CONSTANTS.CodingContractBaseCompanyRepGain * difficulty;
|
||||
Companies[reward.name].playerReputation += repGain;
|
||||
|
@ -292,38 +292,31 @@ export class Sleeve extends Person implements SleevePerson {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Start work for one of the player's factions
|
||||
* Returns boolean indicating success
|
||||
*/
|
||||
workForFaction(factionName: string, workType: string): boolean {
|
||||
/** TODO 2.4: Make this take in type correct data */
|
||||
workForFaction(_factionName: string, _workType: string): boolean {
|
||||
const factionName = getEnumHelper("FactionName").fuzzyGetMember(_factionName);
|
||||
if (!factionName) return false;
|
||||
const faction = Factions[factionName];
|
||||
if (factionName === "" || !faction || !Player.factions.includes(factionName)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const workType = getEnumHelper("FactionWorkType").fuzzyGetMember(_workType);
|
||||
if (!workType) return false;
|
||||
const factionInfo = faction.getInfo();
|
||||
|
||||
// Set type of work (hacking/field/security), and the experience gains
|
||||
const sanitizedWorkType = workType.toLowerCase();
|
||||
let factionWorkType: FactionWorkType;
|
||||
if (sanitizedWorkType.includes("hack")) {
|
||||
if (!factionInfo.offerHackingWork) return false;
|
||||
factionWorkType = FactionWorkType.hacking;
|
||||
} else if (sanitizedWorkType.includes("field")) {
|
||||
if (!factionInfo.offerFieldWork) return false;
|
||||
factionWorkType = FactionWorkType.field;
|
||||
} else if (sanitizedWorkType.includes("security")) {
|
||||
if (!factionInfo.offerSecurityWork) return false;
|
||||
factionWorkType = FactionWorkType.security;
|
||||
} else {
|
||||
return false;
|
||||
switch (workType) {
|
||||
case FactionWorkType.field:
|
||||
if (!factionInfo.offerFieldWork) return false;
|
||||
break;
|
||||
case FactionWorkType.hacking:
|
||||
if (!factionInfo.offerHackingWork) return false;
|
||||
break;
|
||||
case FactionWorkType.security:
|
||||
if (!factionInfo.offerSecurityWork) return false;
|
||||
break;
|
||||
}
|
||||
|
||||
this.startWork(
|
||||
new SleeveFactionWork({
|
||||
factionWorkType: factionWorkType,
|
||||
factionName: faction.name,
|
||||
factionWorkType: workType,
|
||||
factionName: factionName,
|
||||
}),
|
||||
);
|
||||
|
||||
|
@ -7,11 +7,11 @@ import { Factions } from "../../../Faction/Factions";
|
||||
import { calculateFactionExp, calculateFactionRep } from "../../../Work/Formulas";
|
||||
import { Faction } from "../../../Faction/Faction";
|
||||
import { scaleWorkStats, WorkStats } from "../../../Work/WorkStats";
|
||||
import { findEnumMember } from "../../../utils/helpers/enum";
|
||||
import { getEnumHelper } from "../../../utils/EnumHelper";
|
||||
|
||||
interface SleeveFactionWorkParams {
|
||||
factionWorkType: FactionWorkType;
|
||||
factionName: string;
|
||||
factionName: FactionName;
|
||||
}
|
||||
|
||||
export const isSleeveFactionWork = (w: SleeveWorkClass | null): w is SleeveFactionWork =>
|
||||
@ -20,7 +20,7 @@ export const isSleeveFactionWork = (w: SleeveWorkClass | null): w is SleeveFacti
|
||||
export class SleeveFactionWork extends SleeveWorkClass {
|
||||
type: SleeveWorkType.FACTION = SleeveWorkType.FACTION;
|
||||
factionWorkType: FactionWorkType;
|
||||
factionName: string;
|
||||
factionName: FactionName;
|
||||
|
||||
constructor(params?: SleeveFactionWorkParams) {
|
||||
super();
|
||||
@ -67,8 +67,8 @@ export class SleeveFactionWork extends SleeveWorkClass {
|
||||
/** Initializes a FactionWork object from a JSON save state. */
|
||||
static fromJSON(value: IReviverValue): SleeveFactionWork {
|
||||
const factionWork = Generic_fromJSON(SleeveFactionWork, value.data);
|
||||
factionWork.factionWorkType =
|
||||
findEnumMember(FactionWorkType, factionWork.factionWorkType) ?? FactionWorkType.hacking;
|
||||
factionWork.factionWorkType = getEnumHelper("FactionWorkType").fuzzyGetMember(factionWork.factionWorkType, true);
|
||||
factionWork.factionName = getEnumHelper("FactionName").fuzzyGetMember(factionWork.factionName, true);
|
||||
return factionWork;
|
||||
}
|
||||
}
|
||||
|
@ -137,10 +137,9 @@ const tasks: {
|
||||
|
||||
return {
|
||||
first: factions,
|
||||
second: (s1: string) => {
|
||||
second: (s1) => {
|
||||
if (!getEnumHelper("FactionName").isMember(s1)) return ["------"];
|
||||
const faction = Factions[s1];
|
||||
if (!faction) return ["------"];
|
||||
|
||||
const facInfo = faction.getInfo();
|
||||
const options: string[] = [];
|
||||
if (facInfo.offerHackingWork) {
|
||||
|
@ -2,7 +2,7 @@ import { AugmentationName, CityName, CompletedProgramName, FactionName, Literatu
|
||||
import { initBitNodeMultipliers } from "./BitNode/BitNode";
|
||||
import { Companies, initCompanies } from "./Company/Companies";
|
||||
import { resetIndustryResearchTrees } from "./Corporation/data/IndustryData";
|
||||
import { Factions, initFactions } from "./Faction/Factions";
|
||||
import { Factions } from "./Faction/Factions";
|
||||
import { joinFaction } from "./Faction/FactionHelpers";
|
||||
import { updateHashManagerCapacity } from "./Hacknet/HacknetHelpers";
|
||||
import { prestigeWorkerScripts } from "./NetscriptWorker";
|
||||
@ -23,6 +23,7 @@ import { ProgramsSeen } from "./Programs/ui/ProgramsRoot";
|
||||
import { InvitationsSeen } from "./Faction/ui/FactionsRoot";
|
||||
import { CONSTANTS } from "./Constants";
|
||||
import { LogBoxClearEvents } from "./ui/React/LogBoxManager";
|
||||
import { initCircadianModulator } from "./Augmentation/Augmentations";
|
||||
|
||||
const BitNode8StartingMoney = 250e6;
|
||||
function delayedDialog(message: string) {
|
||||
@ -71,7 +72,7 @@ export function prestigeAugmentation(): void {
|
||||
|
||||
// Gain favor for Companies and Factions
|
||||
for (const company of Object.values(Companies)) company.gainFavor();
|
||||
for (const faction of Object.values(Factions)) faction.gainFavor();
|
||||
for (const faction of Object.values(Factions)) faction.prestigeAugmentation();
|
||||
|
||||
// Stop a Terminal action if there is one.
|
||||
if (Terminal.action !== null) {
|
||||
@ -80,10 +81,11 @@ export function prestigeAugmentation(): void {
|
||||
Terminal.clear();
|
||||
LogBoxClearEvents.emit();
|
||||
|
||||
// Re-initialize things - This will update any changes
|
||||
initFactions(); // Factions must be initialized before augmentations
|
||||
// Recalculate the bonus for circadian modulator aug
|
||||
initCircadianModulator();
|
||||
|
||||
Player.factionInvitations = Player.factionInvitations.concat(maintainMembership);
|
||||
for (const factionName of maintainMembership) Factions[factionName].alreadyInvited = true;
|
||||
Player.reapplyAllAugmentations();
|
||||
Player.reapplyAllSourceFiles();
|
||||
Player.hp.current = Player.hp.max;
|
||||
@ -193,7 +195,7 @@ export function prestigeSourceFile(isFlume: boolean): void {
|
||||
|
||||
// Reset favor for Companies and Factions
|
||||
for (const company of Object.values(Companies)) company.favor = 0;
|
||||
for (const faction of Object.values(Factions)) faction.favor = 0;
|
||||
for (const faction of Object.values(Factions)) faction.prestigeSourceFile();
|
||||
|
||||
// Stop a Terminal action if there is one
|
||||
if (Terminal.action !== null) {
|
||||
@ -208,8 +210,8 @@ export function prestigeSourceFile(isFlume: boolean): void {
|
||||
});
|
||||
}
|
||||
|
||||
// Re-initialize things - This will update any changes
|
||||
initFactions(); // Factions must be initialized before augmentations
|
||||
initCircadianModulator();
|
||||
|
||||
Player.reapplyAllAugmentations();
|
||||
Player.reapplyAllSourceFiles();
|
||||
initCompanies();
|
||||
|
@ -1,28 +1,29 @@
|
||||
import type { Faction } from "../Faction/Faction";
|
||||
|
||||
import React from "react";
|
||||
import { Work, WorkType } from "./Work";
|
||||
import { constructorsForReviver, Generic_toJSON, Generic_fromJSON, IReviverValue } from "../utils/JSONReviver";
|
||||
import { Player } from "@player";
|
||||
import { AugmentationName, FactionName, FactionWorkType } from "@enums";
|
||||
import { Factions } from "../Faction/Factions";
|
||||
import { Faction } from "../Faction/Faction";
|
||||
import { applyWorkStats, scaleWorkStats, WorkStats } from "./WorkStats";
|
||||
import { dialogBoxCreate } from "../ui/React/DialogBox";
|
||||
import { Reputation } from "../ui/React/Reputation";
|
||||
import { CONSTANTS } from "../Constants";
|
||||
import { calculateFactionExp, calculateFactionRep } from "./Formulas";
|
||||
import { findEnumMember } from "../utils/helpers/enum";
|
||||
import { getEnumHelper } from "../utils/EnumHelper";
|
||||
|
||||
interface FactionWorkParams {
|
||||
singularity: boolean;
|
||||
factionWorkType: FactionWorkType;
|
||||
faction: string;
|
||||
faction: FactionName;
|
||||
}
|
||||
|
||||
export const isFactionWork = (w: Work | null): w is FactionWork => w !== null && w.type === WorkType.FACTION;
|
||||
|
||||
export class FactionWork extends Work {
|
||||
factionWorkType: FactionWorkType;
|
||||
factionName: string;
|
||||
factionName: FactionName;
|
||||
|
||||
constructor(params?: FactionWorkParams) {
|
||||
super(WorkType.FACTION, params?.singularity ?? true);
|
||||
@ -31,9 +32,7 @@ export class FactionWork extends Work {
|
||||
}
|
||||
|
||||
getFaction(): Faction {
|
||||
const f = Factions[this.factionName];
|
||||
if (!f) throw new Error(`Faction work started with invalid / unknown faction: '${this.factionName}'`);
|
||||
return f;
|
||||
return Factions[this.factionName];
|
||||
}
|
||||
|
||||
getReputationRate(): number {
|
||||
@ -92,8 +91,8 @@ export class FactionWork extends Work {
|
||||
/** Initializes a FactionWork object from a JSON save state. */
|
||||
static fromJSON(value: IReviverValue): FactionWork {
|
||||
const factionWork = Generic_fromJSON(FactionWork, value.data);
|
||||
factionWork.factionWorkType =
|
||||
findEnumMember(FactionWorkType, factionWork.factionWorkType) ?? FactionWorkType.hacking;
|
||||
factionWork.factionWorkType = getEnumHelper("FactionWorkType").fuzzyGetMember(factionWork.factionWorkType, true);
|
||||
factionWork.factionName = getEnumHelper("FactionName").fuzzyGetMember(factionWork.factionName, true);
|
||||
return factionWork;
|
||||
}
|
||||
}
|
||||
|
@ -5,7 +5,7 @@ import { initSourceFiles } from "./SourceFile/SourceFiles";
|
||||
import { generateRandomContract } from "./CodingContractGenerator";
|
||||
import { initCompanies } from "./Company/Companies";
|
||||
import { CONSTANTS } from "./Constants";
|
||||
import { Factions, initFactions } from "./Faction/Factions";
|
||||
import { Factions } from "./Faction/Factions";
|
||||
import { staneksGift } from "./CotMG/Helper";
|
||||
import { processPassiveFactionRepGain, inviteToFaction } from "./Faction/FactionHelpers";
|
||||
import { Router } from "./ui/GameRoot";
|
||||
@ -375,7 +375,6 @@ const Engine: {
|
||||
Player.init();
|
||||
initForeignServers(Player.getHomeComputer());
|
||||
initCompanies();
|
||||
initFactions();
|
||||
Player.reapplyAllAugmentations();
|
||||
|
||||
// Start interactive tutorial
|
||||
|
@ -1,4 +1,6 @@
|
||||
/* Generic Reviver, toJSON, and fromJSON functions used for saving and loading objects */
|
||||
import type { Unknownify } from "../types";
|
||||
|
||||
import { ObjectValidator, validateObject } from "./Validator";
|
||||
import { JSONMap, JSONSet } from "../Types/Jsonable";
|
||||
|
||||
@ -102,3 +104,7 @@ export function Generic_fromJSON<T extends Record<string, any>>(
|
||||
for (const [key, val] of Object.entries(data) as [keyof T, T[keyof T]][]) obj[key] = val;
|
||||
return obj;
|
||||
}
|
||||
|
||||
// This function is empty because Unknownify<T> is a typesafe assertion on any object with no runtime checks needed.
|
||||
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
||||
export function assertLoadingType<T extends object>(val: object): asserts val is Unknownify<T> {}
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { saveObject } from "../../src/SaveObject";
|
||||
import { Factions, initFactions } from "../../src/Faction/Factions";
|
||||
import { Factions } from "../../src/Faction/Factions";
|
||||
import { Player, setPlayer } from "../../src/Player";
|
||||
import { PlayerObject } from "../../src/PersonObjects/Player/PlayerObject";
|
||||
import { joinFaction } from "../../src/Faction/FactionHelpers";
|
||||
@ -33,7 +33,6 @@ function establishInitialConditions() {
|
||||
setPlayer(new PlayerObject());
|
||||
Player.init();
|
||||
Player.identifier = "Overwritten identifier";
|
||||
initFactions();
|
||||
Player.sleevesFromCovenant = 1;
|
||||
Player.sourceFiles.set(10, 1);
|
||||
Player.prestigeAugmentation();
|
||||
|
@ -6,19 +6,9 @@ exports[`Check Save File Continuity FactionsSave continuity 1`] = `
|
||||
"ctor": "Faction",
|
||||
"data": {
|
||||
"alreadyInvited": false,
|
||||
"augmentations": [
|
||||
"Wired Reflexes",
|
||||
"Speech Processor Implant",
|
||||
"Synaptic Enhancement Implant",
|
||||
"Neuralstimulator",
|
||||
"PCMatrix",
|
||||
"NeuroFlux Governor",
|
||||
"Neurotrainer I",
|
||||
],
|
||||
"favor": 0,
|
||||
"isBanned": false,
|
||||
"isMember": false,
|
||||
"name": "Aevum",
|
||||
"playerReputation": 0,
|
||||
},
|
||||
},
|
||||
@ -26,20 +16,9 @@ exports[`Check Save File Continuity FactionsSave continuity 1`] = `
|
||||
"ctor": "Faction",
|
||||
"data": {
|
||||
"alreadyInvited": false,
|
||||
"augmentations": [
|
||||
"Enhanced Social Interaction Implant",
|
||||
"Neuralstimulator",
|
||||
"Nuoptimal Nootropic Injector Implant",
|
||||
"Speech Enhancement",
|
||||
"FocusWire",
|
||||
"ADR-V2 Pheromone Gene",
|
||||
"NeuroFlux Governor",
|
||||
"SmartJaw",
|
||||
],
|
||||
"favor": 0,
|
||||
"isBanned": false,
|
||||
"isMember": false,
|
||||
"name": "Bachman & Associates",
|
||||
"playerReputation": 0,
|
||||
},
|
||||
},
|
||||
@ -47,25 +26,9 @@ exports[`Check Save File Continuity FactionsSave continuity 1`] = `
|
||||
"ctor": "Faction",
|
||||
"data": {
|
||||
"alreadyInvited": false,
|
||||
"augmentations": [
|
||||
"Artificial Bio-neural Network Implant",
|
||||
"Enhanced Myelin Sheathing",
|
||||
"DataJack",
|
||||
"Embedded Netburner Module",
|
||||
"Embedded Netburner Module Core Implant",
|
||||
"Embedded Netburner Module Core V2 Upgrade",
|
||||
"Neural Accelerator",
|
||||
"Cranial Signal Processors - Gen III",
|
||||
"Cranial Signal Processors - Gen IV",
|
||||
"Cranial Signal Processors - Gen V",
|
||||
"NeuroFlux Governor",
|
||||
"Neurotrainer II",
|
||||
"BitRunners Neurolink",
|
||||
],
|
||||
"favor": 0,
|
||||
"isBanned": false,
|
||||
"isMember": false,
|
||||
"name": "BitRunners",
|
||||
"playerReputation": 0,
|
||||
},
|
||||
},
|
||||
@ -73,30 +36,9 @@ exports[`Check Save File Continuity FactionsSave continuity 1`] = `
|
||||
"ctor": "Faction",
|
||||
"data": {
|
||||
"alreadyInvited": false,
|
||||
"augmentations": [
|
||||
"Augmented Targeting I",
|
||||
"Augmented Targeting II",
|
||||
"Augmented Targeting III",
|
||||
"Synfibril Muscle",
|
||||
"Combat Rib I",
|
||||
"Combat Rib II",
|
||||
"Combat Rib III",
|
||||
"Nanofiber Weave",
|
||||
"Bionic Spine",
|
||||
"Bionic Legs",
|
||||
"Embedded Netburner Module",
|
||||
"Embedded Netburner Module Core Implant",
|
||||
"Embedded Netburner Module Core V2 Upgrade",
|
||||
"PC Direct-Neural Interface",
|
||||
"PC Direct-Neural Interface Optimization Submodule",
|
||||
"NeuroFlux Governor",
|
||||
"HyperSight Corneal Implant",
|
||||
"Neotra",
|
||||
],
|
||||
"favor": 0,
|
||||
"isBanned": false,
|
||||
"isMember": false,
|
||||
"name": "Blade Industries",
|
||||
"playerReputation": 0,
|
||||
},
|
||||
},
|
||||
@ -104,29 +46,9 @@ exports[`Check Save File Continuity FactionsSave continuity 1`] = `
|
||||
"ctor": "Faction",
|
||||
"data": {
|
||||
"alreadyInvited": false,
|
||||
"augmentations": [
|
||||
"EsperTech Bladeburner Eyewear",
|
||||
"EMS-4 Recombination",
|
||||
"ORION-MKIV Shoulder",
|
||||
"Hyperion Plasma Cannon V1",
|
||||
"Hyperion Plasma Cannon V2",
|
||||
"GOLEM Serum",
|
||||
"Vangelis Virus",
|
||||
"Vangelis Virus 3.0",
|
||||
"I.N.T.E.R.L.I.N.K.E.D",
|
||||
"Blade's Runners",
|
||||
"BLADE-51b Tesla Armor",
|
||||
"BLADE-51b Tesla Armor: Power Cells Upgrade",
|
||||
"BLADE-51b Tesla Armor: Energy Shielding Upgrade",
|
||||
"BLADE-51b Tesla Armor: Unibeam Upgrade",
|
||||
"BLADE-51b Tesla Armor: Omnibeam Upgrade",
|
||||
"BLADE-51b Tesla Armor: IPU Upgrade",
|
||||
"The Blade's Simulacrum",
|
||||
],
|
||||
"favor": 0,
|
||||
"isBanned": false,
|
||||
"isMember": true,
|
||||
"name": "Bladeburners",
|
||||
"playerReputation": 4000,
|
||||
},
|
||||
},
|
||||
@ -134,18 +56,9 @@ exports[`Check Save File Continuity FactionsSave continuity 1`] = `
|
||||
"ctor": "Faction",
|
||||
"data": {
|
||||
"alreadyInvited": false,
|
||||
"augmentations": [
|
||||
"Speech Processor Implant",
|
||||
"DataJack",
|
||||
"Neuralstimulator",
|
||||
"Nuoptimal Nootropic Injector Implant",
|
||||
"NeuroFlux Governor",
|
||||
"Neuregen Gene Modification",
|
||||
],
|
||||
"favor": 0,
|
||||
"isBanned": false,
|
||||
"isMember": false,
|
||||
"name": "Chongqing",
|
||||
"playerReputation": 0,
|
||||
},
|
||||
},
|
||||
@ -153,15 +66,9 @@ exports[`Check Save File Continuity FactionsSave continuity 1`] = `
|
||||
"ctor": "Faction",
|
||||
"data": {
|
||||
"alreadyInvited": false,
|
||||
"augmentations": [
|
||||
"Stanek's Gift - Genesis",
|
||||
"Stanek's Gift - Awakening",
|
||||
"Stanek's Gift - Serenity",
|
||||
],
|
||||
"favor": 0,
|
||||
"isBanned": false,
|
||||
"isMember": false,
|
||||
"name": "Church of the Machine God",
|
||||
"playerReputation": 0,
|
||||
},
|
||||
},
|
||||
@ -169,21 +76,9 @@ exports[`Check Save File Continuity FactionsSave continuity 1`] = `
|
||||
"ctor": "Faction",
|
||||
"data": {
|
||||
"alreadyInvited": false,
|
||||
"augmentations": [
|
||||
"Enhanced Social Interaction Implant",
|
||||
"Neuralstimulator",
|
||||
"Neuronal Densification",
|
||||
"Nuoptimal Nootropic Injector Implant",
|
||||
"Speech Enhancement",
|
||||
"FocusWire",
|
||||
"ADR-V2 Pheromone Gene",
|
||||
"NeuroFlux Governor",
|
||||
"nextSENS Gene Modification",
|
||||
],
|
||||
"favor": 0,
|
||||
"isBanned": false,
|
||||
"isMember": false,
|
||||
"name": "Clarke Incorporated",
|
||||
"playerReputation": 0,
|
||||
},
|
||||
},
|
||||
@ -191,18 +86,9 @@ exports[`Check Save File Continuity FactionsSave continuity 1`] = `
|
||||
"ctor": "Faction",
|
||||
"data": {
|
||||
"alreadyInvited": false,
|
||||
"augmentations": [
|
||||
"BitWire",
|
||||
"Synaptic Enhancement Implant",
|
||||
"Cranial Signal Processors - Gen I",
|
||||
"Cranial Signal Processors - Gen II",
|
||||
"NeuroFlux Governor",
|
||||
"Neurotrainer I",
|
||||
],
|
||||
"favor": 20,
|
||||
"isBanned": false,
|
||||
"isMember": true,
|
||||
"name": "CyberSec",
|
||||
"playerReputation": 1000000,
|
||||
},
|
||||
},
|
||||
@ -210,20 +96,9 @@ exports[`Check Save File Continuity FactionsSave continuity 1`] = `
|
||||
"ctor": "Faction",
|
||||
"data": {
|
||||
"alreadyInvited": false,
|
||||
"augmentations": [
|
||||
"Synthetic Heart",
|
||||
"Synfibril Muscle",
|
||||
"NEMEAN Subdermal Weave",
|
||||
"Embedded Netburner Module Core V3 Upgrade",
|
||||
"Embedded Netburner Module Analyze Engine",
|
||||
"Embedded Netburner Module Direct Memory Access Upgrade",
|
||||
"NeuroFlux Governor",
|
||||
"The Red Pill",
|
||||
],
|
||||
"favor": 0,
|
||||
"isBanned": false,
|
||||
"isMember": false,
|
||||
"name": "Daedalus",
|
||||
"playerReputation": 0,
|
||||
},
|
||||
},
|
||||
@ -231,24 +106,9 @@ exports[`Check Save File Continuity FactionsSave continuity 1`] = `
|
||||
"ctor": "Faction",
|
||||
"data": {
|
||||
"alreadyInvited": false,
|
||||
"augmentations": [
|
||||
"Graphene Bionic Spine Upgrade",
|
||||
"Graphene Bionic Legs Upgrade",
|
||||
"Embedded Netburner Module",
|
||||
"Embedded Netburner Module Core Implant",
|
||||
"Embedded Netburner Module Core V2 Upgrade",
|
||||
"Embedded Netburner Module Core V3 Upgrade",
|
||||
"Embedded Netburner Module Analyze Engine",
|
||||
"Embedded Netburner Module Direct Memory Access Upgrade",
|
||||
"PC Direct-Neural Interface",
|
||||
"PC Direct-Neural Interface Optimization Submodule",
|
||||
"NeuroFlux Governor",
|
||||
"ECorp HVMind Implant",
|
||||
],
|
||||
"favor": 0,
|
||||
"isBanned": false,
|
||||
"isMember": false,
|
||||
"name": "ECorp",
|
||||
"playerReputation": 0,
|
||||
},
|
||||
},
|
||||
@ -256,22 +116,9 @@ exports[`Check Save File Continuity FactionsSave continuity 1`] = `
|
||||
"ctor": "Faction",
|
||||
"data": {
|
||||
"alreadyInvited": false,
|
||||
"augmentations": [
|
||||
"Enhanced Social Interaction Implant",
|
||||
"Neuralstimulator",
|
||||
"Nuoptimal Nootropic Injector Implant",
|
||||
"Speech Enhancement",
|
||||
"FocusWire",
|
||||
"PC Direct-Neural Interface",
|
||||
"ADR-V1 Pheromone Gene",
|
||||
"ADR-V2 Pheromone Gene",
|
||||
"NeuroFlux Governor",
|
||||
"Neurotrainer III",
|
||||
],
|
||||
"favor": 0,
|
||||
"isBanned": false,
|
||||
"isMember": false,
|
||||
"name": "Four Sigma",
|
||||
"playerReputation": 0,
|
||||
},
|
||||
},
|
||||
@ -279,30 +126,9 @@ exports[`Check Save File Continuity FactionsSave continuity 1`] = `
|
||||
"ctor": "Faction",
|
||||
"data": {
|
||||
"alreadyInvited": false,
|
||||
"augmentations": [
|
||||
"Synthetic Heart",
|
||||
"Synfibril Muscle",
|
||||
"Nanofiber Weave",
|
||||
"NEMEAN Subdermal Weave",
|
||||
"Graphene Bone Lacings",
|
||||
"Graphene Bionic Spine Upgrade",
|
||||
"Graphene Bionic Legs Upgrade",
|
||||
"Artificial Bio-neural Network Implant",
|
||||
"Enhanced Myelin Sheathing",
|
||||
"Embedded Netburner Module",
|
||||
"Embedded Netburner Module Core Implant",
|
||||
"Embedded Netburner Module Core V2 Upgrade",
|
||||
"Embedded Netburner Module Core V3 Upgrade",
|
||||
"Embedded Netburner Module Analyze Engine",
|
||||
"Embedded Netburner Module Direct Memory Access Upgrade",
|
||||
"PC Direct-Neural Interface Optimization Submodule",
|
||||
"PC Direct-Neural Interface NeuroNet Injector",
|
||||
"NeuroFlux Governor",
|
||||
],
|
||||
"favor": 0,
|
||||
"isBanned": false,
|
||||
"isMember": false,
|
||||
"name": "Fulcrum Secret Technologies",
|
||||
"playerReputation": 0,
|
||||
},
|
||||
},
|
||||
@ -310,20 +136,9 @@ exports[`Check Save File Continuity FactionsSave continuity 1`] = `
|
||||
"ctor": "Faction",
|
||||
"data": {
|
||||
"alreadyInvited": false,
|
||||
"augmentations": [
|
||||
"Synthetic Heart",
|
||||
"Synfibril Muscle",
|
||||
"NEMEAN Subdermal Weave",
|
||||
"Embedded Netburner Module Core V3 Upgrade",
|
||||
"Embedded Netburner Module Analyze Engine",
|
||||
"Embedded Netburner Module Direct Memory Access Upgrade",
|
||||
"NeuroFlux Governor",
|
||||
"QLink",
|
||||
],
|
||||
"favor": 0,
|
||||
"isBanned": false,
|
||||
"isMember": false,
|
||||
"name": "Illuminati",
|
||||
"playerReputation": 0,
|
||||
},
|
||||
},
|
||||
@ -331,19 +146,9 @@ exports[`Check Save File Continuity FactionsSave continuity 1`] = `
|
||||
"ctor": "Faction",
|
||||
"data": {
|
||||
"alreadyInvited": false,
|
||||
"augmentations": [
|
||||
"Augmented Targeting I",
|
||||
"Combat Rib I",
|
||||
"Wired Reflexes",
|
||||
"Speech Processor Implant",
|
||||
"Neuralstimulator",
|
||||
"NeuroFlux Governor",
|
||||
"INFRARET Enhancement",
|
||||
],
|
||||
"favor": 0,
|
||||
"isBanned": false,
|
||||
"isMember": false,
|
||||
"name": "Ishima",
|
||||
"playerReputation": 0,
|
||||
},
|
||||
},
|
||||
@ -351,28 +156,9 @@ exports[`Check Save File Continuity FactionsSave continuity 1`] = `
|
||||
"ctor": "Faction",
|
||||
"data": {
|
||||
"alreadyInvited": false,
|
||||
"augmentations": [
|
||||
"Augmented Targeting I",
|
||||
"Augmented Targeting II",
|
||||
"Augmented Targeting III",
|
||||
"Synthetic Heart",
|
||||
"Synfibril Muscle",
|
||||
"Combat Rib I",
|
||||
"Combat Rib II",
|
||||
"Combat Rib III",
|
||||
"Bionic Spine",
|
||||
"Bionic Legs",
|
||||
"Embedded Netburner Module Core V2 Upgrade",
|
||||
"Speech Enhancement",
|
||||
"FocusWire",
|
||||
"NeuroFlux Governor",
|
||||
"HyperSight Corneal Implant",
|
||||
"Photosynthetic Cells",
|
||||
],
|
||||
"favor": 0,
|
||||
"isBanned": false,
|
||||
"isMember": false,
|
||||
"name": "KuaiGong International",
|
||||
"playerReputation": 0,
|
||||
},
|
||||
},
|
||||
@ -380,22 +166,9 @@ exports[`Check Save File Continuity FactionsSave continuity 1`] = `
|
||||
"ctor": "Faction",
|
||||
"data": {
|
||||
"alreadyInvited": false,
|
||||
"augmentations": [
|
||||
"Graphene Bionic Legs Upgrade",
|
||||
"Embedded Netburner Module",
|
||||
"Embedded Netburner Module Core Implant",
|
||||
"Embedded Netburner Module Core V2 Upgrade",
|
||||
"Embedded Netburner Module Core V3 Upgrade",
|
||||
"Embedded Netburner Module Analyze Engine",
|
||||
"Embedded Netburner Module Direct Memory Access Upgrade",
|
||||
"ADR-V1 Pheromone Gene",
|
||||
"NeuroFlux Governor",
|
||||
"CordiARC Fusion Reactor",
|
||||
],
|
||||
"favor": 0,
|
||||
"isBanned": false,
|
||||
"isMember": false,
|
||||
"name": "MegaCorp",
|
||||
"playerReputation": 0,
|
||||
},
|
||||
},
|
||||
@ -403,27 +176,9 @@ exports[`Check Save File Continuity FactionsSave continuity 1`] = `
|
||||
"ctor": "Faction",
|
||||
"data": {
|
||||
"alreadyInvited": false,
|
||||
"augmentations": [
|
||||
"Synthetic Heart",
|
||||
"Synfibril Muscle",
|
||||
"Enhanced Social Interaction Implant",
|
||||
"Embedded Netburner Module",
|
||||
"Embedded Netburner Module Core Implant",
|
||||
"Embedded Netburner Module Core V2 Upgrade",
|
||||
"Embedded Netburner Module Core V3 Upgrade",
|
||||
"Embedded Netburner Module Analyze Engine",
|
||||
"Embedded Netburner Module Direct Memory Access Upgrade",
|
||||
"ADR-V1 Pheromone Gene",
|
||||
"NeuroFlux Governor",
|
||||
"Neurotrainer III",
|
||||
"Power Recirculation Core",
|
||||
"Xanipher",
|
||||
"Hydroflame Left Arm",
|
||||
],
|
||||
"favor": 0,
|
||||
"isBanned": false,
|
||||
"isMember": false,
|
||||
"name": "NWO",
|
||||
"playerReputation": 0,
|
||||
},
|
||||
},
|
||||
@ -431,18 +186,9 @@ exports[`Check Save File Continuity FactionsSave continuity 1`] = `
|
||||
"ctor": "Faction",
|
||||
"data": {
|
||||
"alreadyInvited": false,
|
||||
"augmentations": [
|
||||
"Hacknet Node CPU Architecture Neural-Upload",
|
||||
"Hacknet Node Cache Architecture Neural-Upload",
|
||||
"Hacknet Node NIC Architecture Neural-Upload",
|
||||
"Hacknet Node Kernel Direct-Neural Interface",
|
||||
"Hacknet Node Core Direct-Neural Interface",
|
||||
"NeuroFlux Governor",
|
||||
],
|
||||
"favor": 0,
|
||||
"isBanned": false,
|
||||
"isMember": false,
|
||||
"name": "Netburners",
|
||||
"playerReputation": 0,
|
||||
},
|
||||
},
|
||||
@ -450,18 +196,9 @@ exports[`Check Save File Continuity FactionsSave continuity 1`] = `
|
||||
"ctor": "Faction",
|
||||
"data": {
|
||||
"alreadyInvited": false,
|
||||
"augmentations": [
|
||||
"Speech Processor Implant",
|
||||
"DataJack",
|
||||
"Neuralstimulator",
|
||||
"Nuoptimal Nootropic Injector Implant",
|
||||
"NeuroFlux Governor",
|
||||
"NutriGen Implant",
|
||||
],
|
||||
"favor": 0,
|
||||
"isBanned": false,
|
||||
"isMember": false,
|
||||
"name": "New Tokyo",
|
||||
"playerReputation": 0,
|
||||
},
|
||||
},
|
||||
@ -469,23 +206,9 @@ exports[`Check Save File Continuity FactionsSave continuity 1`] = `
|
||||
"ctor": "Faction",
|
||||
"data": {
|
||||
"alreadyInvited": false,
|
||||
"augmentations": [
|
||||
"BitWire",
|
||||
"Artificial Synaptic Potentiation",
|
||||
"Neural-Retention Enhancement",
|
||||
"DataJack",
|
||||
"Embedded Netburner Module",
|
||||
"Cranial Signal Processors - Gen I",
|
||||
"Cranial Signal Processors - Gen II",
|
||||
"Cranial Signal Processors - Gen III",
|
||||
"NeuroFlux Governor",
|
||||
"Neurotrainer II",
|
||||
"CRTX42-AA Gene Modification",
|
||||
],
|
||||
"favor": 0,
|
||||
"isBanned": false,
|
||||
"isMember": false,
|
||||
"name": "NiteSec",
|
||||
"playerReputation": 0,
|
||||
},
|
||||
},
|
||||
@ -493,26 +216,9 @@ exports[`Check Save File Continuity FactionsSave continuity 1`] = `
|
||||
"ctor": "Faction",
|
||||
"data": {
|
||||
"alreadyInvited": false,
|
||||
"augmentations": [
|
||||
"Augmented Targeting I",
|
||||
"Augmented Targeting II",
|
||||
"Augmented Targeting III",
|
||||
"Combat Rib I",
|
||||
"Combat Rib II",
|
||||
"Combat Rib III",
|
||||
"Nanofiber Weave",
|
||||
"Bionic Spine",
|
||||
"Bionic Legs",
|
||||
"Enhanced Social Interaction Implant",
|
||||
"Embedded Netburner Module Core V2 Upgrade",
|
||||
"PC Direct-Neural Interface",
|
||||
"NeuroFlux Governor",
|
||||
"OmniTek InfoLoad",
|
||||
],
|
||||
"favor": 0,
|
||||
"isBanned": false,
|
||||
"isMember": false,
|
||||
"name": "OmniTek Incorporated",
|
||||
"playerReputation": 0,
|
||||
},
|
||||
},
|
||||
@ -520,19 +226,9 @@ exports[`Check Save File Continuity FactionsSave continuity 1`] = `
|
||||
"ctor": "Faction",
|
||||
"data": {
|
||||
"alreadyInvited": false,
|
||||
"augmentations": [
|
||||
"Augmented Targeting I",
|
||||
"Augmented Targeting II",
|
||||
"Wired Reflexes",
|
||||
"Speech Processor Implant",
|
||||
"Neuralstimulator",
|
||||
"NeuroFlux Governor",
|
||||
"CashRoot Starter Kit",
|
||||
],
|
||||
"favor": 0,
|
||||
"isBanned": false,
|
||||
"isMember": false,
|
||||
"name": "Sector-12",
|
||||
"playerReputation": 0,
|
||||
},
|
||||
},
|
||||
@ -540,21 +236,9 @@ exports[`Check Save File Continuity FactionsSave continuity 1`] = `
|
||||
"ctor": "Faction",
|
||||
"data": {
|
||||
"alreadyInvited": false,
|
||||
"augmentations": [
|
||||
"SoA - Might of Ares",
|
||||
"SoA - Wisdom of Athena",
|
||||
"SoA - Trickery of Hermes",
|
||||
"SoA - Beauty of Aphrodite",
|
||||
"SoA - Chaos of Dionysus",
|
||||
"SoA - Flood of Poseidon",
|
||||
"SoA - Hunt of Artemis",
|
||||
"SoA - Knowledge of Apollo",
|
||||
"SoA - phyzical WKS harmonizer",
|
||||
],
|
||||
"favor": 0,
|
||||
"isBanned": false,
|
||||
"isMember": false,
|
||||
"name": "Shadows of Anarchy",
|
||||
"playerReputation": 0,
|
||||
},
|
||||
},
|
||||
@ -562,16 +246,9 @@ exports[`Check Save File Continuity FactionsSave continuity 1`] = `
|
||||
"ctor": "Faction",
|
||||
"data": {
|
||||
"alreadyInvited": false,
|
||||
"augmentations": [
|
||||
"Speech Processor Implant",
|
||||
"TITN-41 Gene-Modification Injection",
|
||||
"ADR-V2 Pheromone Gene",
|
||||
"NeuroFlux Governor",
|
||||
],
|
||||
"favor": 0,
|
||||
"isBanned": false,
|
||||
"isMember": false,
|
||||
"name": "Silhouette",
|
||||
"playerReputation": 0,
|
||||
},
|
||||
},
|
||||
@ -579,19 +256,9 @@ exports[`Check Save File Continuity FactionsSave continuity 1`] = `
|
||||
"ctor": "Faction",
|
||||
"data": {
|
||||
"alreadyInvited": false,
|
||||
"augmentations": [
|
||||
"Augmented Targeting I",
|
||||
"Combat Rib I",
|
||||
"Wired Reflexes",
|
||||
"NeuroFlux Governor",
|
||||
"LuminCloaking-V1 Skin Implant",
|
||||
"LuminCloaking-V2 Skin Implant",
|
||||
"SmartSonar Implant",
|
||||
],
|
||||
"favor": 0,
|
||||
"isBanned": false,
|
||||
"isMember": true,
|
||||
"name": "Slum Snakes",
|
||||
"playerReputation": 0,
|
||||
},
|
||||
},
|
||||
@ -599,23 +266,9 @@ exports[`Check Save File Continuity FactionsSave continuity 1`] = `
|
||||
"ctor": "Faction",
|
||||
"data": {
|
||||
"alreadyInvited": false,
|
||||
"augmentations": [
|
||||
"Synthetic Heart",
|
||||
"Synfibril Muscle",
|
||||
"Nanofiber Weave",
|
||||
"Wired Reflexes",
|
||||
"Bionic Spine",
|
||||
"Bionic Legs",
|
||||
"Speech Enhancement",
|
||||
"The Shadow's Simulacrum",
|
||||
"NeuroFlux Governor",
|
||||
"Unstable Circadian Modulator",
|
||||
"Graphene BrachiBlades Upgrade",
|
||||
],
|
||||
"favor": 0,
|
||||
"isBanned": false,
|
||||
"isMember": false,
|
||||
"name": "Speakers for the Dead",
|
||||
"playerReputation": 0,
|
||||
},
|
||||
},
|
||||
@ -623,18 +276,9 @@ exports[`Check Save File Continuity FactionsSave continuity 1`] = `
|
||||
"ctor": "Faction",
|
||||
"data": {
|
||||
"alreadyInvited": false,
|
||||
"augmentations": [
|
||||
"NeuroFlux Governor",
|
||||
"LuminCloaking-V1 Skin Implant",
|
||||
"LuminCloaking-V2 Skin Implant",
|
||||
"HemoRecirculator",
|
||||
"Power Recirculation Core",
|
||||
"Bionic Arms",
|
||||
],
|
||||
"favor": 0,
|
||||
"isBanned": false,
|
||||
"isMember": false,
|
||||
"name": "Tetrads",
|
||||
"playerReputation": 0,
|
||||
},
|
||||
},
|
||||
@ -642,22 +286,9 @@ exports[`Check Save File Continuity FactionsSave continuity 1`] = `
|
||||
"ctor": "Faction",
|
||||
"data": {
|
||||
"alreadyInvited": false,
|
||||
"augmentations": [
|
||||
"Artificial Synaptic Potentiation",
|
||||
"Enhanced Myelin Sheathing",
|
||||
"DataJack",
|
||||
"Embedded Netburner Module",
|
||||
"Embedded Netburner Module Core Implant",
|
||||
"Neuralstimulator",
|
||||
"Cranial Signal Processors - Gen III",
|
||||
"Cranial Signal Processors - Gen IV",
|
||||
"NeuroFlux Governor",
|
||||
"The Black Hand",
|
||||
],
|
||||
"favor": 0,
|
||||
"isBanned": false,
|
||||
"isMember": false,
|
||||
"name": "The Black Hand",
|
||||
"playerReputation": 0,
|
||||
},
|
||||
},
|
||||
@ -665,23 +296,9 @@ exports[`Check Save File Continuity FactionsSave continuity 1`] = `
|
||||
"ctor": "Faction",
|
||||
"data": {
|
||||
"alreadyInvited": false,
|
||||
"augmentations": [
|
||||
"Augmented Targeting III",
|
||||
"Synthetic Heart",
|
||||
"Synfibril Muscle",
|
||||
"Combat Rib III",
|
||||
"NEMEAN Subdermal Weave",
|
||||
"Graphene Bone Lacings",
|
||||
"Embedded Netburner Module Core V3 Upgrade",
|
||||
"Embedded Netburner Module Analyze Engine",
|
||||
"Embedded Netburner Module Direct Memory Access Upgrade",
|
||||
"NeuroFlux Governor",
|
||||
"SPTN-97 Gene Modification",
|
||||
],
|
||||
"favor": 0,
|
||||
"isBanned": false,
|
||||
"isMember": false,
|
||||
"name": "The Covenant",
|
||||
"playerReputation": 0,
|
||||
},
|
||||
},
|
||||
@ -689,25 +306,9 @@ exports[`Check Save File Continuity FactionsSave continuity 1`] = `
|
||||
"ctor": "Faction",
|
||||
"data": {
|
||||
"alreadyInvited": false,
|
||||
"augmentations": [
|
||||
"Augmented Targeting I",
|
||||
"Augmented Targeting II",
|
||||
"Augmented Targeting III",
|
||||
"Combat Rib I",
|
||||
"Combat Rib II",
|
||||
"Combat Rib III",
|
||||
"Nanofiber Weave",
|
||||
"Wired Reflexes",
|
||||
"The Shadow's Simulacrum",
|
||||
"NeuroFlux Governor",
|
||||
"HemoRecirculator",
|
||||
"Power Recirculation Core",
|
||||
"Graphene Bionic Arms Upgrade",
|
||||
],
|
||||
"favor": 0,
|
||||
"isBanned": false,
|
||||
"isMember": false,
|
||||
"name": "The Dark Army",
|
||||
"playerReputation": 0,
|
||||
},
|
||||
},
|
||||
@ -715,29 +316,9 @@ exports[`Check Save File Continuity FactionsSave continuity 1`] = `
|
||||
"ctor": "Faction",
|
||||
"data": {
|
||||
"alreadyInvited": false,
|
||||
"augmentations": [
|
||||
"Augmented Targeting I",
|
||||
"Augmented Targeting II",
|
||||
"Augmented Targeting III",
|
||||
"Combat Rib I",
|
||||
"Combat Rib II",
|
||||
"Combat Rib III",
|
||||
"Nanofiber Weave",
|
||||
"NEMEAN Subdermal Weave",
|
||||
"Wired Reflexes",
|
||||
"Bionic Spine",
|
||||
"Bionic Legs",
|
||||
"ADR-V1 Pheromone Gene",
|
||||
"The Shadow's Simulacrum",
|
||||
"NeuroFlux Governor",
|
||||
"HemoRecirculator",
|
||||
"Power Recirculation Core",
|
||||
"BrachiBlades",
|
||||
],
|
||||
"favor": 0,
|
||||
"isBanned": false,
|
||||
"isMember": false,
|
||||
"name": "The Syndicate",
|
||||
"playerReputation": 0,
|
||||
},
|
||||
},
|
||||
@ -745,21 +326,9 @@ exports[`Check Save File Continuity FactionsSave continuity 1`] = `
|
||||
"ctor": "Faction",
|
||||
"data": {
|
||||
"alreadyInvited": false,
|
||||
"augmentations": [
|
||||
"Nanofiber Weave",
|
||||
"Wired Reflexes",
|
||||
"Speech Processor Implant",
|
||||
"Neuroreceptor Management Implant",
|
||||
"Nuoptimal Nootropic Injector Implant",
|
||||
"Speech Enhancement",
|
||||
"ADR-V1 Pheromone Gene",
|
||||
"NeuroFlux Governor",
|
||||
"Social Negotiation Assistant (S.N.A)",
|
||||
],
|
||||
"favor": 0,
|
||||
"isBanned": false,
|
||||
"isMember": false,
|
||||
"name": "Tian Di Hui",
|
||||
"playerReputation": 0,
|
||||
},
|
||||
},
|
||||
@ -767,20 +336,9 @@ exports[`Check Save File Continuity FactionsSave continuity 1`] = `
|
||||
"ctor": "Faction",
|
||||
"data": {
|
||||
"alreadyInvited": false,
|
||||
"augmentations": [
|
||||
"Combat Rib I",
|
||||
"Combat Rib II",
|
||||
"Wired Reflexes",
|
||||
"Speech Processor Implant",
|
||||
"Neuralstimulator",
|
||||
"Nuoptimal Nootropic Injector Implant",
|
||||
"NeuroFlux Governor",
|
||||
"DermaForce Particle Barrier",
|
||||
],
|
||||
"favor": 0,
|
||||
"isBanned": false,
|
||||
"isMember": false,
|
||||
"name": "Volhaven",
|
||||
"playerReputation": 0,
|
||||
},
|
||||
},
|
||||
|
Reference in New Issue
Block a user