+Are you sure you want to ascend this member? They will lose all of
+their non-Augmentation upgrades and their stats will reset back to 1.
+
+Furthermore, your gang will lose {numeralWrapper.formatRespect(props.member.earnedRespect)} respect
+
+In return, they will gain the following permanent boost to stat multipliers:
+Hacking: +{numeralWrapper.formatPercentage(ascendBenefits.hack/100)}
+Strength: +{numeralWrapper.formatPercentage(ascendBenefits.str/100)}
+Defense: +{numeralWrapper.formatPercentage(ascendBenefits.def/100)}
+Dexterity: +{numeralWrapper.formatPercentage(ascendBenefits.dex/100)}
+Agility: +{numeralWrapper.formatPercentage(ascendBenefits.agi/100)}
+Charisma: +{numeralWrapper.formatPercentage(ascendBenefits.cha/100)}
+
+
+
+ >);
+}
\ No newline at end of file
diff --git a/src/Gang/ui/BonusTime.tsx b/src/Gang/ui/BonusTime.tsx
new file mode 100644
index 000000000..693964daf
--- /dev/null
+++ b/src/Gang/ui/BonusTime.tsx
@@ -0,0 +1,26 @@
+import * as React from "react";
+import { Gang } from "../Gang";
+import { CONSTANTS } from "../../Constants";
+import { convertTimeMsToTimeElapsedString } from "../../../utils/StringHelperFunctions";
+
+interface IProps {
+ gang: Gang;
+}
+
+export function BonusTime(props: IProps): React.ReactElement {
+ const CyclerPerSecond = 1000 / CONSTANTS._idleSpeed;
+ if (props.gang.storedCycles / CyclerPerSecond*1000 <= 5000) return (<>>);
+ const bonusMillis = props.gang.storedCycles / CyclerPerSecond * 1000;
+ return (<>
+
+ Bonus time: {convertTimeMsToTimeElapsedString(bonusMillis)}
+
+ You gain bonus time while offline or when the game is inactive
+ (e.g. when the tab is throttled by the browser). Bonus time
+ makes the Gang mechanic progress faster, up to 5x the normal
+ speed.
+
+
+
+ >);
+}
\ No newline at end of file
diff --git a/src/Gang/ui/GangMemberAccordion.tsx b/src/Gang/ui/GangMemberAccordion.tsx
new file mode 100644
index 000000000..e2daa32eb
--- /dev/null
+++ b/src/Gang/ui/GangMemberAccordion.tsx
@@ -0,0 +1,19 @@
+import React from "react";
+import { Gang } from "../Gang";
+import { GangMember } from "../GangMember";
+import { Accordion } from "../../ui/React/Accordion";
+import { GangMemberAccordionContent } from "./GangMemberAccordionContent";
+
+interface IProps {
+ gang: Gang;
+ member: GangMember;
+}
+
+export function GangMemberAccordion(props: IProps): React.ReactElement {
+ return {props.member.name}>}
+ panelContent={} />
+}
\ No newline at end of file
diff --git a/src/Gang/ui/GangMemberAccordionContent.tsx b/src/Gang/ui/GangMemberAccordionContent.tsx
index 573f95738..4b0ca2d08 100644
--- a/src/Gang/ui/GangMemberAccordionContent.tsx
+++ b/src/Gang/ui/GangMemberAccordionContent.tsx
@@ -1,7 +1,7 @@
import React, { useState } from "react";
-import { Panel1 } from "./Panel1";
-import { Panel2 } from "./Panel2";
-import { Panel3 } from "./Panel3";
+import { GangMemberStats } from "./GangMemberStats";
+import { TaskSelector } from "./TaskSelector";
+import { TaskDescription } from "./TaskDescription";
import { Gang } from "../Gang";
import { GangMember } from "../GangMember";
@@ -14,13 +14,16 @@ export function GangMemberAccordionContent(props: IProps): React.ReactElement {
const setRerender = useState(false)[1];
return (<>
>);
diff --git a/src/Gang/ui/Panel1.tsx b/src/Gang/ui/GangMemberStats.tsx
similarity index 56%
rename from src/Gang/ui/Panel1.tsx
rename to src/Gang/ui/GangMemberStats.tsx
index dcb6d5601..a47eda0da 100644
--- a/src/Gang/ui/Panel1.tsx
+++ b/src/Gang/ui/GangMemberStats.tsx
@@ -1,59 +1,21 @@
-import React, { useState, useEffect } from "react";
+import React from "react";
import { dialogBoxCreate } from "../../../utils/DialogBox";
import { formatNumber } from "../../../utils/StringHelperFunctions";
import { numeralWrapper } from "../../ui/numeralFormat";
import { createPopup, removePopup } from "../../ui/React/createPopup";
import { Gang } from "../Gang";
import { GangMember } from "../GangMember";
-
-interface IAscendProps {
- member: GangMember;
- gang: Gang;
- popupId: string;
-}
-
-function ascendPopup(props: IAscendProps): React.ReactElement {
- function confirm(): void {
- props.gang.ascendMember(props.member);
- removePopup(props.popupId);
- }
-
- function cancel(): void {
- removePopup(props.popupId);
- }
-
- const ascendBenefits = props.member.getAscensionResults();
-
- return (<>
-
-Are you sure you want to ascend this member? They will lose all of
-their non-Augmentation upgrades and their stats will reset back to 1.
-
-Furthermore, your gang will lose {numeralWrapper.formatRespect(props.member.earnedRespect)} respect
-
-In return, they will gain the following permanent boost to stat multipliers:
-Hacking: +{numeralWrapper.formatPercentage(ascendBenefits.hack/100)}
-Strength: +{numeralWrapper.formatPercentage(ascendBenefits.str/100)}
-Defense: +{numeralWrapper.formatPercentage(ascendBenefits.def/100)}
-Dexterity: +{numeralWrapper.formatPercentage(ascendBenefits.dex/100)}
-Agility: +{numeralWrapper.formatPercentage(ascendBenefits.agi/100)}
-Charisma: +{numeralWrapper.formatPercentage(ascendBenefits.cha/100)}
-
Discount: -{numeralWrapper.formatPercentage(1 - 1 / props.gang.getDiscount())}
- You get a discount on equipment and upgrades based on your gang's respect and power. More respect and power leads to more discounts.
+
+ You get a discount on equipment and upgrades based on your
+ gang's respect and power. More respect and power leads to more
+ discounts.
+
- {props.gang.members.map((member: GangMember) => )}
+ {props.gang.members.map((member: GangMember) =>
+ )
+ }
>);
}
diff --git a/src/Gang/ui/GangStats.tsx b/src/Gang/ui/GangStats.tsx
index e3d96db23..1037ceff0 100644
--- a/src/Gang/ui/GangStats.tsx
+++ b/src/Gang/ui/GangStats.tsx
@@ -1,125 +1,18 @@
-import React, { useState, useEffect } from "react";
+import React from "react";
import { Factions } from "../../Faction/Factions";
import { Gang } from "../Gang";
-import {
- formatNumber,
- convertTimeMsToTimeElapsedString,
-} from "../../../utils/StringHelperFunctions";
+import { formatNumber } from "../../../utils/StringHelperFunctions";
import { numeralWrapper } from "../../ui/numeralFormat";
import { MoneyRate } from "../../ui/React/MoneyRate";
import { Reputation } from "../../ui/React/Reputation";
import { AllGangs } from "../AllGangs";
-import { GangConstants } from "../data/Constants";
-import { createPopup, removePopup } from "../../ui/React/createPopup";
-import { dialogBoxCreate } from "../../../utils/DialogBox";
-
-interface IRecruitPopupProps {
- gang: Gang;
- popupId: string;
-}
-
-function recruitPopup(props: IRecruitPopupProps): React.ReactElement {
- const [name, setName] = useState("");
-
- function recruit(): void {
- if (name === "") {
- dialogBoxCreate("You must enter a name for your Gang member!");
- return;
- }
- if (!props.gang.canRecruitMember()) {
- dialogBoxCreate("You cannot recruit another Gang member!");
- return;
- }
-
- // At this point, the only way this can fail is if you already
- // have a gang member with the same name
- if (!props.gang.recruitMember(name)) {
- dialogBoxCreate("You already have a gang member with this name!");
- return;
- }
-
- removePopup(props.popupId);
- }
-
- function cancel(): void {
- removePopup(props.popupId);
- }
-
- function onKeyUp(event: React.KeyboardEvent): void {
- if(event.keyCode === 13) recruit();
- if(event.keyCode === 27) cancel();
- }
-
- function onChange(event: React.ChangeEvent): void {
- setName(event.target.value);
- }
-
- return (<>
-
Enter a name for your new Gang member:
-
- Recruit Gang Member
- Cancel
- >);
-}
+import { BonusTime } from "./BonusTime";
interface IProps {
gang: Gang;
}
-function Recruitment(props: IProps): React.ReactElement {
- // Toggle the 'Recruit member button' if valid
- const numMembers = props.gang.members.length;
- const respectCost = props.gang.getRespectNeededToRecruitMember();
-
- if (numMembers >= GangConstants.MaximumGangMembers) {
- return (<>>);
- } else if (props.gang.canRecruitMember()) {
- function onClick(): void {
- const popupId = "recruit-gang-member-popup";
- createPopup(popupId, recruitPopup, {
- gang: props.gang,
- popupId: popupId,
- });
- }
- return (<>
-
- Recruit Gang Member
-
- >);
- }
- return (<>
-
- Recruit Gang Member
-
-
- {formatNumber(respectCost, 2)} respect needed to recruit next member
-
- Bonus time: {convertTimeMsToTimeElapsedString(props.gang.storedCycles / CyclesPerSecond*1000)}
-
- You gain bonus time while offline or when the game is inactive (e.g. when the tab is throttled by the browser). Bonus time makes the Gang mechanic progress faster, up to 5x the normal speed
-
-
-
- >);
-}
-
export function GangStats(props: IProps): React.ReactElement {
const territoryMult = AllGangs[props.gang.facName].territory * 100;
let territoryStr;
@@ -171,7 +64,5 @@ export function GangStats(props: IProps): React.ReactElement {
-
-
>);
}
\ No newline at end of file
diff --git a/src/Gang/ui/ManagementSubpage.tsx b/src/Gang/ui/ManagementSubpage.tsx
index b79c0979a..8ea57ad11 100644
--- a/src/Gang/ui/ManagementSubpage.tsx
+++ b/src/Gang/ui/ManagementSubpage.tsx
@@ -1,4 +1,4 @@
-import React, { useState, useEffect } from "react";
+import React from "react";
import { IPlayer } from "../../PersonObjects/IPlayer";
import { GangStats } from "./GangStats";
import { Gang } from "../Gang";
@@ -12,24 +12,28 @@ interface IProps {
export function ManagementSubpage(props: IProps): React.ReactElement {
return (
- This page is used to manage your gang members and get an overview of your gang's stats.
+ This page is used to manage your gang members and get an overview of
+ your gang's stats.
- If a gang member is not earning much money or respect, the task that you
- have assigned to that member might be too difficult. Consider training that
- member's stats or choosing an easier task. The tasks closer to the
- top of the dropdown list are generally easier. Alternatively, the gang member's
- low production might be due to the fact that your wanted level is too high.
- Consider assigning a few members to the '{props.gang.isHackingGang?"Ethical Hacking":"Vigilante Justice"}'
+ If a gang member is not earning much money or respect, the task that
+ you have assigned to that member might be too difficult. Consider
+ training that member's stats or choosing an easier task. The tasks
+ closer to the top of the dropdown list are generally easier.
+ Alternatively, the gang member's low production might be due to the
+ fact that your wanted level is too high. Consider assigning a few
+ members to the '{props.gang.isHackingGang?"Ethical Hacking":"Vigilante Justice"}'
task to lower your wanted level.
- Installing Augmentations does NOT reset your progress with your Gang.
- Furthermore, after installing Augmentations, you will
- automatically be a member of whatever Faction you created your gang with.
+ Installing Augmentations does NOT reset your progress with your
+ Gang. Furthermore, after installing Augmentations, you will
+ automatically be a member of whatever Faction you created your gang
+ with.
- You can also manage your gang programmatically through Netscript using the Gang API
+ You can also manage your gang programmatically through Netscript
+ using the Gang API
diff --git a/src/Gang/ui/RecruitButton.tsx b/src/Gang/ui/RecruitButton.tsx
new file mode 100644
index 000000000..0f9b1c903
--- /dev/null
+++ b/src/Gang/ui/RecruitButton.tsx
@@ -0,0 +1,47 @@
+import React from "react";
+import { Gang } from "../Gang";
+import { RecruitPopup } from "./RecruitPopup";
+import { GangConstants } from "../data/Constants";
+import { formatNumber } from "../../../utils/StringHelperFunctions";
+import { createPopup } from "../../ui/React/createPopup";
+
+interface IProps {
+ gang: Gang;
+ onRecruit: () => void;
+}
+
+export function RecruitButton(props: IProps): React.ReactElement {
+ if (props.gang.members.length >= GangConstants.MaximumGangMembers) {
+ return (<>>);
+ }
+
+ if (!props.gang.canRecruitMember()) {
+ const respect = props.gang.getRespectNeededToRecruitMember();
+ return (<>
+
+ Recruit Gang Member
+
+
+ {formatNumber(respect, 2)} respect needed to recruit next member
+
+ >);
+ }
+
+ function onClick(): void {
+ const popupId = "recruit-gang-member-popup";
+ createPopup(popupId, RecruitPopup, {
+ gang: props.gang,
+ popupId: popupId,
+ onRecruit: props.onRecruit,
+ });
+ }
+
+ return (<>
+
+ Recruit Gang Member
+
+ >);
+}
\ No newline at end of file
diff --git a/src/Gang/ui/RecruitPopup.tsx b/src/Gang/ui/RecruitPopup.tsx
new file mode 100644
index 000000000..ba328e5c3
--- /dev/null
+++ b/src/Gang/ui/RecruitPopup.tsx
@@ -0,0 +1,60 @@
+import React, { useState } from "react";
+import { Gang } from "../Gang";
+import { removePopup } from "../../ui/React/createPopup";
+import { dialogBoxCreate } from "../../../utils/DialogBox";
+
+interface IRecruitPopupProps {
+ gang: Gang;
+ popupId: string;
+ onRecruit: () => void;
+}
+
+export function RecruitPopup(props: IRecruitPopupProps): React.ReactElement {
+ const [name, setName] = useState("");
+
+ function recruit(): void {
+ if (name === "") {
+ dialogBoxCreate("You must enter a name for your Gang member!");
+ return;
+ }
+ if (!props.gang.canRecruitMember()) {
+ dialogBoxCreate("You cannot recruit another Gang member!");
+ return;
+ }
+
+ // At this point, the only way this can fail is if you already
+ // have a gang member with the same name
+ if (!props.gang.recruitMember(name)) {
+ dialogBoxCreate("You already have a gang member with this name!");
+ return;
+ }
+
+ props.onRecruit();
+ removePopup(props.popupId);
+ }
+
+ function cancel(): void {
+ removePopup(props.popupId);
+ }
+
+ function onKeyUp(event: React.KeyboardEvent): void {
+ if(event.keyCode === 13) recruit();
+ if(event.keyCode === 27) cancel();
+ }
+
+ function onChange(event: React.ChangeEvent): void {
+ setName(event.target.value);
+ }
+
+ return (<>
+
Enter a name for your new Gang member:
+
+ Recruit Gang Member
+ Cancel
+ >);
+}
\ No newline at end of file
diff --git a/src/Gang/ui/Root.tsx b/src/Gang/ui/Root.tsx
index 2859b41cf..906bf9acc 100644
--- a/src/Gang/ui/Root.tsx
+++ b/src/Gang/ui/Root.tsx
@@ -27,9 +27,18 @@ export function Root(props: IProps): React.ReactElement {
}
return (<>
- Back
- setManagement(true)}>Gang Management
- setManagement(false)}>Gang Territory
+ Back
+ setManagement(true)}>
+ Gang Management
+
+ setManagement(false)}>
+ Gang Territory
+
{management ?
:
}
diff --git a/src/Gang/ui/Panel3.tsx b/src/Gang/ui/TaskDescription.tsx
similarity index 80%
rename from src/Gang/ui/Panel3.tsx
rename to src/Gang/ui/TaskDescription.tsx
index b7e33e742..82715b17a 100644
--- a/src/Gang/ui/Panel3.tsx
+++ b/src/Gang/ui/TaskDescription.tsx
@@ -1,4 +1,4 @@
-import React, { useState, useEffect } from "react";
+import React from "react";
import { GangMemberTasks } from "../GangMemberTasks";
import { GangMember } from "../GangMember";
@@ -6,7 +6,7 @@ interface IProps {
member: GangMember;
}
-export function Panel3(props: IProps): React.ReactElement {
+export function TaskDescription(props: IProps): React.ReactElement {
const task = GangMemberTasks[props.member.task];
const desc = task ? task.desc: GangMemberTasks["Unassigned"].desc;
diff --git a/src/Gang/ui/Panel2.tsx b/src/Gang/ui/TaskSelector.tsx
similarity index 93%
rename from src/Gang/ui/Panel2.tsx
rename to src/Gang/ui/TaskSelector.tsx
index d87e1f73c..105e21dc7 100644
--- a/src/Gang/ui/Panel2.tsx
+++ b/src/Gang/ui/TaskSelector.tsx
@@ -1,4 +1,4 @@
-import React, { useState, useEffect } from "react";
+import React, { useState } from "react";
import { numeralWrapper } from "../../ui/numeralFormat";
import { StatsTable } from "../../ui/React/StatsTable";
import { MoneyRate } from "../../ui/React/MoneyRate";
@@ -11,7 +11,7 @@ interface IProps {
onTaskChange: () => void;
}
-export function Panel2(props: IProps): React.ReactElement {
+export function TaskSelector(props: IProps): React.ReactElement {
const [currentTask, setCurrentTask] = useState(props.member.task);
function onChange(event: React.ChangeEvent): void {
diff --git a/src/Gang/ui/TerritorySubpage.tsx b/src/Gang/ui/TerritorySubpage.tsx
index f6af15d30..d5ea8df91 100644
--- a/src/Gang/ui/TerritorySubpage.tsx
+++ b/src/Gang/ui/TerritorySubpage.tsx
@@ -1,4 +1,4 @@
-import React, { useState, useEffect } from "react";
+import React from "react";
import { numeralWrapper } from "../../ui/numeralFormat";
import { dialogBoxCreate } from "../../../utils/DialogBox";
import { formatNumber } from "../../../utils/StringHelperFunctions";
@@ -11,13 +11,13 @@ interface IProps {
export function TerritorySubpage(props: IProps): React.ReactElement {
function openWarfareHelp(): void {
- dialogBoxCreate("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.")
+ dialogBoxCreate("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.");
}
- function formatTerritoryP(n: number): string {
+ function formatTerritory(n: number): string {
const v = n * 100;
if (v <= 0) {
return formatNumber(0, 2);
@@ -35,7 +35,7 @@ export function TerritorySubpage(props: IProps): React.ReactElement {
return ({name}
Power: {formatNumber(power, 6)}
- Territory: {formatTerritoryP(AllGangs[name].territory)}%
+ Territory: {formatTerritory(AllGangs[name].territory)}%
Chance to win clash with this gang: {numeralWrapper.formatPercentage(clashVictoryChance, 3)}