From 5d6952dbacf0ffeb2f4a6ac967d94ab58e604f8a Mon Sep 17 00:00:00 2001 From: nickofolas Date: Mon, 7 Mar 2022 20:03:23 -0600 Subject: [PATCH 1/8] First iteration of sleeves UI improvements --- .../Sleeve/ui/SleeveAugmentationsModal.tsx | 116 +++++------ src/PersonObjects/Sleeve/ui/SleeveElem.tsx | 153 +++++++-------- src/PersonObjects/Sleeve/ui/SleeveRoot.tsx | 9 +- src/PersonObjects/Sleeve/ui/StatsElement.tsx | 181 ++++++++++++++++-- src/PersonObjects/Sleeve/ui/TaskSelector.tsx | 8 +- 5 files changed, 289 insertions(+), 178 deletions(-) diff --git a/src/PersonObjects/Sleeve/ui/SleeveAugmentationsModal.tsx b/src/PersonObjects/Sleeve/ui/SleeveAugmentationsModal.tsx index 301137b24..57c402878 100644 --- a/src/PersonObjects/Sleeve/ui/SleeveAugmentationsModal.tsx +++ b/src/PersonObjects/Sleeve/ui/SleeveAugmentationsModal.tsx @@ -50,74 +50,62 @@ export function SleeveAugmentationsModal(props: IProps): React.ReactElement { return ( <> - - You can purchase Augmentations for your Duplicate Sleeves. These Augmentations have the same effect as they - would for you. You can only purchase Augmentations that you have unlocked through Factions. -
-
- When purchasing an Augmentation for a Duplicate Sleeve, they are immediately installed. This means that the - Duplicate Sleeve will immediately lose all of its stat experience. -
- - - {availableAugs.map((aug) => { - return ( - - - - - - - - {aug.name} - - - - - - - - ); - })} - -
+ + + You can purchase Augmentations for your Duplicate Sleeves. These Augmentations have the same effect as they + would for you. You can only purchase Augmentations that you have unlocked through Factions. +
+
+ When purchasing an Augmentation for a Duplicate Sleeve, they are immediately installed. This means that the + Duplicate Sleeve will immediately lose all of its stat experience. +
+ + + + {availableAugs.map((aug) => { + return ( + + + + + + + + {aug.name} + + + + + + + + ); + })} + +
+
+
{ownedAugNames.length > 0 && ( <> - Owned Augmentations: - {ownedAugNames.map((augName) => { - const aug = Augmentations[augName]; - let tooltip = <>; - if (typeof aug.info === "string") { - tooltip = ( - <> - {aug.info} -
-
- {aug.stats} - - ); - } else { - tooltip = ( - <> - {aug.info} -
-
- {aug.stats} - - ); - } + Owned Augmentations: + + {ownedAugNames.map((augName) => { + const aug = Augmentations[augName]; + const info = typeof aug.info === "string" ? {aug.info} : aug.info + const tooltip = (<>{info}

{aug.stats}); - return ( - {tooltip}}> - - {augName} - - - ); - })} + return ( + {tooltip}}> + + {augName} + + + ); + })} +
)} diff --git a/src/PersonObjects/Sleeve/ui/SleeveElem.tsx b/src/PersonObjects/Sleeve/ui/SleeveElem.tsx index 45a3e909d..61c9f5cbc 100644 --- a/src/PersonObjects/Sleeve/ui/SleeveElem.tsx +++ b/src/PersonObjects/Sleeve/ui/SleeveElem.tsx @@ -13,20 +13,16 @@ import { createProgressBarText } from "../../../utils/helpers/createProgressBarT import { SleeveAugmentationsModal } from "./SleeveAugmentationsModal"; import { TravelModal } from "./TravelModal"; -import { Money } from "../../../ui/React/Money"; -import { MoneyRate } from "../../../ui/React/MoneyRate"; import { use } from "../../../ui/Context"; -import { ReputationRate } from "../../../ui/React/ReputationRate"; -import { StatsElement } from "./StatsElement"; +import { StatsElement, EarningsElement } from "./StatsElement"; import { MoreStatsModal } from "./MoreStatsModal"; import { MoreEarningsModal } from "./MoreEarningsModal"; import { TaskSelector } from "./TaskSelector"; import { FactionWorkType } from "../../../Faction/FactionWorkTypeEnum"; -import { StatsTable } from "../../../ui/React/StatsTable"; import Typography from "@mui/material/Typography"; import Paper from "@mui/material/Paper"; -import Grid from "@mui/material/Grid"; +import { Box } from "@mui/material"; import Button from "@mui/material/Button"; import Tooltip from "@mui/material/Tooltip"; @@ -141,86 +137,71 @@ export function SleeveElem(props: IProps): React.ReactElement { console.error(`Invalid/Unrecognized taskValue in updateSleeveTaskDescription(): ${abc[0]}`); } - let data: any[][] = []; - if (props.sleeve.currentTask === SleeveTaskType.Crime) { - data = [ - [`Money`, , `(on success)`], - [`Hacking Exp`, numeralWrapper.formatExp(props.sleeve.gainRatesForTask.hack), `(2x on success)`], - [`Strength Exp`, numeralWrapper.formatExp(props.sleeve.gainRatesForTask.str), `(2x on success)`], - [`Defense Exp`, numeralWrapper.formatExp(props.sleeve.gainRatesForTask.def), `(2x on success)`], - [`Dexterity Exp`, numeralWrapper.formatExp(props.sleeve.gainRatesForTask.dex), `(2x on success)`], - [`Agility Exp`, numeralWrapper.formatExp(props.sleeve.gainRatesForTask.agi), `(2x on success)`], - [`Charisma Exp`, numeralWrapper.formatExp(props.sleeve.gainRatesForTask.cha), `(2x on success)`], - ]; - } else { - data = [ - [`Money:`, ], - [`Hacking Exp:`, `${numeralWrapper.formatExp(5 * props.sleeve.gainRatesForTask.hack)} / s`], - [`Strength Exp:`, `${numeralWrapper.formatExp(5 * props.sleeve.gainRatesForTask.str)} / s`], - [`Defense Exp:`, `${numeralWrapper.formatExp(5 * props.sleeve.gainRatesForTask.def)} / s`], - [`Dexterity Exp:`, `${numeralWrapper.formatExp(5 * props.sleeve.gainRatesForTask.dex)} / s`], - [`Agility Exp:`, `${numeralWrapper.formatExp(5 * props.sleeve.gainRatesForTask.agi)} / s`], - [`Charisma Exp:`, `${numeralWrapper.formatExp(5 * props.sleeve.gainRatesForTask.cha)} / s`], - ]; - if (props.sleeve.currentTask === SleeveTaskType.Company || props.sleeve.currentTask === SleeveTaskType.Faction) { - const repGain: number = props.sleeve.getRepGain(player); - data.push([`Reputation:`, ]); - } - } - return ( - <> - - - - - Insufficient funds : ""}> - - - - - Unlocked when sleeve has fully recovered : ""} - > - - - - - - - - {desc} - - {props.sleeve.currentTask === SleeveTaskType.Crime && - createProgressBarText({ - progress: props.sleeve.currentTaskTime / props.sleeve.currentTaskMaxTime, - totalTicks: 25, - })} - - - - - - - - - setStatsOpen(false)} sleeve={props.sleeve} /> - setEarningsOpen(false)} sleeve={props.sleeve} /> - setTravelOpen(false)} - sleeve={props.sleeve} - rerender={props.rerender} - /> - setAugmentationsOpen(false)} - sleeve={props.sleeve} - /> - + + + + + + + + + Insufficient funds : ""}> + + + + + Unlocked when sleeve has fully recovered : ""} + > + + + + + + + + + + + + {desc} + + {props.sleeve.currentTask === SleeveTaskType.Crime && + createProgressBarText({ + progress: props.sleeve.currentTaskTime / props.sleeve.currentTaskMaxTime, + totalTicks: 25, + })} + + + + setStatsOpen(false)} sleeve={props.sleeve} /> + setEarningsOpen(false)} sleeve={props.sleeve} /> + setTravelOpen(false)} + sleeve={props.sleeve} + rerender={props.rerender} + /> + setAugmentationsOpen(false)} + sleeve={props.sleeve} + /> + + + ); } diff --git a/src/PersonObjects/Sleeve/ui/SleeveRoot.tsx b/src/PersonObjects/Sleeve/ui/SleeveRoot.tsx index 808b84723..a41a59e87 100644 --- a/src/PersonObjects/Sleeve/ui/SleeveRoot.tsx +++ b/src/PersonObjects/Sleeve/ui/SleeveRoot.tsx @@ -7,6 +7,7 @@ import { use } from "../../../ui/Context"; import Typography from "@mui/material/Typography"; import Button from "@mui/material/Button"; import Link from "@mui/material/Link"; +import { Box } from "@mui/material"; export function SleeveRoot(): React.ReactElement { const player = use.Player(); @@ -41,9 +42,11 @@ export function SleeveRoot(): React.ReactElement { > Documentation - {player.sleeves.map((sleeve, i) => ( - - ))} + + {player.sleeves.map((sleeve, i) => ( + + ))} + setFAQOpen(false)} /> ); diff --git a/src/PersonObjects/Sleeve/ui/StatsElement.tsx b/src/PersonObjects/Sleeve/ui/StatsElement.tsx index 9e51214fc..d348280e6 100644 --- a/src/PersonObjects/Sleeve/ui/StatsElement.tsx +++ b/src/PersonObjects/Sleeve/ui/StatsElement.tsx @@ -1,31 +1,172 @@ import { Sleeve } from "../Sleeve"; import { numeralWrapper } from "../../../ui/numeralFormat"; import React from "react"; +import Typography from "@mui/material/Typography"; +import { + Table, + TableBody, + TableCell, + TableRow, +} from "@mui/material"; -import { StatsTable } from "../../../ui/React/StatsTable"; +import { Settings } from "../../../Settings/Settings"; +import { formatNumber } from "../../../utils/StringHelperFunctions"; +import { characterOverviewStyles as useStyles } from "../../../ui/React/CharacterOverview"; + +import { Money } from "../../../ui/React/Money"; +import { MoneyRate } from "../../../ui/React/MoneyRate"; +import { ReputationRate } from "../../../ui/React/ReputationRate"; +import { SleeveTaskType } from "../SleeveTaskTypesEnum"; +import { use } from "../../../ui/Context"; + +interface ITableRowData { + content?: string; + level?: number; + exp?: number; +} + +export const generateTableRow = ( + name: string, + color: string, + // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types + classes: any, + data: ITableRowData +): React.ReactElement => { + let content; + + if (data.content !== undefined) { + content = data.content; + } else if (data.level !== undefined && data.exp !== undefined) { + content = `${formatNumber(data.level, 0)} (${numeralWrapper.formatExp(data.exp)} exp)`; + } else if (data.level !== undefined && data.exp === undefined) { + content = `${formatNumber(data.level, 0)}`; + } + + return ( + + + {name} + + + + {content} + + + + ) +} interface IProps { sleeve: Sleeve; } export function StatsElement(props: IProps): React.ReactElement { - const rows = [ - [ - "HP: ", - <> - {numeralWrapper.formatHp(props.sleeve.hp)} / {numeralWrapper.formatHp(props.sleeve.max_hp)} - , - ], - ["City: ", <>{props.sleeve.city}], - ["Hacking: ", <>{numeralWrapper.formatSkill(props.sleeve.hacking)}], - ["Strength: ", <>{numeralWrapper.formatSkill(props.sleeve.strength)}], - ["Defense: ", <>{numeralWrapper.formatSkill(props.sleeve.defense)}], - ["Dexterity: ", <>{numeralWrapper.formatSkill(props.sleeve.dexterity)}], - ["Agility: ", <>{numeralWrapper.formatSkill(props.sleeve.agility)}], - ["Charisma: ", <>{numeralWrapper.formatSkill(props.sleeve.charisma)}], - ["Shock: ", <>{numeralWrapper.formatSleeveShock(100 - props.sleeve.shock)}], - ["Sync: ", <>{numeralWrapper.formatSleeveSynchro(props.sleeve.sync)}], - ["Memory: ", <>{numeralWrapper.formatSleeveMemory(props.sleeve.memory)}], - ]; - return ; + const classes = useStyles(); + + return ( + + + {generateTableRow("City", Settings.theme.primary, classes, { + content: props.sleeve.city + })} + {generateTableRow("HP", Settings.theme.hp, classes, { + content: `${numeralWrapper.formatHp(props.sleeve.hp)} / ${numeralWrapper.formatHp(props.sleeve.max_hp)}` + })} + {generateTableRow("Hacking", Settings.theme.hack, classes, { + level: props.sleeve.hacking, + exp: props.sleeve.hacking_exp + })} + {generateTableRow("Strength", Settings.theme.combat, classes, { + level: props.sleeve.strength, + exp: props.sleeve.strength_exp + })} + {generateTableRow("Defense", Settings.theme.combat, classes, { + level: props.sleeve.defense, + exp: props.sleeve.defense_exp + })} + {generateTableRow("Dexterity", Settings.theme.combat, classes, { + level: props.sleeve.dexterity, + exp: props.sleeve.dexterity_exp + })} + {generateTableRow("Agility", Settings.theme.combat, classes, { + level: props.sleeve.agility, + exp: props.sleeve.agility_exp + })} + {generateTableRow("Charisma", Settings.theme.cha, classes, { + level: props.sleeve.charisma, + exp: props.sleeve.charisma_exp + })} + + +
+
+
+ {generateTableRow("Shock", Settings.theme.primary, classes, { + content: numeralWrapper.formatSleeveShock(100 - props.sleeve.shock) + })} + {generateTableRow("Sync", Settings.theme.primary, classes, { + content: numeralWrapper.formatSleeveSynchro(props.sleeve.sync) + })} + {generateTableRow("Memory", Settings.theme.primary, classes, { + content: numeralWrapper.formatSleeveMemory(props.sleeve.memory) + })} +
+
+ ) } + +export function EarningsElement(props: IProps): React.ReactElement { + const classes = useStyles(); + const player = use.Player(); + + let data: any[][] = []; + if (props.sleeve.currentTask === SleeveTaskType.Crime) { + data = [ + [`Money`, <> (on success)], + [`Hacking Exp`, `${numeralWrapper.formatExp(props.sleeve.gainRatesForTask.hack)} (2x on success)`], + [`Strength Exp`, `${numeralWrapper.formatExp(props.sleeve.gainRatesForTask.str)} (2x on success)`], + [`Defense Exp`, `${numeralWrapper.formatExp(props.sleeve.gainRatesForTask.def)} (2x on success)`], + [`Dexterity Exp`, `${numeralWrapper.formatExp(props.sleeve.gainRatesForTask.dex)} (2x on success)`], + [`Agility Exp`, `${numeralWrapper.formatExp(props.sleeve.gainRatesForTask.agi)} (2x on success)`], + [`Charisma Exp`, `${numeralWrapper.formatExp(props.sleeve.gainRatesForTask.cha)} (2x on success)`], + ]; + } else { + data = [ + [`Money:`, ], + [`Hacking Exp:`, `${numeralWrapper.formatExp(5 * props.sleeve.gainRatesForTask.hack)} / sec`], + [`Strength Exp:`, `${numeralWrapper.formatExp(5 * props.sleeve.gainRatesForTask.str)} / sec`], + [`Defense Exp:`, `${numeralWrapper.formatExp(5 * props.sleeve.gainRatesForTask.def)} / sec`], + [`Dexterity Exp:`, `${numeralWrapper.formatExp(5 * props.sleeve.gainRatesForTask.dex)} / sec`], + [`Agility Exp:`, `${numeralWrapper.formatExp(5 * props.sleeve.gainRatesForTask.agi)} / sec`], + [`Charisma Exp:`, `${numeralWrapper.formatExp(5 * props.sleeve.gainRatesForTask.cha)} / sec`], + ]; + if (props.sleeve.currentTask === SleeveTaskType.Company || props.sleeve.currentTask === SleeveTaskType.Faction) { + const repGain: number = props.sleeve.getRepGain(player); + data.push([`Reputation:`, ]); + } + } + + return ( + + + + + + Earnings + + + + {data.map(([a, b]) => ( + + + {a} + + + {b} + + + ))} + +
+ ) +} \ No newline at end of file diff --git a/src/PersonObjects/Sleeve/ui/TaskSelector.tsx b/src/PersonObjects/Sleeve/ui/TaskSelector.tsx index 724352aaa..bff6af55e 100644 --- a/src/PersonObjects/Sleeve/ui/TaskSelector.tsx +++ b/src/PersonObjects/Sleeve/ui/TaskSelector.tsx @@ -278,7 +278,7 @@ export function TaskSelector(props: IProps): React.ReactElement { return ( <> - {validActions.map((task) => ( {task} @@ -287,8 +287,7 @@ export function TaskSelector(props: IProps): React.ReactElement { {!(details.first.length === 1 && details.first[0] === "------") && ( <> -
- {details.first.map((detail) => ( {detail} @@ -299,8 +298,7 @@ export function TaskSelector(props: IProps): React.ReactElement { )} {!(details2.length === 1 && details2[0] === "------") && ( <> -
- {details2.map((detail) => ( {detail} From 8ce1660f8ad414fa0561a935eb0825c9dc87f006 Mon Sep 17 00:00:00 2001 From: nickofolas Date: Thu, 10 Mar 2022 22:21:02 -0600 Subject: [PATCH 2/8] Fix missing newline at EOL --- src/PersonObjects/Sleeve/ui/StatsElement.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/PersonObjects/Sleeve/ui/StatsElement.tsx b/src/PersonObjects/Sleeve/ui/StatsElement.tsx index d348280e6..8a3e1197d 100644 --- a/src/PersonObjects/Sleeve/ui/StatsElement.tsx +++ b/src/PersonObjects/Sleeve/ui/StatsElement.tsx @@ -169,4 +169,4 @@ export function EarningsElement(props: IProps): React.ReactElement { ) -} \ No newline at end of file +} From 7b309c2624502eb6fb42ad9e1423f6e2f43ec0fd Mon Sep 17 00:00:00 2001 From: nickofolas Date: Thu, 10 Mar 2022 22:47:18 -0600 Subject: [PATCH 3/8] Refactor sleeve stats row to JSX element --- src/PersonObjects/Sleeve/ui/StatsElement.tsx | 87 +++++++++----------- 1 file changed, 41 insertions(+), 46 deletions(-) diff --git a/src/PersonObjects/Sleeve/ui/StatsElement.tsx b/src/PersonObjects/Sleeve/ui/StatsElement.tsx index 8a3e1197d..d21352fbf 100644 --- a/src/PersonObjects/Sleeve/ui/StatsElement.tsx +++ b/src/PersonObjects/Sleeve/ui/StatsElement.tsx @@ -25,13 +25,14 @@ interface ITableRowData { exp?: number; } -export const generateTableRow = ( - name: string, - color: string, - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types - classes: any, - data: ITableRowData -): React.ReactElement => { +interface IStatsRowProps { + name: string; + color: string; + classes: any; + data: ITableRowData; +} + +export const SleeveStatsRow = ({ name, color, classes, data }: IStatsRowProps): React.ReactElement => { let content; if (data.content !== undefined) { @@ -66,50 +67,44 @@ export function StatsElement(props: IProps): React.ReactElement { return ( - {generateTableRow("City", Settings.theme.primary, classes, { - content: props.sleeve.city - })} - {generateTableRow("HP", Settings.theme.hp, classes, { - content: `${numeralWrapper.formatHp(props.sleeve.hp)} / ${numeralWrapper.formatHp(props.sleeve.max_hp)}` - })} - {generateTableRow("Hacking", Settings.theme.hack, classes, { - level: props.sleeve.hacking, - exp: props.sleeve.hacking_exp - })} - {generateTableRow("Strength", Settings.theme.combat, classes, { - level: props.sleeve.strength, - exp: props.sleeve.strength_exp - })} - {generateTableRow("Defense", Settings.theme.combat, classes, { - level: props.sleeve.defense, - exp: props.sleeve.defense_exp - })} - {generateTableRow("Dexterity", Settings.theme.combat, classes, { - level: props.sleeve.dexterity, - exp: props.sleeve.dexterity_exp - })} - {generateTableRow("Agility", Settings.theme.combat, classes, { - level: props.sleeve.agility, - exp: props.sleeve.agility_exp - })} - {generateTableRow("Charisma", Settings.theme.cha, classes, { - level: props.sleeve.charisma, - exp: props.sleeve.charisma_exp - })} + + + + + + + +
- {generateTableRow("Shock", Settings.theme.primary, classes, { - content: numeralWrapper.formatSleeveShock(100 - props.sleeve.shock) - })} - {generateTableRow("Sync", Settings.theme.primary, classes, { - content: numeralWrapper.formatSleeveSynchro(props.sleeve.sync) - })} - {generateTableRow("Memory", Settings.theme.primary, classes, { - content: numeralWrapper.formatSleeveMemory(props.sleeve.memory) - })} + + +
) From 07a61c38a4d0626e6fc5efdac4a6139a5ac28105 Mon Sep 17 00:00:00 2001 From: nickofolas Date: Thu, 10 Mar 2022 23:02:32 -0600 Subject: [PATCH 4/8] Clean up imports --- src/PersonObjects/Sleeve/ui/SleeveElem.tsx | 31 ++++++++++---------- src/PersonObjects/Sleeve/ui/SleeveRoot.tsx | 15 ++++++---- src/PersonObjects/Sleeve/ui/StatsElement.tsx | 11 +++---- 3 files changed, 30 insertions(+), 27 deletions(-) diff --git a/src/PersonObjects/Sleeve/ui/SleeveElem.tsx b/src/PersonObjects/Sleeve/ui/SleeveElem.tsx index 61c9f5cbc..5d73a762d 100644 --- a/src/PersonObjects/Sleeve/ui/SleeveElem.tsx +++ b/src/PersonObjects/Sleeve/ui/SleeveElem.tsx @@ -1,30 +1,29 @@ import React, { useState } from "react"; +import { + Box, + Paper, + Typography, + Button, + Tooltip +} from "@mui/material"; + +import { CONSTANTS } from "../../../Constants"; +import { Crimes } from "../../../Crime/Crimes"; +import { numeralWrapper } from "../../../ui/numeralFormat"; +import { createProgressBarText } from "../../../utils/helpers/createProgressBarText"; +import { use } from "../../../ui/Context"; +import { FactionWorkType } from "../../../Faction/FactionWorkTypeEnum"; + import { Sleeve } from "../Sleeve"; import { SleeveTaskType } from "../SleeveTaskTypesEnum"; -import { CONSTANTS } from "../../../Constants"; - -import { Crimes } from "../../../Crime/Crimes"; - -import { numeralWrapper } from "../../../ui/numeralFormat"; - -import { createProgressBarText } from "../../../utils/helpers/createProgressBarText"; - import { SleeveAugmentationsModal } from "./SleeveAugmentationsModal"; import { TravelModal } from "./TravelModal"; -import { use } from "../../../ui/Context"; import { StatsElement, EarningsElement } from "./StatsElement"; import { MoreStatsModal } from "./MoreStatsModal"; import { MoreEarningsModal } from "./MoreEarningsModal"; import { TaskSelector } from "./TaskSelector"; -import { FactionWorkType } from "../../../Faction/FactionWorkTypeEnum"; - -import Typography from "@mui/material/Typography"; -import Paper from "@mui/material/Paper"; -import { Box } from "@mui/material"; -import Button from "@mui/material/Button"; -import Tooltip from "@mui/material/Tooltip"; interface IProps { sleeve: Sleeve; diff --git a/src/PersonObjects/Sleeve/ui/SleeveRoot.tsx b/src/PersonObjects/Sleeve/ui/SleeveRoot.tsx index a41a59e87..c1ea67251 100644 --- a/src/PersonObjects/Sleeve/ui/SleeveRoot.tsx +++ b/src/PersonObjects/Sleeve/ui/SleeveRoot.tsx @@ -1,13 +1,16 @@ import React, { useState, useEffect } from "react"; +import { + Box, + Typography, + Button, + Link +} from "@mui/material"; + +import { use } from "../../../ui/Context"; + import { SleeveElem } from "./SleeveElem"; import { FAQModal } from "./FAQModal"; -import { use } from "../../../ui/Context"; - -import Typography from "@mui/material/Typography"; -import Button from "@mui/material/Button"; -import Link from "@mui/material/Link"; -import { Box } from "@mui/material"; export function SleeveRoot(): React.ReactElement { const player = use.Player(); diff --git a/src/PersonObjects/Sleeve/ui/StatsElement.tsx b/src/PersonObjects/Sleeve/ui/StatsElement.tsx index d21352fbf..c28b898d1 100644 --- a/src/PersonObjects/Sleeve/ui/StatsElement.tsx +++ b/src/PersonObjects/Sleeve/ui/StatsElement.tsx @@ -1,24 +1,25 @@ -import { Sleeve } from "../Sleeve"; -import { numeralWrapper } from "../../../ui/numeralFormat"; import React from "react"; -import Typography from "@mui/material/Typography"; + import { + Typography, Table, TableBody, TableCell, TableRow, } from "@mui/material"; +import { numeralWrapper } from "../../../ui/numeralFormat"; import { Settings } from "../../../Settings/Settings"; import { formatNumber } from "../../../utils/StringHelperFunctions"; import { characterOverviewStyles as useStyles } from "../../../ui/React/CharacterOverview"; - import { Money } from "../../../ui/React/Money"; import { MoneyRate } from "../../../ui/React/MoneyRate"; import { ReputationRate } from "../../../ui/React/ReputationRate"; -import { SleeveTaskType } from "../SleeveTaskTypesEnum"; import { use } from "../../../ui/Context"; +import { Sleeve } from "../Sleeve"; +import { SleeveTaskType } from "../SleeveTaskTypesEnum"; + interface ITableRowData { content?: string; level?: number; From 230d68aab218cacd3232863517ca590162b04fe3 Mon Sep 17 00:00:00 2001 From: nickofolas Date: Sat, 12 Mar 2022 15:49:07 -0600 Subject: [PATCH 5/8] Implement common stats row element --- src/Gang/ui/EquipmentsSubpage.tsx | 16 ++-- src/Gang/ui/GangMemberStats.tsx | 36 ++------- src/PersonObjects/Sleeve/ui/StatsElement.tsx | 82 +++----------------- src/ui/React/StatsRow.tsx | 49 ++++++++++++ 4 files changed, 75 insertions(+), 108 deletions(-) create mode 100644 src/ui/React/StatsRow.tsx diff --git a/src/Gang/ui/EquipmentsSubpage.tsx b/src/Gang/ui/EquipmentsSubpage.tsx index b2f53c0d8..664fe9c13 100644 --- a/src/Gang/ui/EquipmentsSubpage.tsx +++ b/src/Gang/ui/EquipmentsSubpage.tsx @@ -3,7 +3,6 @@ */ import React, { useState } from "react"; import { useGang } from "./Context"; -import { generateTableRow } from "./GangMemberStats"; import Typography from "@mui/material/Typography"; import Button from "@mui/material/Button"; @@ -22,7 +21,7 @@ import { GangMember } from "../GangMember"; import { UpgradeType } from "../data/upgrades"; import { use } from "../../ui/Context"; import { Settings } from "../../Settings/Settings"; -import { characterOverviewStyles as useStyles } from "../../ui/React/CharacterOverview"; +import { StatsRow } from "../../ui/React/StatsRow"; interface INextRevealProps { upgrades: string[]; @@ -91,7 +90,6 @@ interface IPanelProps { } function GangMemberUpgradePanel(props: IPanelProps): React.ReactElement { - const classes = useStyles(); const gang = useGang(); const player = use.Player(); const setRerender = useState(false)[1]; @@ -178,12 +176,12 @@ function GangMemberUpgradePanel(props: IPanelProps): React.ReactElement { > - {generateTableRow("Hacking", props.member.hack, props.member.hack_exp, Settings.theme.hack, classes)} - {generateTableRow("Strength", props.member.str, props.member.str_exp, Settings.theme.combat, classes)} - {generateTableRow("Defense", props.member.def, props.member.def_exp, Settings.theme.combat, classes)} - {generateTableRow("Dexterity", props.member.dex, props.member.dex_exp, Settings.theme.combat, classes)} - {generateTableRow("Agility", props.member.agi, props.member.agi_exp, Settings.theme.combat, classes)} - {generateTableRow("Charisma", props.member.cha, props.member.cha_exp, Settings.theme.cha, classes)} + + + + + +
diff --git a/src/Gang/ui/GangMemberStats.tsx b/src/Gang/ui/GangMemberStats.tsx index 859057837..66fe16582 100644 --- a/src/Gang/ui/GangMemberStats.tsx +++ b/src/Gang/ui/GangMemberStats.tsx @@ -17,36 +17,14 @@ import { import { numeralWrapper } from "../../ui/numeralFormat"; import { GangMember } from "../GangMember"; import { Settings } from "../../Settings/Settings"; -import { formatNumber } from "../../utils/StringHelperFunctions"; import { MoneyRate } from "../../ui/React/MoneyRate"; +import { StatsRow } from "../../ui/React/StatsRow"; import { characterOverviewStyles as useStyles } from "../../ui/React/CharacterOverview"; interface IProps { member: GangMember; } -export const generateTableRow = ( - name: string, - level: number, - exp: number, - color: string, - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types - classes: any -): React.ReactElement => { - return ( - - - {name} - - - - {formatNumber(level, 0)} ({numeralWrapper.formatExp(exp)} exp) - - - - ) -} - export function GangMemberStats(props: IProps): React.ReactElement { const classes = useStyles(); @@ -102,12 +80,12 @@ export function GangMemberStats(props: IProps): React.ReactElement { > - {generateTableRow("Hacking", props.member.hack, props.member.hack_exp, Settings.theme.hack, classes)} - {generateTableRow("Strength", props.member.str, props.member.str_exp, Settings.theme.combat, classes)} - {generateTableRow("Defense", props.member.def, props.member.def_exp, Settings.theme.combat, classes)} - {generateTableRow("Dexterity", props.member.dex, props.member.dex_exp, Settings.theme.combat, classes)} - {generateTableRow("Agility", props.member.agi, props.member.agi_exp, Settings.theme.combat, classes)} - {generateTableRow("Charisma", props.member.cha, props.member.cha_exp, Settings.theme.cha, classes)} + + + + + +
diff --git a/src/PersonObjects/Sleeve/ui/StatsElement.tsx b/src/PersonObjects/Sleeve/ui/StatsElement.tsx index c28b898d1..901348a8e 100644 --- a/src/PersonObjects/Sleeve/ui/StatsElement.tsx +++ b/src/PersonObjects/Sleeve/ui/StatsElement.tsx @@ -10,7 +10,7 @@ import { import { numeralWrapper } from "../../../ui/numeralFormat"; import { Settings } from "../../../Settings/Settings"; -import { formatNumber } from "../../../utils/StringHelperFunctions"; +import { StatsRow } from "../../../ui/React/StatsRow"; import { characterOverviewStyles as useStyles } from "../../../ui/React/CharacterOverview"; import { Money } from "../../../ui/React/Money"; import { MoneyRate } from "../../../ui/React/MoneyRate"; @@ -20,44 +20,6 @@ import { use } from "../../../ui/Context"; import { Sleeve } from "../Sleeve"; import { SleeveTaskType } from "../SleeveTaskTypesEnum"; -interface ITableRowData { - content?: string; - level?: number; - exp?: number; -} - -interface IStatsRowProps { - name: string; - color: string; - classes: any; - data: ITableRowData; -} - -export const SleeveStatsRow = ({ name, color, classes, data }: IStatsRowProps): React.ReactElement => { - let content; - - if (data.content !== undefined) { - content = data.content; - } else if (data.level !== undefined && data.exp !== undefined) { - content = `${formatNumber(data.level, 0)} (${numeralWrapper.formatExp(data.exp)} exp)`; - } else if (data.level !== undefined && data.exp === undefined) { - content = `${formatNumber(data.level, 0)}`; - } - - return ( - - - {name} - - - - {content} - - - - ) -} - interface IProps { sleeve: Sleeve; } @@ -68,44 +30,24 @@ export function StatsElement(props: IProps): React.ReactElement { return (
- - + - - - - - - + + + + + +
- - - + + +
) diff --git a/src/ui/React/StatsRow.tsx b/src/ui/React/StatsRow.tsx new file mode 100644 index 000000000..ce623ccd3 --- /dev/null +++ b/src/ui/React/StatsRow.tsx @@ -0,0 +1,49 @@ +import React from "react"; + +import { + Typography, + TableCell, + TableRow, +} from "@mui/material"; + +import { numeralWrapper } from "../numeralFormat"; +import { formatNumber } from "../../utils/StringHelperFunctions"; +import { characterOverviewStyles as useStyles } from "./CharacterOverview"; + +interface ITableRowData { + content?: string; + level?: number; + exp?: number; +} + +interface IProps { + name: string; + color: string; + classes?: any; + data: ITableRowData; +} + +export const StatsRow = ({ name, color, classes = useStyles(), data }: IProps): React.ReactElement => { + let content; + + if (data.content !== undefined) { + content = data.content; + } else if (data.level !== undefined && data.exp !== undefined) { + content = `${formatNumber(data.level, 0)} (${numeralWrapper.formatExp(data.exp)} exp)`; + } else if (data.level !== undefined && data.exp === undefined) { + content = `${formatNumber(data.level, 0)}`; + } + + return ( + + + {name} + + + + {content} + + + + ) +} From a205f42d88063e36f117511d7c4c8a06c0db1b46 Mon Sep 17 00:00:00 2001 From: nickofolas Date: Wed, 16 Mar 2022 17:35:04 -0500 Subject: [PATCH 6/8] Finalize (?) sleeves --- src/PersonObjects/Sleeve/ui/SleeveRoot.tsx | 36 +++++++++++----------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/src/PersonObjects/Sleeve/ui/SleeveRoot.tsx b/src/PersonObjects/Sleeve/ui/SleeveRoot.tsx index c1ea67251..5d553a495 100644 --- a/src/PersonObjects/Sleeve/ui/SleeveRoot.tsx +++ b/src/PersonObjects/Sleeve/ui/SleeveRoot.tsx @@ -4,7 +4,7 @@ import { Box, Typography, Button, - Link + Container } from "@mui/material"; import { use } from "../../../ui/Context"; @@ -27,25 +27,25 @@ export function SleeveRoot(): React.ReactElement { return ( <> - Sleeves - - Duplicate Sleeves are MK-V Synthoids (synthetic androids) into which your consciousness has been copied. In - other words, these Synthoids contain a perfect duplicate of your mind. -
-
- Sleeves can be used to perform different tasks synchronously. -
-
-
+ + Sleeves + + Duplicate Sleeves are MK-V Synthoids (synthetic androids) into which your consciousness has been copied. In + other words, these Synthoids contain a perfect duplicate of your mind. +
+
+ Sleeves can be used to perform different tasks synchronously. +
+
+
+ +
- - Documentation - - + + {player.sleeves.map((sleeve, i) => ( ))} From a032ee16be3b0a5942c0ac85590fe7a3a4bd2266 Mon Sep 17 00:00:00 2001 From: nickofolas Date: Wed, 16 Mar 2022 18:20:23 -0500 Subject: [PATCH 7/8] Update gang territory UI --- src/Gang/ui/TerritoryInfoModal.tsx | 54 +++++++++ src/Gang/ui/TerritorySubpage.tsx | 179 ++++++++++++----------------- 2 files changed, 127 insertions(+), 106 deletions(-) create mode 100644 src/Gang/ui/TerritoryInfoModal.tsx diff --git a/src/Gang/ui/TerritoryInfoModal.tsx b/src/Gang/ui/TerritoryInfoModal.tsx new file mode 100644 index 000000000..3c4c74e16 --- /dev/null +++ b/src/Gang/ui/TerritoryInfoModal.tsx @@ -0,0 +1,54 @@ +import React from "react"; + +import Typography from "@mui/material/Typography"; + +import { Modal } from "../../ui/React/Modal"; + +interface IProps { + open: boolean; + onClose: () => void; +} + +export const TerritoryInfoModal = ({ open, onClose }: IProps): React.ReactElement => { + return ( + + <> + + Clashing + + + Every ~20 seconds, your gang has a chance to 'clash' with other gangs. Your chance to win a clash depends on + your gang's power, which is listed in the display below. Your gang's power slowly accumulates over time. The + accumulation rate is determined by the stats of all Gang members you have assigned to the 'Territory Warfare' + task. Gang members that are not assigned to this task do not contribute to your gang's power. Your gang also + loses a small amount of power whenever you lose a clash. +
+
+ NOTE: Gang members assigned to 'Territory Warfare' can be killed during clashes. This can happen regardless of + whether you win or lose the clash. A gang member being killed results in both respect and power loss for your + gang. +
+
+ + Territory + + + The amount of territory you have affects all aspects of your Gang members' production, including money, respect, + and wanted level. It is very beneficial to have high territory control. +
+
+ To increase your chances of winning territory assign gang members to "Territory Warfare", this will build your + gang power. Then enable "Engage in Territory Warfare" to start fighting over territory. +
+
+ + Territory Clash Chance + + + This percentage represents the chance you have of 'clashing' with with another gang. If you do not wish to + gain/lose territory, then keep this percentage at 0% by not engaging in territory warfare. + + +
+ ); +} diff --git a/src/Gang/ui/TerritorySubpage.tsx b/src/Gang/ui/TerritorySubpage.tsx index 434bf1c3e..9a52ea2ab 100644 --- a/src/Gang/ui/TerritorySubpage.tsx +++ b/src/Gang/ui/TerritorySubpage.tsx @@ -1,133 +1,100 @@ /** * React Component for the territory subpage. */ -import React from "react"; +import React, { useState } from "react"; + +import { + Container, + Button, + Paper, + Box, + Tooltip, + Switch, + FormControlLabel, + Typography +} from "@mui/material"; +import { Help } from "@mui/icons-material"; + import { numeralWrapper } from "../../ui/numeralFormat"; import { formatNumber } from "../../utils/StringHelperFunctions"; -import { AllGangs } from "../AllGangs"; -import { useGang } from "./Context"; -import Typography from "@mui/material/Typography"; -import FormControlLabel from "@mui/material/FormControlLabel"; -import Switch from "@mui/material/Switch"; -import Tooltip from "@mui/material/Tooltip"; -import Box from "@mui/material/Box"; -import Paper from "@mui/material/Paper"; +import { AllGangs } from "../AllGangs"; + +import { useGang } from "./Context"; +import { TerritoryInfoModal } from "./TerritoryInfoModal"; export function TerritorySubpage(): React.ReactElement { const gang = useGang(); const gangNames = Object.keys(AllGangs).filter((g) => g != gang.facName); + const [infoOpen, setInfoOpen] = useState(false); return ( - <> + This page shows how much territory your Gang controls. This statistic is listed as a percentage, which represents how much of the total territory you control. -
-
- Every ~20 seconds, your gang has a chance to 'clash' with other gangs. Your chance to win a clash depends on - your gang's power, which is listed in the display below. Your gang's power slowly accumulates over time. The - accumulation rate is determined by the stats of all Gang members you have assigned to the 'Territory Warfare' - task. Gang members that are not assigned to this task do not contribute to your gang's power. Your gang also - loses a small amount of power whenever you lose a clash. -
-
- NOTE: Gang members assigned to 'Territory Warfare' can be killed during clashes. This can happen regardless of - whether you win or lose the clash. A gang member being killed results in both respect and power loss for your - gang. -
-
- The amount of territory you have affects all aspects of your Gang members' production, including money, respect, - and wanted level. It is very beneficial to have high territory control. -
-
- To increase your chances of winning territory assign gang members to "Territory Warfare", this will build your - gang power. Then enable "Engage in Territory Warfare" to start fighting over territory.
- setInfoOpen(true)} sx={{ my: 1 }}> + + About Gang Territory + + + + + {gang.facName} (Your gang) + + + (gang.territoryWarfareEngaged = event.target.checked)} - /> - } - label={ - - Engaging in Territory Warfare sets your clash chance to 100%. Disengaging will cause your clash chance - to gradually decrease until it reaches 0%. - - } - > + />} + label={ + Engaging in Territory Warfare sets your clash chance to 100%. Disengaging will cause your clash chance + to gradually decrease until it reaches 0%. + }> Engage in Territory Warfare - - } - /> -
- - - This percentage represents the chance you have of 'clashing' with with another gang. If you do not wish to - gain/lose territory, then keep this percentage at 0% by not engaging in territory warfare. - - } - > - - Territory Clash Chance: {numeralWrapper.formatPercentage(gang.territoryClashChance, 3)} - - - -
- } /> +
+ (gang.notifyMemberDeath = event.target.checked)} - /> - } - label={ - - If this is enabled, then you will receive a pop-up notifying you whenever one of your Gang Members dies - in a territory clash. - - } - > + />} + label={ + If this is enabled, then you will receive a pop-up notifying you whenever one of your Gang Members dies + in a territory clash. + }> Notify about Gang Member Deaths - - } - /> -
- +
} /> + - - {gang.facName} - -
- Power: {formatNumber(AllGangs[gang.facName].power, 6)} -
- Territory: {formatTerritory(AllGangs[gang.facName].territory)}% -
-
+ Territory Clash Chance: {numeralWrapper.formatPercentage(gang.territoryClashChance, 3)}
+ Power: {formatNumber(AllGangs[gang.facName].power, 3)}
+ Territory: {formatTerritory(AllGangs[gang.facName].territory)}%
+
+ {gangNames.map((name) => ( ))} - - + + setInfoOpen(false)} /> +
); } function formatTerritory(n: number): string { const v = n * 100; + const precision = 3; if (v <= 0) { - return formatNumber(0, 2); + return formatNumber(0, precision); } else if (v >= 100) { - return formatNumber(100, 2); + return formatNumber(100, precision); } else { - return formatNumber(v, 2); + return formatNumber(v, precision); } } @@ -141,15 +108,15 @@ function OtherGangTerritory(props: ITerritoryProps): React.ReactElement { const power = AllGangs[props.name].power; const clashVictoryChance = playerPower / (power + playerPower); return ( - - {props.name} -
- Power: {formatNumber(power, 6)} -
- Territory: {formatTerritory(AllGangs[props.name].territory)}%
- Chance to win clash with this gang: {numeralWrapper.formatPercentage(clashVictoryChance, 3)} -
-
-
+ + + {props.name} + + + Power: {formatNumber(power, 3)}
+ Territory: {formatTerritory(AllGangs[props.name].territory)}%
+ Clash Win Chance: {numeralWrapper.formatPercentage(clashVictoryChance, 3)} +
+
); } From ea61c36790a885870d1be241c9f963642414efbc Mon Sep 17 00:00:00 2001 From: nickofolas Date: Wed, 16 Mar 2022 18:29:15 -0500 Subject: [PATCH 8/8] Modal content proofreading --- src/Gang/ui/TerritoryInfoModal.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Gang/ui/TerritoryInfoModal.tsx b/src/Gang/ui/TerritoryInfoModal.tsx index 3c4c74e16..cbd8640f0 100644 --- a/src/Gang/ui/TerritoryInfoModal.tsx +++ b/src/Gang/ui/TerritoryInfoModal.tsx @@ -37,15 +37,15 @@ export const TerritoryInfoModal = ({ open, onClose }: IProps): React.ReactElemen and wanted level. It is very beneficial to have high territory control.

- To increase your chances of winning territory assign gang members to "Territory Warfare", this will build your - gang power. Then enable "Engage in Territory Warfare" to start fighting over territory. + To increase your chances of winning territory, assign gang members to "Territory Warfare". This will build your + gang power. Then, enable "Engage in Territory Warfare" to start fighting over territory.
Territory Clash Chance - This percentage represents the chance you have of 'clashing' with with another gang. If you do not wish to + This percentage represents the chance you have of 'clashing' with another gang. If you do not wish to gain/lose territory, then keep this percentage at 0% by not engaging in territory warfare.