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) => {
faction.discovery = FactionDiscovery.unknown;
});
Player.factionRumors.length = 0;
Player.factionRumors.clear();
setFactionDiscovery(Factions[factionName].discovery);
}

@ -3,7 +3,6 @@ import { FactionInfo, FactionInfos } from "./FactionInfo";
import { favorToRep, repToFavor } from "./formulas/favor";
import { Generic_fromJSON, Generic_toJSON, IReviverValue, constructorsForReviver } from "../utils/JSONReviver";
import { getKeyList } from "../utils/helpers/getKeyList";
import type { PlayerObject } from "../PersonObjects/Player/PlayerObject";
export class Faction {
/**
@ -79,31 +78,9 @@ export class Faction {
return newFavor - this.favor;
}
checkForInvite(p: PlayerObject): boolean {
if (this.isBanned) return false;
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"] });
static savedKeys = getKeyList(Faction, {
removedKeys: ["augmentations", "name", "alreadyInvited", "isBanned", "isMember"],
});
/** Serialize the current object to a JSON save state. */
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
for (const enemy of factionInfo.enemies) {
if (Factions[enemy]) Factions[enemy].isBanned = true;
Player.factionRumors.delete(enemy);
}
for (let i = 0; i < Player.factionInvitations.length; ++i) {
if (Player.factionInvitations[i] == faction.name || Factions[Player.factionInvitations[i]].isBanned) {
@ -50,12 +51,7 @@ export function joinFaction(faction: Faction): void {
i--;
}
}
for (let i = 0; i < Player.factionRumors.length; ++i) {
if (Player.factionRumors[i] == faction.name || Factions[Player.factionRumors[i]].isBanned) {
Player.factionRumors.splice(i, 1);
i--;
}
}
Player.factionRumors.delete(faction.name);
}
//Returns a boolean indicating whether the player has the prerequisites for the

@ -1,7 +1,5 @@
/**
* Initialization and manipulation of the Factions object, which stores data
* about all Factions in the game
*/
import type { PlayerObject } from "../PersonObjects/Player/PlayerObject";
import { FactionName, FactionDiscovery } from "@enums";
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;
// This loading method allows invalid data in player save, but just ignores anything invalid
if (!loadedFactions) return;
@ -35,11 +33,27 @@ export function loadFactions(saveString: string): void {
if (typeof loadedRep === "number" && loadedRep > 0) faction.playerReputation = loadedRep;
if (typeof loadedFavor === "number" && loadedFavor > 0) faction.favor = loadedFavor;
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;
}
// 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 (
<>
{info.inviteReqs.map((condition, i) => (
<Requirement
key={i}
fulfilled={condition.isSatisfied(Player)}
value={condition.toString()}
color={Settings.theme.primary}
incompleteColor={Settings.theme.primarydark}
/>
<Requirement key={i} fulfilled={condition.isSatisfied(Player)} value={condition.toString()} />
))}
</>
);
@ -226,8 +220,6 @@ export function FactionsRoot(): React.ReactElement {
const invitations = Player.factionInvitations.map((facName) => Factions[facName]).filter((faction) => !!faction);
const rumors = Player.factionRumors.map((facName) => Factions[facName]).filter((faction) => !!faction);
return (
<Container disableGutters maxWidth="lg" sx={{ mx: 0, mb: 10 }}>
<Typography variant="h4">
@ -273,14 +265,14 @@ export function FactionsRoot(): React.ReactElement {
</>
)}
{rumors.length > 0 && (
{Player.factionRumors.size > 0 && (
<>
<Typography variant="h5" color="primary">
Rumors
</Typography>
<div style={{ display: "grid", gap: 1, gridAutoRows: "minmax(70px, auto)" }}>
{rumors.map((faction) => (
<FactionElement key={faction.name} faction={faction} rerender={rerender} />
{[...Player.factionRumors].map((factionName) => (
<FactionElement key={factionName} faction={Factions[factionName]} rerender={rerender} />
))}
</div>
</>

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

@ -103,7 +103,7 @@ export function prestigeAugmentation(this: PlayerObject): void {
this.factions = [];
this.factionInvitations = [];
this.factionRumors = [];
this.factionRumors.clear();
// Clear any pending invitation modals
InvitationEvent.emit(null);
@ -170,37 +170,17 @@ export function prestigeSourceFile(this: PlayerObject): void {
}
export function receiveInvite(this: PlayerObject, factionName: FactionName): void {
if (
this.factionInvitations.includes(factionName) ||
Factions[factionName].isMember ||
Factions[factionName].isBanned
) {
return;
}
const faction = Factions[factionName];
if (faction.alreadyInvited || faction.isMember || faction.isBanned) return;
this.factionInvitations.push(factionName);
if (this.factionRumors.includes(factionName)) {
this.factionRumors.splice(this.factionRumors.indexOf(factionName), 1);
}
Factions[factionName].discovery = FactionDiscovery.known;
this.factionRumors.delete(factionName);
faction.discovery = FactionDiscovery.known;
}
export function receiveRumor(
this: PlayerObject,
factionName: FactionName,
discovery?: FactionDiscovery | undefined,
): 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);
export function receiveRumor(this: PlayerObject, factionName: FactionName): void {
const faction = Factions[factionName];
if (this.factionRumors.has(factionName) || faction.isMember || faction.isBanned || faction.alreadyInvited) return;
this.factionRumors.add(factionName);
}
//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();
}
/*************** Check for Faction Invitations *************/
//This function sets the requirements to join a Faction. It checks whether the Player meets
//those requirements and will return an array of all factions that the Player should
//receive an invitation to
/**
* Checks whether a player meets the requirements for joining each faction, and returns an array of all invitations the player should receive.
* Also handles receiving rumors for factions if the rumor requirements are met.
*/
export function checkForFactionInvitations(this: PlayerObject): Faction[] {
const invitedFactions = [];
for (const faction of Object.values(Factions)) {
if (faction.checkForInvite(this)) invitedFactions.push(faction);
if (faction.checkForRumor(this)) this.receiveRumor(faction.name);
if (faction.isBanned) continue;
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;
}

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

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