Cuts copypaste from Antag Info UIs (#76736)

## About The Pull Request

Instead of copy-pasting this `Objective` type and component into every
UI, let's just import it yeah?

The only one I didn't remove this from is the one Blob uses, because it
did some unique things. Left it be.

<Details>

<Summary> UIs work </Summary>


![image](https://github.com/tgstation/tgstation/assets/51863163/4bd47675-98d5-4f02-825c-50cd3aa2fa63)

</Details>

Also removed a now-unused Family antag info ui. 

## Why It's Good For The Game

Cleaner code

## Changelog

🆑 Melbert
refactor: Refactored display-ing of antag objectives in their UIs
/🆑
This commit is contained in:
MrMelbert
2023-07-16 21:13:13 -07:00
committed by GitHub
parent 5dc747e30d
commit 5dac4b7d0f
13 changed files with 130 additions and 429 deletions
@@ -1,6 +1,6 @@
import { BooleanLike } from 'common/react';
import { useBackend } from '../backend';
import { Box, Collapsible, Divider, LabeledList, Section, Stack } from '../components';
import { Objective } from './common/Objectives';
import { Window } from '../layouts';
@@ -9,16 +9,7 @@ type Data = {
description: string;
effects: string;
name: string;
objectives: Objectives[];
};
type Objectives = {
count: number;
name: string;
explanation: string;
complete: BooleanLike;
was_uncompleted: BooleanLike;
reward: number;
objectives: Objective[];
};
const BLOB_COLOR = '#556b2f';
@@ -1,22 +1,15 @@
import { useBackend } from '../backend';
import { Icon, Section, Stack } from '../components';
import { BooleanLike } from 'common/react';
import { Box, Icon, Section, Stack } from '../components';
import { Window } from '../layouts';
import { ObjectivePrintout, Objective } from './common/Objectives';
type Objective = {
count: number;
name: string;
explanation: string;
complete: BooleanLike;
was_uncompleted: BooleanLike;
reward: number;
};
type Info = {
type Data = {
objectives: Objective[];
};
export const AntagInfoBrainwashed = () => {
export const AntagInfoBrainwashed = (porps, context) => {
const { data } = useBackend<Data>(context);
return (
<Window width={400} height={400} theme="abductor">
<Window.Content backgroundColor="#722e7d">
@@ -40,7 +33,15 @@ export const AntagInfoBrainwashed = () => {
It is focusing on a single purpose...
</Stack.Item>
<Stack.Item mt={3.5} grow>
<ObjectivePrintout />
<ObjectivePrintout
fill
objectives={data.objectives}
objectiveFollowup={
<Box bold textColor="red">
This Directive must be followed.
</Box>
}
/>
</Stack.Item>
<Stack.Item fontSize="20px" textColor="#61e4b9">
Follow the directives at any cost!
@@ -54,28 +55,3 @@ export const AntagInfoBrainwashed = () => {
</Window>
);
};
const ObjectivePrintout = (props, context) => {
const { data } = useBackend<Info>(context);
const { objectives } = data;
return (
<Stack fill vertical>
<Stack.Item bold textColor="#61e4b9">
Your current objectives:
</Stack.Item>
<Stack.Item textAlign="left">
{(!objectives && 'None!') ||
objectives.map((objective) => (
<>
<Stack.Item key={objective.count}>
{objective.count}. {objective.explanation}
</Stack.Item>
<Stack.Item bold textColor="red">
This Directive must be followed.
</Stack.Item>
</>
))}
</Stack.Item>
</Stack>
);
};
@@ -1,16 +1,7 @@
import { useBackend } from '../backend';
import { Section, Stack } from '../components';
import { BooleanLike } from 'common/react';
import { Window } from '../layouts';
type Objective = {
count: number;
name: string;
explanation: string;
complete: BooleanLike;
was_uncompleted: BooleanLike;
reward: number;
};
import { ObjectivePrintout, Objective } from './common/Objectives';
type Info = {
antag_name: string;
@@ -20,7 +11,7 @@ type Info = {
export const AntagInfoBrother = (props, context) => {
const { data } = useBackend<Info>(context);
const { antag_name, brothers } = data;
const { antag_name, brothers, objectives } = data;
return (
<Window width={620} height={250}>
<Window.Content>
@@ -30,7 +21,7 @@ export const AntagInfoBrother = (props, context) => {
You are the {antag_name} of {brothers}!
</Stack.Item>
<Stack.Item>
<ObjectivePrintout />
<ObjectivePrintout objectives={objectives} />
</Stack.Item>
</Stack>
</Section>
@@ -38,21 +29,3 @@ export const AntagInfoBrother = (props, context) => {
</Window>
);
};
const ObjectivePrintout = (props, context) => {
const { data } = useBackend<Info>(context);
const { objectives } = data;
return (
<Stack vertical>
<Stack.Item bold>Your objectives:</Stack.Item>
<Stack.Item>
{(!objectives && 'None!') ||
objectives.map((objective) => (
<Stack.Item key={objective.count}>
#{objective.count}: {objective.explanation}
</Stack.Item>
))}
</Stack.Item>
</Stack>
);
};
@@ -2,6 +2,7 @@ import { multiline } from 'common/string';
import { useBackend, useSharedState } from '../backend';
import { Button, Dimmer, Dropdown, Section, Stack, NoticeBox } from '../components';
import { Window } from '../layouts';
import { ObjectivePrintout, Objective } from './common/Objectives';
const hivestyle = {
fontWeight: 'bold',
@@ -38,12 +39,6 @@ const fallenstyle = {
fontWeight: 'bold',
};
type Objective = {
count: number;
name: string;
explanation: string;
};
type Memory = {
name: string;
story: string;
@@ -90,24 +85,6 @@ export const AntagInfoChangeling = (props, context) => {
);
};
const ObjectivePrintout = (props, context) => {
const { data } = useBackend<Info>(context);
const { objectives } = data;
return (
<Stack vertical>
<Stack.Item bold>Your current objectives:</Stack.Item>
<Stack.Item>
{(!objectives && 'None!') ||
objectives.map((objective) => (
<Stack.Item key={objective.count}>
#{objective.count}: {objective.explanation}
</Stack.Item>
))}
</Stack.Item>
</Stack>
);
};
const HivemindSection = (props, context) => {
const { act, data } = useBackend<Info>(context);
const { true_name } = data;
@@ -150,7 +127,7 @@ const IntroductionSection = (props, context) => {
<span style={hivestyle}> {hive_name}</span>.
</Stack.Item>
<Stack.Item>
<ObjectivePrintout />
<ObjectivePrintout objectives={objectives} />
</Stack.Item>
</Stack>
</Section>
@@ -2,6 +2,7 @@ import { useBackend } from '../backend';
import { Box, Section, Stack } from '../components';
import { BooleanLike } from 'common/react';
import { Window } from '../layouts';
import { ObjectivePrintout, Objective } from './common/Objectives';
const jauntstyle = {
color: 'lightblue',
@@ -11,15 +12,6 @@ const injurestyle = {
color: 'yellow',
};
type Objective = {
count: number;
name: string;
explanation: string;
complete: BooleanLike;
was_uncompleted: BooleanLike;
reward: number;
};
type Info = {
fluff: string;
explain_attack: BooleanLike;
@@ -48,7 +40,11 @@ export const AntagInfoDemon = (props, context) => {
{fluff}
</Stack.Item>
<Stack.Item>
<ObjectivePrintout />
<ObjectivePrintout
titleMessage="It is in your nature to accomplish these goals:"
objectiveTextSize="20px"
objectives={objectives}
/>
</Stack.Item>
</Stack>
</Section>
@@ -88,26 +84,6 @@ export const AntagInfoDemon = (props, context) => {
);
};
const ObjectivePrintout = (props, context) => {
const { data } = useBackend<Info>(context);
const { objectives } = data;
return (
<Stack vertical>
<Stack.Item bold>
It is in your nature to accomplish these goals:
</Stack.Item>
<Stack.Item>
{(!objectives && 'None!') ||
objectives.map((objective) => (
<Stack.Item fontSize="20px" key={objective.count}>
#{objective.count}: {objective.explanation}
</Stack.Item>
))}
</Stack.Item>
</Stack>
);
};
const DemonRunes = (props, context) => {
return (
<Section height="102%" mt="-6px" fill>
@@ -1,115 +0,0 @@
import { useBackend } from '../backend';
import { BlockQuote, Icon, Section, Stack } from '../components';
import { Window } from '../layouts';
type Info = {
antag_name: string;
gang_name: string;
gang_objective: string;
gang_clothes: string[];
};
export const AntagInfoGangmember = (props, context) => {
const { data } = useBackend<Info>(context);
const { gang_name, antag_name } = data;
return (
<Window width={620} height={500}>
<Window.Content
style={{
'background-image': 'none',
}}>
<Section fill>
<Stack vertical>
<Stack.Item textColor="red" fontSize="20px">
{gang_name} for life! You are a {antag_name}!
</Stack.Item>
<Stack.Item fontSize="18px">
As a gang member, support your family above all! Tag turf with a
spraycan, wear your family&apos;s clothes, induct new members with
induction packages, and accomplish your family objective.
</Stack.Item>
<Stack.Divider />
<Stack.Item>
<Stack fill>
<Stack.Item grow basis={0}>
<GangClothesPrintout />
</Stack.Item>
<Stack.Item grow basis={0}>
<GangPhonePrintout />
</Stack.Item>
</Stack>
</Stack.Item>
<Stack.Divider />
<Stack.Item grow basis={0}>
<GangObjectivePrintout />
</Stack.Item>
</Stack>
</Section>
</Window.Content>
</Window>
);
};
const GangClothesPrintout = (props, context) => {
const { data } = useBackend<Info>(context);
const { gang_name, gang_clothes } = data;
return (
<Stack vertical>
<Stack.Item>
<Stack>
<Stack.Item mt={0.5} mb={1}>
<Icon size={2} name="tshirt" />
</Stack.Item>
<Stack.Item bold>
Wear the following to represent the {gang_name}:
</Stack.Item>
</Stack>
</Stack.Item>
<BlockQuote>
{gang_clothes && gang_clothes.length
? gang_clothes.map((clothes_item) => (
<Stack.Item key={clothes_item}>- {clothes_item}</Stack.Item>
))
: '- Anything!'}
</BlockQuote>
</Stack>
);
};
const GangPhonePrintout = () => {
return (
<Stack vertical>
<Stack.Item>
<Stack>
<Stack.Item mt={0.5}>
<Icon size={2} name="phone" />
</Stack.Item>
<Stack.Item bold>
You were given a cell phone with your induction package!
</Stack.Item>
</Stack>
</Stack.Item>
<Stack.Item>
<BlockQuote>
Use it in hand to activate it, then speak into it to talk with your
other family members.
</BlockQuote>
</Stack.Item>
</Stack>
);
};
const GangObjectivePrintout = (props, context) => {
const { data } = useBackend<Info>(context);
const { gang_objective } = data;
return (
<Stack vertical>
<Stack.Item bold fontSize="16px">
Your family&apos;s goal:
</Stack.Item>
<Stack.Item>
{gang_objective || 'No objective set! This is a problem!'}
</Stack.Item>
</Stack>
);
};
@@ -1,16 +1,7 @@
import { useBackend } from '../backend';
import { Section, Stack } from '../components';
import { BooleanLike } from 'common/react';
import { Window } from '../layouts';
type Objective = {
count: number;
name: string;
explanation: string;
complete: BooleanLike;
was_uncompleted: BooleanLike;
reward: number;
};
import { ObjectivePrintout, Objective } from './common/Objectives';
type Info = {
antag_name: string;
@@ -19,7 +10,7 @@ type Info = {
export const AntagInfoGeneric = (props, context) => {
const { data } = useBackend<Info>(context);
const { antag_name } = data;
const { antag_name, objectives } = data;
return (
<Window width={620} height={250}>
<Window.Content>
@@ -29,7 +20,7 @@ export const AntagInfoGeneric = (props, context) => {
You are the {antag_name}!
</Stack.Item>
<Stack.Item>
<ObjectivePrintout />
<ObjectivePrintout objectives={objectives} />
</Stack.Item>
</Stack>
</Section>
@@ -37,21 +28,3 @@ export const AntagInfoGeneric = (props, context) => {
</Window>
);
};
const ObjectivePrintout = (props, context) => {
const { data } = useBackend<Info>(context);
const { objectives } = data;
return (
<Stack vertical>
<Stack.Item bold>Your objectives:</Stack.Item>
<Stack.Item>
{(!objectives && 'None!') ||
objectives.map((objective) => (
<Stack.Item key={objective.count}>
#{objective.count}: {objective.explanation}
</Stack.Item>
))}
</Stack.Item>
</Stack>
);
};
@@ -2,6 +2,7 @@ import { useBackend, useLocalState } from '../backend';
import { Section, Stack, Box, Tabs, Button, BlockQuote } from '../components';
import { Window } from '../layouts';
import { BooleanLike } from 'common/react';
import { ObjectivePrintout, Objective } from './common/Objectives';
const hereticRed = {
color: '#e03c3c',
@@ -43,12 +44,6 @@ type KnowledgeInfo = {
learnedKnowledge: Knowledge[];
};
type Objective = {
count: number;
name: string;
explanation: string;
};
type Info = {
charges: number;
total_sacrifices: number;
@@ -56,7 +51,10 @@ type Info = {
objectives: Objective[];
};
const IntroductionSection = () => {
const IntroductionSection = (props, context) => {
const { data } = useBackend<Info>(context);
const { objectives } = data;
return (
<Stack justify="space-evenly" height="100%" width="100%">
<Stack.Item grow>
@@ -71,7 +69,13 @@ const IntroductionSection = () => {
<InformationSection />
<Stack.Divider />
<ObjectivePrintout />
<Stack.Item>
<ObjectivePrintout
fill
titleMessage="In order to ascend, you have these tasks to fulfill:"
objectives={objectives}
/>
</Stack.Item>
</Stack>
</Section>
</Stack.Item>
@@ -194,28 +198,6 @@ const InformationSection = (props, context) => {
);
};
const ObjectivePrintout = (props, context) => {
const { data } = useBackend<Info>(context);
const { objectives } = data;
return (
<Stack.Item>
<Stack vertical fill>
<Stack.Item bold>
In order to ascend, you have these tasks to fulfill:
</Stack.Item>
<Stack.Item>
{(!objectives && 'None!') ||
objectives.map((objective) => (
<Stack.Item key={objective.count}>
{objective.count}: {objective.explanation}
</Stack.Item>
))}
</Stack.Item>
</Stack>
</Stack.Item>
);
};
const ResearchedKnowledge = (props, context) => {
const { data } = useBackend<KnowledgeInfo>(context);
const { learnedKnowledge } = data;
@@ -313,8 +295,6 @@ export const AntagInfoHeretic = (props, context) => {
<Window width={675} height={625}>
<Window.Content
style={{
// 'font-family': 'Times New Roman',
// 'fontSize': '20px',
'background-image': 'none',
'background': ascended
? 'radial-gradient(circle, rgba(24,9,9,1) 54%, rgba(31,10,10,1) 60%, rgba(46,11,11,1) 80%, rgba(47,14,14,1) 100%);'
@@ -4,6 +4,7 @@ import { GenericUplink, Item } from './Uplink/GenericUplink';
import { BlockQuote, Button, Section, Stack, Tabs } from '../components';
import { BooleanLike } from 'common/react';
import { Window } from '../layouts';
import { ObjectivePrintout, Objective } from './common/Objectives';
const allystyle = {
fontWeight: 'bold',
@@ -20,12 +21,6 @@ const goalstyle = {
fontWeight: 'bold',
};
type Objective = {
count: number;
name: string;
explanation: string;
};
type Info = {
has_codewords: BooleanLike;
phrases: string;
@@ -39,33 +34,19 @@ type Info = {
categories: any[];
};
const ObjectivePrintout = (props, context) => {
const { data } = useBackend<Info>(context);
const { objectives } = data;
return (
<Stack vertical>
<Stack.Item bold>Your prime objectives:</Stack.Item>
<Stack.Item>
{(!objectives && 'None!') ||
objectives.map((objective) => (
<Stack.Item key={objective.count}>
&#8805-{objective.count}: {objective.explanation}
</Stack.Item>
))}
</Stack.Item>
</Stack>
);
};
const IntroductionSection = (props, context) => {
const { act, data } = useBackend<Info>(context);
const { intro } = data;
const { intro, objectives } = data;
return (
<Section fill title="Intro" scrollable>
<Stack vertical fill>
<Stack.Item fontSize="25px">{intro}</Stack.Item>
<Stack.Item grow>
<ObjectivePrintout />
<ObjectivePrintout
objectives={objectives}
titleMessage="Your prime objectives:"
objectivePrefix="&#8805-"
/>
</Stack.Item>
</Stack>
</Section>
@@ -1,12 +1,7 @@
import { useBackend } from '../backend';
import { Icon, Section, Stack } from '../components';
import { Window } from '../layouts';
type Objective = {
count: number;
name: string;
explanation: string;
};
import { ObjectivePrintout, Objective } from './common/Objectives';
type Info = {
objectives: Objective[];
@@ -35,7 +30,7 @@ export const AntagInfoSeparatist = (props, context) => {
const IntroductionObjectives = (props, context) => {
const { data } = useBackend<Info>(context);
const { nation } = data;
const { nation, objectives } = data;
return (
<Section fill>
<Stack vertical>
@@ -43,7 +38,10 @@ const IntroductionObjectives = (props, context) => {
You are the Separatist for a free {nation}!
</Stack.Item>
<Stack.Item grow>
<ObjectivePrintout />
<ObjectivePrintout
objectives={objectives}
titleMessage={`${nation}'s objectives:`}
/>
</Stack.Item>
</Stack>
</Section>
@@ -88,21 +86,3 @@ const FrequentlyAskedQuestions = (props, context) => {
</Section>
);
};
const ObjectivePrintout = (props, context) => {
const { data } = useBackend<Info>(context);
const { nation, objectives } = data;
return (
<Stack vertical>
<Stack.Item bold>{nation}&apos;s objectives:</Stack.Item>
<Stack.Item>
{(!objectives && 'None!') ||
objectives.map((objective) => (
<Stack.Item key={objective.count}>
#{objective.count}: {objective.explanation}
</Stack.Item>
))}
</Stack.Item>
</Stack>
);
};
@@ -3,6 +3,7 @@ import { multiline } from 'common/string';
import { BlockQuote, Button, Dimmer, Section, Stack } from '../components';
import { BooleanLike } from 'common/react';
import { Window } from '../layouts';
import { ObjectivePrintout, Objective } from './common/Objectives';
const allystyle = {
fontWeight: 'bold',
@@ -19,12 +20,6 @@ const goalstyle = {
fontWeight: 'bold',
};
type Objective = {
count: number;
name: string;
explanation: string;
};
type Info = {
has_codewords: BooleanLike;
phrases: string;
@@ -43,33 +38,15 @@ type Info = {
objectives: Objective[];
};
const ObjectivePrintout = (props, context) => {
const { data } = useBackend<Info>(context);
const { objectives } = data;
return (
<Stack vertical>
<Stack.Item bold>Your current objectives:</Stack.Item>
<Stack.Item>
{(!objectives && 'None!') ||
objectives.map((objective) => (
<Stack.Item key={objective.count}>
#{objective.count}: {objective.explanation}
</Stack.Item>
))}
</Stack.Item>
</Stack>
);
};
const IntroductionSection = (props, context) => {
const { act, data } = useBackend<Info>(context);
const { intro } = data;
const { intro, objectives } = data;
return (
<Section fill title="Intro" scrollable>
<Stack vertical fill>
<Stack.Item fontSize="25px">{intro}</Stack.Item>
<Stack.Item grow>
<ObjectivePrintout />
<ObjectivePrintout objectives={objectives} />
</Stack.Item>
</Stack>
</Section>
@@ -1,7 +1,7 @@
import { useBackend } from '../backend';
import { Section, Stack } from '../components';
import { BooleanLike } from 'common/react';
import { Box, Section, Stack } from '../components';
import { Window } from '../layouts';
import { ObjectivePrintout, Objective } from './common/Objectives';
const teleportstyle = {
color: 'yellow',
@@ -36,15 +36,6 @@ const grandritualstyle = {
color: '#bd54e0',
};
type Objective = {
count: number;
name: string;
explanation: string;
complete: BooleanLike;
was_uncompleted: BooleanLike;
reward: number;
};
type GrandRitual = {
remaining: number;
next_area: string;
@@ -56,6 +47,9 @@ type Info = {
};
export const AntagInfoWizard = (props, context) => {
const { data } = useBackend<Info>(context);
const { ritual, objectives } = data;
return (
<Window width={620} height={620} theme="wizard">
<Window.Content>
@@ -67,7 +61,11 @@ export const AntagInfoWizard = (props, context) => {
You are the Space Wizard!
</Stack.Item>
<Stack.Item>
<ObjectivePrintout />
<ObjectivePrintout
objectives={objectives}
titleMessage="The Space Wizard Federation has given you the following tasks:"
objectiveFollowup={<RitualPrintout ritual={ritual} />}
/>
</Stack.Item>
</Stack>
</Section>
@@ -143,35 +141,13 @@ export const AntagInfoWizard = (props, context) => {
);
};
const ObjectivePrintout = (props, context) => {
const { data } = useBackend<Info>(context);
const { objectives, ritual } = data;
return (
<Stack vertical>
<Stack.Item bold>
The Space Wizards Federation has given you the following tasks:
</Stack.Item>
<Stack.Item>
{(!objectives && 'None!') ||
objectives.map((objective) => (
<Stack.Item key={objective.count}>
#{objective.count}: {objective.explanation}
</Stack.Item>
))}
</Stack.Item>
<RitualPrintout />
</Stack>
);
};
const RitualPrintout = (props, context) => {
const { data } = useBackend<Info>(context);
const { objectives, ritual } = data;
const RitualPrintout = (props: { ritual: GrandRitual }, context) => {
const { ritual } = props;
if (!ritual.next_area) {
return <Stack.Item />;
return null;
}
return (
<Stack.Item>
<Box>
Alternately, complete the{' '}
<span style={grandritualstyle}>Grand Ritual </span>
by invoking a ritual circle at several nexuses of power.
@@ -181,6 +157,6 @@ const RitualPrintout = (props, context) => {
<br />
Your next ritual location is the
<span style={grandritualstyle}> {ritual.next_area}</span>.
</Stack.Item>
</Box>
);
};
@@ -0,0 +1,56 @@
import { BooleanLike } from 'common/react';
import { InfernoNode } from 'inferno';
import { Stack } from '../../components';
export type Objective = {
// The title of the objective, not actually displayed so optional
name?: string;
// What "number" objective this is, IE, its index in the list of objectives
count: number;
// The text explaining what this objective requires
explanation: string;
// Whether or not this objective is completed
complete: BooleanLike;
};
type ObjectivePrintoutProps = {
// For passing onto the Stack component
fill?: boolean;
// Allows additional components to follow the printout in the same stack
objectiveFollowup?: InfernoNode;
// The prefix to use for each objective, defaults to "#" (#1, #2)
objectivePrefix?: string;
// The font size to use for each objective
objectiveTextSize?: string;
// The objectives to print out
objectives: Objective[];
// The title to use for the printout, defaults to "Your current objectives"
titleMessage?: string;
};
export const ObjectivePrintout = (props: ObjectivePrintoutProps, context) => {
const {
fill,
objectiveFollowup,
objectivePrefix,
objectiveTextSize,
objectives = [],
titleMessage,
} = props;
return (
<Stack fill={fill} vertical>
<Stack.Item bold>{titleMessage || `Your current objectives`}:</Stack.Item>
<Stack.Item>
{(objectives.length === 0 && 'None!') ||
objectives.map((objective) => (
<Stack.Item fontSize={objectiveTextSize} key={objective.count}>
{objectivePrefix || '#'}
{objective.count}: {objective.explanation}
</Stack.Item>
))}
</Stack.Item>
{!!objectiveFollowup && <Stack.Item>{objectiveFollowup}</Stack.Item>}
</Stack>
);
};