FACTIONS: Followup changes for Rumors PR (#910)

This commit is contained in:
Snarling 2023-11-02 11:02:12 -04:00 committed by GitHub
parent fdcb8306d9
commit 2997384403
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 63 additions and 196 deletions

@ -66,7 +66,7 @@ export function FactionsDev(): React.ReactElement {
Object.values(Factions).forEach((faction) => { Object.values(Factions).forEach((faction) => {
faction.discovery = FactionDiscovery.unknown; faction.discovery = FactionDiscovery.unknown;
}); });
Player.factionRumors.length = 0; Player.factionRumors.clear();
setFactionDiscovery(Factions[factionName].discovery); setFactionDiscovery(Factions[factionName].discovery);
} }

@ -3,7 +3,6 @@ import { FactionInfo, FactionInfos } from "./FactionInfo";
import { favorToRep, repToFavor } from "./formulas/favor"; import { favorToRep, repToFavor } from "./formulas/favor";
import { Generic_fromJSON, Generic_toJSON, IReviverValue, constructorsForReviver } from "../utils/JSONReviver"; import { Generic_fromJSON, Generic_toJSON, IReviverValue, constructorsForReviver } from "../utils/JSONReviver";
import { getKeyList } from "../utils/helpers/getKeyList"; import { getKeyList } from "../utils/helpers/getKeyList";
import type { PlayerObject } from "../PersonObjects/Player/PlayerObject";
export class Faction { export class Faction {
/** /**
@ -79,31 +78,9 @@ export class Faction {
return newFavor - this.favor; return newFavor - this.favor;
} }
checkForInvite(p: PlayerObject): boolean { static savedKeys = getKeyList(Faction, {
if (this.isBanned) return false; removedKeys: ["augmentations", "name", "alreadyInvited", "isBanned", "isMember"],
if (this.isMember) return false; });
if (this.alreadyInvited) return false;
const conditions = this.getInfo().inviteReqs;
if (conditions.length == 0) return false;
for (const condition of conditions) {
if (!condition.isSatisfied(p)) return false;
}
return true;
}
checkForRumor(p: PlayerObject): boolean {
if (this.isBanned) return false;
if (this.isMember) return false;
if (this.alreadyInvited) return false;
const conditions = this.getInfo().rumorReqs;
if (conditions.length == 0) return false;
for (const condition of conditions) {
if (!condition.isSatisfied(p)) return false;
}
return true;
}
static savedKeys = getKeyList(Faction, { removedKeys: ["augmentations", "name"] });
/** Serialize the current object to a JSON save state. */ /** Serialize the current object to a JSON save state. */
toJSON(): IReviverValue { toJSON(): IReviverValue {

@ -43,6 +43,7 @@ export function joinFaction(faction: Faction): void {
//Determine what factions you are banned from now that you have joined this faction //Determine what factions you are banned from now that you have joined this faction
for (const enemy of factionInfo.enemies) { for (const enemy of factionInfo.enemies) {
if (Factions[enemy]) Factions[enemy].isBanned = true; if (Factions[enemy]) Factions[enemy].isBanned = true;
Player.factionRumors.delete(enemy);
} }
for (let i = 0; i < Player.factionInvitations.length; ++i) { for (let i = 0; i < Player.factionInvitations.length; ++i) {
if (Player.factionInvitations[i] == faction.name || Factions[Player.factionInvitations[i]].isBanned) { if (Player.factionInvitations[i] == faction.name || Factions[Player.factionInvitations[i]].isBanned) {
@ -50,12 +51,7 @@ export function joinFaction(faction: Faction): void {
i--; i--;
} }
} }
for (let i = 0; i < Player.factionRumors.length; ++i) { Player.factionRumors.delete(faction.name);
if (Player.factionRumors[i] == faction.name || Factions[Player.factionRumors[i]].isBanned) {
Player.factionRumors.splice(i, 1);
i--;
}
}
} }
//Returns a boolean indicating whether the player has the prerequisites for the //Returns a boolean indicating whether the player has the prerequisites for the

@ -1,7 +1,5 @@
/** import type { PlayerObject } from "../PersonObjects/Player/PlayerObject";
* Initialization and manipulation of the Factions object, which stores data
* about all Factions in the game
*/
import { FactionName, FactionDiscovery } from "@enums"; import { FactionName, FactionDiscovery } from "@enums";
import { Faction } from "./Faction"; import { Faction } from "./Faction";
@ -20,7 +18,7 @@ for (const aug of getRecordValues(Augmentations)) {
} }
} }
export function loadFactions(saveString: string): void { export function loadFactions(saveString: string, player: PlayerObject): void {
const loadedFactions = JSON.parse(saveString, Reviver) as unknown; const loadedFactions = JSON.parse(saveString, Reviver) as unknown;
// This loading method allows invalid data in player save, but just ignores anything invalid // This loading method allows invalid data in player save, but just ignores anything invalid
if (!loadedFactions) return; if (!loadedFactions) return;
@ -35,11 +33,27 @@ export function loadFactions(saveString: string): void {
if (typeof loadedRep === "number" && loadedRep > 0) faction.playerReputation = loadedRep; if (typeof loadedRep === "number" && loadedRep > 0) faction.playerReputation = loadedRep;
if (typeof loadedFavor === "number" && loadedFavor > 0) faction.favor = loadedFavor; if (typeof loadedFavor === "number" && loadedFavor > 0) faction.favor = loadedFavor;
if (getEnumHelper("FactionDiscovery").isMember(loadedDiscovery)) faction.discovery = loadedDiscovery; if (getEnumHelper("FactionDiscovery").isMember(loadedDiscovery)) faction.discovery = loadedDiscovery;
// 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;
// Fill in knowledge of currently-joined factions from pre-discovery saves
if (faction.alreadyInvited || faction.isMember) faction.discovery = FactionDiscovery.known; if (faction.alreadyInvited || faction.isMember) faction.discovery = FactionDiscovery.known;
} }
// Load joined factions from player save
for (const joinedFacName of player.factions) {
if (!getEnumHelper("FactionName").isMember(joinedFacName)) {
console.error(`Invalid faction in player save factions array: ${joinedFacName}`);
continue;
}
const faction = Factions[joinedFacName];
faction.isMember = true;
faction.alreadyInvited = true;
faction.discovery = FactionDiscovery.known;
for (const enemyFacName of faction.getInfo().enemies) Factions[enemyFacName].isBanned = true;
}
// Load invited factions from player save
for (const invitedFaction of player.factionInvitations) {
if (!getEnumHelper("FactionName").isMember(invitedFaction)) {
console.error(`Invalid faction in player save factionInvitations array: ${invitedFaction}`);
continue;
}
Factions[invitedFaction].alreadyInvited = true;
Factions[invitedFaction].discovery = FactionDiscovery.known;
}
} }

