FACTIONS: fix unstable display order (#920)

This commit is contained in:
Jesse Clark 2023-12-03 01:06:30 -08:00 committed by GitHub
parent 34cc0441c2
commit 7fc46649f9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 69 additions and 70 deletions

@ -143,12 +143,12 @@ export function FactionsDev(): React.ReactElement {
value={selectedFaction.name}
startAdornment={
<>
<Tooltip title={`Hear rumor about ${selectedFaction}`}>
<Tooltip title={`Hear rumor about ${selectedFaction.name}`}>
<IconButton onClick={receiveRumor} size="large">
<ChatIcon />
</IconButton>
</Tooltip>
<Tooltip title={`Receive invitation to ${selectedFaction}`}>
<Tooltip title={`Receive invitation to ${selectedFaction.name}`}>
<IconButton onClick={receiveInvite} size="large">
<ReplyIcon />
</IconButton>

@ -3,7 +3,7 @@ import type { Faction } from "./Faction";
import { Augmentations } from "../Augmentation/Augmentations";
import { PlayerOwnedAugmentation } from "../Augmentation/PlayerOwnedAugmentation";
import { AugmentationName, FactionName } from "@enums";
import { AugmentationName } from "@enums";
import { currentNodeMults } from "../BitNode/BitNodeMultipliers";
import { Player } from "@player";
@ -20,7 +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";
import { getRecordKeys } from "../Types/Record";
export function inviteToFaction(faction: Faction): void {
if (faction.alreadyInvited || faction.isMember) return;
@ -34,23 +34,18 @@ export function inviteToFaction(faction: Faction): void {
export function joinFaction(faction: Faction): void {
if (faction.isMember) return;
faction.isMember = true;
Player.factions.push(faction.name);
let i = 0;
const factionIndexes = createEnumKeyedRecord(FactionName, (__) => i++);
Player.factions.sort((a, b) => factionIndexes[a] - factionIndexes[b]);
const factionInfo = faction.getInfo();
// Add this faction to player's faction list, keeping it in standard order
Player.factions = getRecordKeys(Factions).filter((facName) => Factions[facName].isMember);
//Determine what factions you are banned from now that you have joined this faction
for (const enemy of factionInfo.enemies) {
// Ban player from this faction's enemies
for (const enemy of faction.getInfo().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) {
Player.factionInvitations.splice(i, 1);
i--;
}
}
// Remove invalid invites and rumors
Player.factionInvitations = Player.factionInvitations.filter((factionName) => {
return !Factions[factionName].isMember && !Factions[factionName].isBanned;
});
Player.factionRumors.delete(faction.name);
}

@ -430,6 +430,25 @@ export const FactionInfos: Record<FactionName, FactionInfo> = {
keepOnInstall: false,
}),
[FactionName.CyberSec]: new FactionInfo({
infoText: (
<>
The Internet is the first thing that was built that we don't fully understand, the largest experiment in anarchy
that we have ever had. And as the world becomes increasingly dominated by it, society approaches the brink of
total chaos. We serve only to protect society, to protect humanity, to protect the world from imminent collapse.
</>
),
rumorText: (
<>
A hacking group known as {FactionName.CyberSec} will invite you to join them if you demonstrate your hacking
skills on their server.
</>
),
inviteReqs: [haveBackdooredServer(SpecialServers.CyberSecServer)],
rumorReqs: [haveFile(MessageFilename.CyberSecTest)],
offerHackingWork: true,
}),
// City factions, essentially governments
[FactionName.Aevum]: new FactionInfo({
infoText: <>The Silicon City.</>,
@ -631,25 +650,6 @@ export const FactionInfos: Record<FactionName, FactionInfo> = {
offerSecurityWork: true,
}),
[FactionName.CyberSec]: new FactionInfo({
infoText: (
<>
The Internet is the first thing that was built that we don't fully understand, the largest experiment in anarchy
that we have ever had. And as the world becomes increasingly dominated by it, society approaches the brink of
total chaos. We serve only to protect society, to protect humanity, to protect the world from imminent collapse.
</>
),
rumorText: (
<>
A hacking group known as {FactionName.CyberSec} will invite you to join them if you demonstrate your hacking
skills on their server.
</>
),
inviteReqs: [haveBackdooredServer(SpecialServers.CyberSecServer)],
rumorReqs: [haveFile(MessageFilename.CyberSecTest)],
offerHackingWork: true,
}),
// Special Factions
[FactionName.Bladeburners]: new FactionInfo({
infoText: (

@ -209,16 +209,16 @@ export function FactionsRoot(): React.ReactElement {
const theme = useTheme();
const rerender = useRerender(200);
useEffect(() => {
Player.factionInvitations.forEach((faction) => {
InvitationsSeen.add(faction);
Player.factionInvitations.forEach((factionName) => {
InvitationsSeen.add(factionName);
});
}, []);
const allFactions = Object.values(FactionName).map((faction) => faction as string);
const allJoinedFactions = [...Player.factions].map((facName) => Factions[facName]).filter((faction) => !!faction);
allJoinedFactions.sort((a, b) => allFactions.indexOf(a.name) - allFactions.indexOf(b.name));
const invitations = Player.factionInvitations.map((facName) => Factions[facName]).filter((faction) => !!faction);
// Display joined factions in the standard order
const joinedFactions = Object.values(Factions).filter((faction) => faction.isMember);
// Display invitations and rumors in the order they were received
const invitedFactions = Player.factionInvitations.map((facName) => Factions[facName]).filter((faction) => !!faction);
const rumoredFactions = [...Player.factionRumors].map((facName) => Factions[facName]).filter((faction) => !!faction);
return (
<Container disableGutters maxWidth="lg" sx={{ mx: 0, mb: 10 }}>
@ -241,7 +241,7 @@ export function FactionsRoot(): React.ReactElement {
display="grid"
sx={{
gap: 1,
gridTemplateColumns: (invitations.length > 0 ? "1fr " : "") + "2fr",
gridTemplateColumns: (invitedFactions.length > 0 ? "1fr " : "") + "2fr",
[theme.breakpoints.down("lg")]: { gridTemplateColumns: "1fr", "& > span:nth-of-type(1)": { order: 1 } },
gridTemplateRows: "minmax(0, 1fr)",
"& > span > .MuiBox-root": {
@ -251,35 +251,22 @@ export function FactionsRoot(): React.ReactElement {
},
}}
>
<span>
{invitations.length > 0 && (
<span className="factions-invites">
{invitedFactions.length > 0 && (
<>
<Typography variant="h5" color="primary">
Faction Invitations
</Typography>
<Box>
{invitations.map((faction) => (
{invitedFactions.map((faction) => (
<FactionElement key={faction.name} faction={faction} rerender={rerender} />
))}
</Box>
</>
)}
{Player.factionRumors.size > 0 && (
<>
<Typography variant="h5" color="primary">
Rumors
</Typography>
<div style={{ display: "grid", gap: 1, gridAutoRows: "minmax(70px, auto)" }}>
{[...Player.factionRumors].map((factionName) => (
<FactionElement key={factionName} faction={Factions[factionName]} rerender={rerender} />
))}
</div>
</>
)}
</span>
<span>
<span className="factions-joined">
{Player.inGang() && (
<>
<Typography variant="h5" color="primary">
@ -294,8 +281,8 @@ export function FactionsRoot(): React.ReactElement {
Your Factions
</Typography>
<Box>
{allJoinedFactions.length > 0 ? (
allJoinedFactions.map((faction) => {
{joinedFactions.length > 0 ? (
joinedFactions.map((faction) => {
if (Player.getGangName() === faction.name) return null;
return <FactionElement key={faction.name} faction={faction} rerender={rerender} />;
})
@ -305,6 +292,20 @@ export function FactionsRoot(): React.ReactElement {
</Box>
</span>
</Box>
<span className="factions-rumors">
{rumoredFactions.length > 0 && (
<>
<Typography variant="h5" color="primary">
Rumors
</Typography>
<Box style={{ display: "grid", gap: 1, gridAutoRows: "minmax(70px, auto)" }}>
{rumoredFactions.map((faction) => (
<FactionElement key={faction.name} faction={faction} rerender={rerender} />
))}
</Box>
</>
)}
</span>
</Container>
);
}

@ -171,7 +171,8 @@ export function prestigeSourceFile(this: PlayerObject): void {
export function receiveInvite(this: PlayerObject, factionName: FactionName): void {
const faction = Factions[factionName];
if (faction.alreadyInvited || faction.isMember || faction.isBanned) return;
if (this.factionInvitations.includes(factionName) || faction.alreadyInvited || faction.isMember || faction.isBanned)
return;
this.factionInvitations.push(factionName);
this.factionRumors.delete(factionName);
faction.discovery = FactionDiscovery.known;

@ -35,13 +35,13 @@ export function prestigeAugmentation(): void {
initBitNodeMultipliers();
// Maintain invites to factions with the 'keepOnInstall' flag, and rumors about others
const maintainInvites = [];
const maintainRumors = [];
const maintainInvites = new Set<FactionName>();
const maintainRumors = new Set<FactionName>();
for (const facName of [...Player.factions, ...Player.factionInvitations]) {
if (Factions[facName].getInfo().keep) {
maintainInvites.push(facName);
maintainInvites.add(facName);
} else {
maintainRumors.push(facName);
maintainRumors.add(facName);
}
}
@ -92,8 +92,10 @@ export function prestigeAugmentation(): void {
// Recalculate the bonus for circadian modulator aug
initCircadianModulator();
Player.factionInvitations = Player.factionInvitations.concat(maintainInvites);
for (const factionName of maintainInvites) Factions[factionName].alreadyInvited = true;
Player.factionInvitations = Player.factionInvitations.concat([...maintainInvites]);
for (const factionName of maintainInvites) {
Factions[factionName].alreadyInvited = true;
}
Player.reapplyAllAugmentations();
Player.reapplyAllSourceFiles();
Player.hp.current = Player.hp.max;