@ -51,13 +51,7 @@ const JoinChecklist = (props: { faction: Faction }): React.ReactElement => {
return ( return (
<> <>
{info.inviteReqs.map((condition, i) => ( {info.inviteReqs.map((condition, i) => (
<Requirement <Requirement key={i} fulfilled={condition.isSatisfied(Player)} value={condition.toString()} />
key={i}
fulfilled={condition.isSatisfied(Player)}
value={condition.toString()}
color={Settings.theme.primary}
incompleteColor={Settings.theme.primarydark}
/>
))} ))}
</> </>
); );
@ -226,8 +220,6 @@ export function FactionsRoot(): React.ReactElement {
const invitations = Player.factionInvitations.map((facName) => Factions[facName]).filter((faction) => !!faction); const invitations = Player.factionInvitations.map((facName) => Factions[facName]).filter((faction) => !!faction);
const rumors = Player.factionRumors.map((facName) => Factions[facName]).filter((faction) => !!faction);
return ( return (
<Container disableGutters maxWidth="lg" sx={{ mx: 0, mb: 10 }}> <Container disableGutters maxWidth="lg" sx={{ mx: 0, mb: 10 }}>
<Typography variant="h4"> <Typography variant="h4">
@ -273,14 +265,14 @@ export function FactionsRoot(): React.ReactElement {
</> </>
)} )}
{rumors.length > 0 && ( {Player.factionRumors.size > 0 && (
<> <>
<Typography variant="h5" color="primary"> <Typography variant="h5" color="primary">
Rumors Rumors
</Typography> </Typography>
<div style={{ display: "grid", gap: 1, gridAutoRows: "minmax(70px, auto)" }}> <div style={{ display: "grid", gap: 1, gridAutoRows: "minmax(70px, auto)" }}>
{rumors.map((faction) => ( {[...Player.factionRumors].map((factionName) => (
<FactionElement key={faction.name} faction={faction} rerender={rerender} /> <FactionElement key={factionName} faction={Factions[factionName]} rerender={rerender} />
))} ))}
</div> </div>
</> </>

@ -21,7 +21,7 @@ import { CompanyName, FactionName, JobName, LocationName } from "@enums";
import { HashManager } from "../../Hacknet/HashManager"; import { HashManager } from "../../Hacknet/HashManager";
import { MoneySourceTracker } from "../../utils/MoneySourceTracker"; import { MoneySourceTracker } from "../../utils/MoneySourceTracker";
import { constructorsForReviver, Generic_toJSON, Generic_fromJSON, IReviverValue } from "../../utils/JSONReviver"; import { constructorsForReviver, Generic_toJSON, Generic_fromJSON, IReviverValue } from "../../utils/JSONReviver";
import { JSONMap } from "../../Types/Jsonable"; import { JSONMap, JSONSet } from "../../Types/Jsonable";
import { cyrb53 } from "../../utils/StringHelperFunctions"; import { cyrb53 } from "../../utils/StringHelperFunctions";
import { getRandomInt } from "../../utils/helpers/getRandomInt"; import { getRandomInt } from "../../utils/helpers/getRandomInt";
import { CONSTANTS } from "../../Constants"; import { CONSTANTS } from "../../Constants";
@ -38,7 +38,7 @@ export class PlayerObject extends Person implements IPlayer {
currentServer = ""; currentServer = "";
factions: FactionName[] = []; factions: FactionName[] = [];
factionInvitations: FactionName[] = []; factionInvitations: FactionName[] = [];
factionRumors: FactionName[] = []; factionRumors = new JSONSet<FactionName>();
hacknetNodes: (HacknetNode | string)[] = []; // HacknetNode object or hostname of Hacknet Server hacknetNodes: (HacknetNode | string)[] = []; // HacknetNode object or hostname of Hacknet Server
has4SData = false; has4SData = false;
has4SDataTixApi = false; has4SDataTixApi = false;

@ -103,7 +103,7 @@ export function prestigeAugmentation(this: PlayerObject): void {
this.factions = []; this.factions = [];
this.factionInvitations = []; this.factionInvitations = [];
this.factionRumors = []; this.factionRumors.clear();
// Clear any pending invitation modals // Clear any pending invitation modals
InvitationEvent.emit(null); InvitationEvent.emit(null);
@ -170,37 +170,17 @@ export function prestigeSourceFile(this: PlayerObject): void {
} }
export function receiveInvite(this: PlayerObject, factionName: FactionName): void { export function receiveInvite(this: PlayerObject, factionName: FactionName): void {
if ( const faction = Factions[factionName];
this.factionInvitations.includes(factionName) || if (faction.alreadyInvited || faction.isMember || faction.isBanned) return;
Factions[factionName].isMember ||
Factions[factionName].isBanned
) {
return;
}
this.factionInvitations.push(factionName); this.factionInvitations.push(factionName);
if (this.factionRumors.includes(factionName)) { this.factionRumors.delete(factionName);
this.factionRumors.splice(this.factionRumors.indexOf(factionName), 1); faction.discovery = FactionDiscovery.known;
}
Factions[factionName].discovery = FactionDiscovery.known;
} }
export function receiveRumor( export function receiveRumor(this: PlayerObject, factionName: FactionName): void {
this: PlayerObject, const faction = Factions[factionName];
factionName: FactionName, if (this.factionRumors.has(factionName) || faction.isMember || faction.isBanned || faction.alreadyInvited) return;
discovery?: FactionDiscovery | undefined, this.factionRumors.add(factionName);
): void {
if (Factions[factionName].discovery == FactionDiscovery.unknown) {
Factions[factionName].discovery = discovery || FactionDiscovery.rumored;
}
if (
this.factionRumors.includes(factionName) ||
this.factionInvitations.includes(factionName) ||
Factions[factionName].isMember ||
Factions[factionName].isBanned
) {
return;
}
this.factionRumors.push(factionName);
} }
//Calculates skill level progress based on experience. The same formula will be used for every skill //Calculates skill level progress based on experience. The same formula will be used for every skill
@ -630,15 +610,22 @@ export function reapplyAllSourceFiles(this: PlayerObject): void {
this.updateSkillLevels(); this.updateSkillLevels();
} }
/*************** Check for Faction Invitations *************/ /**
//This function sets the requirements to join a Faction. It checks whether the Player meets * Checks whether a player meets the requirements for joining each faction, and returns an array of all invitations the player should receive.
//those requirements and will return an array of all factions that the Player should * Also handles receiving rumors for factions if the rumor requirements are met.
//receive an invitation to */
export function checkForFactionInvitations(this: PlayerObject): Faction[] { export function checkForFactionInvitations(this: PlayerObject): Faction[] {
const invitedFactions = []; const invitedFactions = [];
for (const faction of Object.values(Factions)) { for (const faction of Object.values(Factions)) {
if (faction.checkForInvite(this)) invitedFactions.push(faction); if (faction.isBanned) continue;
if (faction.checkForRumor(this)) this.receiveRumor(faction.name); if (faction.isMember) continue;
if (faction.alreadyInvited) continue;
// Handle invites
const { inviteReqs, rumorReqs } = faction.getInfo();
if (inviteReqs.every((req) => req.isSatisfied(this))) invitedFactions.push(faction);
// Handle rumors
if (faction.discovery !== FactionDiscovery.unknown) continue;
if (rumorReqs.every((req) => req.isSatisfied(this))) this.receiveRumor(faction.name);
} }
return invitedFactions; return invitedFactions;
} }

@ -716,7 +716,7 @@ function loadGame(saveString: string): boolean {
setPlayer(loadPlayer(saveObj.PlayerSave)); setPlayer(loadPlayer(saveObj.PlayerSave));
loadAllServers(saveObj.AllServersSave); loadAllServers(saveObj.AllServersSave);
loadCompanies(saveObj.CompaniesSave); loadCompanies(saveObj.CompaniesSave);
loadFactions(saveObj.FactionsSave); loadFactions(saveObj.FactionsSave, Player);
if (Object.hasOwn(saveObj, "StaneksGiftSave")) { if (Object.hasOwn(saveObj, "StaneksGiftSave")) {
loadStaneksGift(saveObj.StaneksGiftSave); loadStaneksGift(saveObj.StaneksGiftSave);

@ -276,374 +276,272 @@ exports[`Check Save File Continuity FactionsSave continuity 1`] = `
"Aevum": { "Aevum": {
"ctor": "Faction", "ctor": "Faction",
"data": { "data": {
"alreadyInvited": false,
"discovery": "unknown", "discovery": "unknown",
"favor": 0, "favor": 0,
"isBanned": false,
"isMember": false,
"playerReputation": 0, "playerReputation": 0,
}, },
}, },
"Bachman & Associates": { "Bachman & Associates": {
"ctor": "Faction", "ctor": "Faction",
"data": { "data": {
"alreadyInvited": false,
"discovery": "unknown", "discovery": "unknown",
"favor": 0, "favor": 0,
"isBanned": false,
"isMember": false,
"playerReputation": 0, "playerReputation": 0,
}, },
}, },
"BitRunners": { "BitRunners": {
"ctor": "Faction", "ctor": "Faction",
"data": { "data": {
"alreadyInvited": false,
"discovery": "unknown", "discovery": "unknown",
"favor": 0, "favor": 0,
"isBanned": false,
"isMember": false,
"playerReputation": 0, "playerReputation": 0,
}, },
}, },
"Blade Industries": { "Blade Industries": {
"ctor": "Faction", "ctor": "Faction",
"data": { "data": {
"alreadyInvited": false,
"discovery": "unknown", "discovery": "unknown",
"favor": 0, "favor": 0,
"isBanned": false,
"isMember": false,
"playerReputation": 0, "playerReputation": 0,
}, },
}, },
"Bladeburners": { "Bladeburners": {
"ctor": "Faction", "ctor": "Faction",
"data": { "data": {
"alreadyInvited": false,
"discovery": "unknown", "discovery": "unknown",
"favor": 0, "favor": 0,
"isBanned": false,
"isMember": true,
"playerReputation": 4000, "playerReputation": 4000,
}, },
}, },
"Chongqing": { "Chongqing": {
"ctor": "Faction", "ctor": "Faction",
"data": { "data": {
"alreadyInvited": false,
"discovery": "unknown", "discovery": "unknown",
"favor": 0, "favor": 0,
"isBanned": false,
"isMember": false,
"playerReputation": 0, "playerReputation": 0,
}, },
}, },
"Church of the Machine God": { "Church of the Machine God": {
"ctor": "Faction", "ctor": "Faction",
"data": { "data": {
"alreadyInvited": false,
"discovery": "unknown", "discovery": "unknown",
"favor": 0, "favor": 0,
"isBanned": false,
"isMember": false,
"playerReputation": 0, "playerReputation": 0,
}, },
}, },
"Clarke Incorporated": { "Clarke Incorporated": {
"ctor": "Faction", "ctor": "Faction",
"data": { "data": {
"alreadyInvited": false,
"discovery": "unknown", "discovery": "unknown",
"favor": 0, "favor": 0,
"isBanned": false,
"isMember": false,
"playerReputation": 0, "playerReputation": 0,
}, },
}, },
"CyberSec": { "CyberSec": {
"ctor": "Faction", "ctor": "Faction",
"data": { "data": {
"alreadyInvited": false,
"discovery": "unknown", "discovery": "unknown",
"favor": 20, "favor": 20,
"isBanned": false,
"isMember": true,
"playerReputation": 1000000, "playerReputation": 1000000,
}, },
}, },
"Daedalus": { "Daedalus": {
"ctor": "Faction", "ctor": "Faction",
"data": { "data": {
"alreadyInvited": false,
"discovery": "unknown", "discovery": "unknown",
"favor": 0, "favor": 0,
"isBanned": false,
"isMember": false,
"playerReputation": 0, "playerReputation": 0,
}, },
}, },
"ECorp": { "ECorp": {
"ctor": "Faction", "ctor": "Faction",
"data": { "data": {
"alreadyInvited": false,
"discovery": "unknown", "discovery": "unknown",
"favor": 0, "favor": 0,
"isBanned": false,
"isMember": false,
"playerReputation": 0, "playerReputation": 0,
}, },
}, },
"Four Sigma": { "Four Sigma": {
"ctor": "Faction", "ctor": "Faction",
"data": { "data": {
"alreadyInvited": false,
"discovery": "unknown", "discovery": "unknown",
"favor": 0, "favor": 0,
"isBanned": false,
"isMember": false,
"playerReputation": 0, "playerReputation": 0,
}, },
}, },
"Fulcrum Secret Technologies": { "Fulcrum Secret Technologies": {
"ctor": "Faction", "ctor": "Faction",
"data": { "data": {
"alreadyInvited": false,
"discovery": "unknown", "discovery": "unknown",
"favor": 0, "favor": 0,
"isBanned": false,
"isMember": false,
"playerReputation": 0, "playerReputation": 0,
}, },
}, },
"Illuminati": { "Illuminati": {
"ctor": "Faction", "ctor": "Faction",
"data": { "data": {
"alreadyInvited": false,
"discovery": "unknown", "discovery": "unknown",
"favor": 0, "favor": 0,
"isBanned": false,
"isMember": false,
"playerReputation": 0, "playerReputation": 0,
}, },
}, },
"Ishima": { "Ishima": {
"ctor": "Faction", "ctor": "Faction",
"data": { "data": {
"alreadyInvited": false,
"discovery": "unknown", "discovery": "unknown",
"favor": 0, "favor": 0,
"isBanned": false,
"isMember": false,
"playerReputation": 0, "playerReputation": 0,
}, },
}, },
"KuaiGong International": { "KuaiGong International": {
"ctor": "Faction", "ctor": "Faction",
"data": { "data": {
"alreadyInvited": false,
"discovery": "unknown", "discovery": "unknown",
"favor": 0, "favor": 0,
"isBanned": false,
"isMember": false,
"playerReputation": 0, "playerReputation": 0,
}, },
}, },
"MegaCorp": { "MegaCorp": {
"ctor": "Faction", "ctor": "Faction",
"data": { "data": {
"alreadyInvited": false,
"discovery": "unknown", "discovery": "unknown",
"favor": 0, "favor": 0,
"isBanned": false,
"isMember": false,
"playerReputation": 0, "playerReputation": 0,
}, },
}, },
"NWO": { "NWO": {
"ctor": "Faction", "ctor": "Faction",
"data": { "data": {
"alreadyInvited": false,
"discovery": "unknown", "discovery": "unknown",
"favor": 0, "favor": 0,
"isBanned": false,
"isMember": false,
"playerReputation": 0, "playerReputation": 0,
}, },
}, },
"Netburners": { "Netburners": {
"ctor": "Faction", "ctor": "Faction",
"data": { "data": {
"alreadyInvited": false,
"discovery": "unknown", "discovery": "unknown",
"favor": 0, "favor": 0,
"isBanned": false,
"isMember": false,
"playerReputation": 0, "playerReputation": 0,
}, },
}, },
"New Tokyo": { "New Tokyo": {
"ctor": "Faction", "ctor": "Faction",
"data": { "data": {
"alreadyInvited": false,
"discovery": "unknown", "discovery": "unknown",
"favor": 0, "favor": 0,
"isBanned": false,
"isMember": false,
"playerReputation": 0, "playerReputation": 0,
}, },
}, },
"NiteSec": { "NiteSec": {
"ctor": "Faction", "ctor": "Faction",
"data": { "data": {
"alreadyInvited": false,
"discovery": "unknown", "discovery": "unknown",
"favor": 0, "favor": 0,
"isBanned": false,
"isMember": false,
"playerReputation": 0, "playerReputation": 0,
}, },
}, },
"OmniTek Incorporated": { "OmniTek Incorporated": {
"ctor": "Faction", "ctor": "Faction",
"data": { "data": {
"alreadyInvited": false,
"discovery": "unknown", "discovery": "unknown",
"favor": 0, "favor": 0,
"isBanned": false,
"isMember": false,
"playerReputation": 0, "playerReputation": 0,
}, },
}, },
"Sector-12": { "Sector-12": {
"ctor": "Faction", "ctor": "Faction",
"data": { "data": {
"alreadyInvited": false,
"discovery": "unknown", "discovery": "unknown",
"favor": 0, "favor": 0,
"isBanned": false,
"isMember": false,
"playerReputation": 0, "playerReputation": 0,
}, },
}, },
"Shadows of Anarchy": { "Shadows of Anarchy": {
"ctor": "Faction", "ctor": "Faction",
"data": { "data": {
"alreadyInvited": false,
"discovery": "unknown", "discovery": "unknown",
"favor": 0, "favor": 0,
"isBanned": false,
"isMember": false,
"playerReputation": 0, "playerReputation": 0,
}, },
}, },
"Silhouette": { "Silhouette": {
"ctor": "Faction", "ctor": "Faction",
"data": { "data": {
"alreadyInvited": false,
"discovery": "unknown", "discovery": "unknown",
"favor": 0, "favor": 0,
"isBanned": false,
"isMember": false,
"playerReputation": 0, "playerReputation": 0,
}, },
}, },
"Slum Snakes": { "Slum Snakes": {
"ctor": "Faction", "ctor": "Faction",
"data": { "data": {
"alreadyInvited": false,
"discovery": "unknown", "discovery": "unknown",
"favor": 0, "favor": 0,
"isBanned": false,
"isMember": true,
"playerReputation": 0, "playerReputation": 0,
}, },
}, },
"Speakers for the Dead": { "Speakers for the Dead": {
"ctor": "Faction", "ctor": "Faction",
"data": { "data": {
"alreadyInvited": false,
"discovery": "unknown", "discovery": "unknown",
"favor": 0, "favor": 0,
"isBanned": false,
"isMember": false,
"playerReputation": 0, "playerReputation": 0,
}, },
}, },
"Tetrads": { "Tetrads": {
"ctor": "Faction", "ctor": "Faction",
"data": { "data": {
"alreadyInvited": false,
"discovery": "unknown", "discovery": "unknown",
"favor": 0, "favor": 0,
"isBanned": false,
"isMember": false,
"playerReputation": 0, "playerReputation": 0,
}, },
}, },
"The Black Hand": { "The Black Hand": {
"ctor": "Faction", "ctor": "Faction",
"data": { "data": {
"alreadyInvited": false,
"discovery": "unknown", "discovery": "unknown",
"favor": 0, "favor": 0,
"isBanned": false,
"isMember": false,
"playerReputation": 0, "playerReputation": 0,
}, },
}, },
"The Covenant": { "The Covenant": {
"ctor": "Faction", "ctor": "Faction",
"data": { "data": {
"alreadyInvited": false,
"discovery": "unknown", "discovery": "unknown",
"favor": 0, "favor": 0,
"isBanned": false,
"isMember": false,
"playerReputation": 0, "playerReputation": 0,
}, },
}, },
"The Dark Army": { "The Dark Army": {
"ctor": "Faction", "ctor": "Faction",
"data": { "data": {
"alreadyInvited": false,
"discovery": "unknown", "discovery": "unknown",
"favor": 0, "favor": 0,
"isBanned": false,
"isMember": false,
"playerReputation": 0, "playerReputation": 0,
}, },
}, },
"The Syndicate": { "The Syndicate": {
"ctor": "Faction", "ctor": "Faction",
"data": { "data": {
"alreadyInvited": false,
"discovery": "unknown", "discovery": "unknown",
"favor": 0, "favor": 0,
"isBanned": false,
"isMember": false,
"playerReputation": 0, "playerReputation": 0,
}, },
}, },
"Tian Di Hui": { "Tian Di Hui": {
"ctor": "Faction", "ctor": "Faction",
"data": { "data": {
"alreadyInvited": false,
"discovery": "unknown", "discovery": "unknown",
"favor": 0, "favor": 0,
"isBanned": false,
"isMember": false,
"playerReputation": 0, "playerReputation": 0,
}, },
}, },
"Volhaven": { "Volhaven": {
"ctor": "Faction", "ctor": "Faction",
"data": { "data": {
"alreadyInvited": false,
"discovery": "unknown", "discovery": "unknown",
"favor": 0, "favor": 0,
"isBanned": false,
"isMember": false,
"playerReputation": 0, "playerReputation": 0,
}, },
}, },
@ -1272,7 +1170,10 @@ exports[`Check Save File Continuity PlayerSave continuity 1`] = `
}, },
"exploits": [], "exploits": [],
"factionInvitations": [], "factionInvitations": [],
"factionRumors": [], "factionRumors": {
"ctor": "JSONSet",
"data": [],
},
"factions": [ "factions": [
"Slum Snakes", "Slum Snakes",
"CyberSec", "CyberSec",