diff --git a/src/Augmentation/Augmentation.tsx b/src/Augmentation/Augmentation.tsx index d64dedc90..eeb6d2cbf 100644 --- a/src/Augmentation/Augmentation.tsx +++ b/src/Augmentation/Augmentation.tsx @@ -55,7 +55,7 @@ interface IConstructorParams { } function generateStatsDescription(mults: IMap, programs?: string[], startingMoney?: number): JSX.Element { - const f = (x: number, decimals: number = 0) => { + const f = (x: number, decimals = 0) => { // look, I don't know how to make a "smart decimals" // todo, make it smarter if(x === 1.0777-1) return "7.77%"; diff --git a/src/Bladeburner.jsx b/src/Bladeburner.jsx index 4693f99b2..8d3b8e158 100644 --- a/src/Bladeburner.jsx +++ b/src/Bladeburner.jsx @@ -52,24 +52,10 @@ import { createPopup } from "../utils/uiHelpers/createPopup"; import { removeElement } from "../utils/uiHelpers/removeElement"; import { removeElementById } from "../utils/uiHelpers/removeElementById"; -import { SkillElem } from "./Bladeburner/ui/SkillElem"; -import { SkillList } from "./Bladeburner/ui/SkillList"; -import { BlackOpElem } from "./Bladeburner/ui/BlackOpElem"; -import { BlackOpList } from "./Bladeburner/ui/BlackOpList"; -import { OperationElem } from "./Bladeburner/ui/OperationElem"; -import { OperationList } from "./Bladeburner/ui/OperationList"; -import { ContractElem } from "./Bladeburner/ui/ContractElem"; -import { ContractList } from "./Bladeburner/ui/ContractList"; -import { GeneralActionElem } from "./Bladeburner/ui/GeneralActionElem"; -import { GeneralActionList } from "./Bladeburner/ui/GeneralActionList"; -import { GeneralActionPage } from "./Bladeburner/ui/GeneralActionPage"; -import { ContractPage } from "./Bladeburner/ui/ContractPage"; -import { OperationPage } from "./Bladeburner/ui/OperationPage"; -import { BlackOpPage } from "./Bladeburner/ui/BlackOpPage"; -import { SkillPage } from "./Bladeburner/ui/SkillPage"; import { Stats } from "./Bladeburner/ui/Stats"; import { AllPages } from "./Bladeburner/ui/AllPages"; import { Console } from "./Bladeburner/ui/Console"; +import { Root } from "./Bladeburner/ui/Root"; import { StatsTable } from "./ui/React/StatsTable"; import { CopyableText } from "./ui/React/CopyableText"; @@ -77,73 +63,6 @@ import { Money } from "./ui/React/Money"; import React from "react"; import ReactDOM from "react-dom"; -const stealthIcon = ` ` -const killIcon = `` - -// DOM related variables -const ActiveActionCssClass = "bladeburner-active-action"; - -// Console related stuff -let consoleHistoryIndex = 0; - -// Keypresses for Console -$(document).keydown(function(event) { - if (routing.isOn(Page.Bladeburner)) { - if (!(Player.bladeburner instanceof Bladeburner)) { return; } - let consoleHistory = Player.bladeburner.consoleHistory; - - if (event.keyCode === KEY.ENTER) { - event.preventDefault(); - var command = DomElems.consoleInput.value; - if (command.length > 0) { - Player.bladeburner.postToConsole("> " + command); - Player.bladeburner.resetConsoleInput(); - Player.bladeburner.executeConsoleCommands(command); - } - } - - if (event.keyCode === KEY.UPARROW) { - if (DomElems.consoleInput == null) {return;} - var i = consoleHistoryIndex; - var len = consoleHistory.length; - - if (len === 0) {return;} - if (i < 0 || i > len) { - consoleHistoryIndex = len; - } - - if (i !== 0) { - --consoleHistoryIndex; - } - - var prevCommand = consoleHistory[consoleHistoryIndex]; - DomElems.consoleInput.value = prevCommand; - setTimeoutRef(function(){DomElems.consoleInput.selectionStart = DomElems.consoleInput.selectionEnd = 10000; }, 0); - } - - if (event.keyCode === KEY.DOWNARROW) { - if (DomElems.consoleInput == null) {return;} - var i = consoleHistoryIndex; - var len = consoleHistory.length; - - if (len == 0) {return;} - if (i < 0 || i > len) { - consoleHistoryIndex = len; - } - - // Latest command, put nothing - if (i == len || i == len-1) { - consoleHistoryIndex = len; - DomElems.consoleInput.value = ""; - } else { - ++consoleHistoryIndex; - var prevCommand = consoleHistory[consoleHistoryIndex]; - DomElems.consoleInput.value = prevCommand; - } - } - } -}); - function ActionIdentifier(params={}) { if (params.name) {this.name = params.name;} if (params.type) {this.type = params.type;} @@ -1216,67 +1135,19 @@ let DomElems = {}; Bladeburner.prototype.initializeDomElementRefs = function() { DomElems = { - bladeburnerDiv: null, - - // Main Divs - overviewConsoleParentDiv: null, - - overviewDiv: null, // Overview of stats that stays fixed on left - actionAndSkillsDiv: null, // Panel for different sections (contracts, ops, skills) - - consoleDiv: null, - consoleTable: null, - consoleInputRow: null, // tr - consoleInputCell: null, // td - consoleInputHeader: null, // "> " - consoleInput: null, // Actual input element + bladeburnerDiv: null, }; } Bladeburner.prototype.createContent = function() { - DomElems.bladeburnerDiv = createElement("div", { - id:"bladeburner-container", position:"fixed", class:"generic-menupage-container", - }); + DomElems.bladeburnerDiv = createElement("div"); - // Parent Div for Overview and Console - DomElems.overviewConsoleParentDiv = createElement("div", { - height:"60%", display:"block", position:"relative", - }); - - // Overview and Action/Skill pane - DomElems.overviewDiv = createElement("div", { - width:"30%", display:"inline-block", border:"1px solid white", - }); - - DomElems.actionAndSkillsDiv = createElement("div", { - width:"70%", display:"block", - border:"1px solid white", margin:"6px", padding:"6px", - }); - - ReactDOM.render(, DomElems.overviewDiv); - ReactDOM.render(, DomElems.actionAndSkillsDiv); - - // Console - DomElems.consoleDiv = createElement("div", { - class:"bladeburner-console-div", - clickListener:() => { - if (DomElems.consoleInput instanceof Element) { - DomElems.consoleInput.focus(); - } - return false; - }, - }); - ReactDOM.render(, DomElems.consoleDiv); - - DomElems.overviewConsoleParentDiv.appendChild(DomElems.overviewDiv); - DomElems.overviewConsoleParentDiv.appendChild(DomElems.consoleDiv); - DomElems.bladeburnerDiv.appendChild(DomElems.overviewConsoleParentDiv); - DomElems.bladeburnerDiv.appendChild(DomElems.actionAndSkillsDiv); + ReactDOM.render(, DomElems.bladeburnerDiv); document.getElementById("entire-game-container").appendChild(DomElems.bladeburnerDiv); if (this.consoleLogs.length === 0) { - this.postToConsole("Bladeburner Console BETA"); + this.postToConsole("Bladeburner Console"); this.postToConsole("Type 'help' to see console commands"); } else { for (let i = 0; i < this.consoleLogs.length; ++i) { @@ -1323,16 +1194,7 @@ Bladeburner.prototype.postToConsole = function(input, saveToLogs=true) { } } - -Bladeburner.prototype.resetConsoleInput = function() { - DomElems.consoleInput.value = ""; -} - Bladeburner.prototype.clearConsole = function() { - while (DomElems.consoleTable.childNodes.length > 1) { - DomElems.consoleTable.removeChild(DomElems.consoleTable.firstChild); - } - this.consoleLogs.length = 0; } @@ -1351,7 +1213,6 @@ Bladeburner.prototype.executeConsoleCommands = function(commands) { this.consoleHistory.splice(0, 1); } } - consoleHistoryIndex = this.consoleHistory.length; const arrayOfCommands = commands.split(";"); for (let i = 0; i < arrayOfCommands.length; ++i) { diff --git a/src/Bladeburner/ui/BlackOpElem.tsx b/src/Bladeburner/ui/BlackOpElem.tsx index 3fd3268f9..d2afc6e22 100644 --- a/src/Bladeburner/ui/BlackOpElem.tsx +++ b/src/Bladeburner/ui/BlackOpElem.tsx @@ -6,6 +6,8 @@ import { import { ActionTypes } from "../data/ActionTypes"; import { createProgressBarText } from "../../../utils/helpers/createProgressBarText"; import { stealthIcon, killIcon } from "../data/Icons"; +import { createPopup } from "../../ui/React/createPopup"; +import { TeamSizePopup } from "./TeamSizePopup"; interface IProps { bladeburner: any; @@ -34,41 +36,12 @@ export function BlackOpElem(props: IProps): React.ReactElement { } function onTeam() { - // TODO(hydroflame): this needs some changes that are in the Gang conversion. - // var popupId = "bladeburner-operation-set-team-size-popup"; - // var txt = createElement("p", { - // innerText:"Enter the amount of team members you would like to take on this " + - // "BlackOp. If you do not have the specified number of team members, " + - // "then as many as possible will be used. Note that team members may " + - // "be lost during operations.", - - // }); - // var input = createElement("input", { - // type:"number", placeholder: "Team size", class: "text-input", - // }); - // var setBtn = createElement("a", { - // innerText:"Confirm", class:"a-link-button", - // clickListener:() => { - // var num = Math.round(parseFloat(input.value)); - // if (isNaN(num) || num < 0) { - // dialogBoxCreate("Invalid value entered for number of Team Members (must be numeric, positive)") - // } else { - // action.teamCount = num; - // this.updateBlackOpsUIElement(el, action); - // } - // removeElementById(popupId); - // return false; - // }, - // }); - // var cancelBtn = createElement("a", { - // innerText:"Cancel", class:"a-link-button", - // clickListener:() => { - // removeElementById(popupId); - // return false; - // }, - // }); - // createPopup(popupId, [txt, input, setBtn, cancelBtn]); - // input.focus(); + const popupId = "bladeburner-operation-set-team-size-popup"; + createPopup(popupId, TeamSizePopup, { + bladeburner: props.bladeburner, + action: props.action, + popupId: popupId, + }); } return (<> diff --git a/src/Bladeburner/ui/BlackOpList.tsx b/src/Bladeburner/ui/BlackOpList.tsx index eeb0f9907..542eecaab 100644 --- a/src/Bladeburner/ui/BlackOpList.tsx +++ b/src/Bladeburner/ui/BlackOpList.tsx @@ -25,18 +25,16 @@ export function BlackOpList(props: IProps): React.ReactElement { return (a.reqdRank - b.reqdRank); }); - blackops = blackops.filter((blackop: BlackOperation, i: number) => - !(props.bladeburner.blackops[blackops[i].name] == null && + blackops = blackops.filter((blackop: BlackOperation, i: number) => !(props.bladeburner.blackops[blackops[i].name] == null && i !== 0 && props.bladeburner.blackops[blackops[i-1].name] == null)); blackops = blackops.reverse(); return (<> - {blackops.map((blackop: BlackOperation) => -
  • + {blackops.map((blackop: BlackOperation) =>
  • -
  • + , )} ); } \ No newline at end of file diff --git a/src/Bladeburner/ui/Console.tsx b/src/Bladeburner/ui/Console.tsx index 7c4de7eb8..971af3c25 100644 --- a/src/Bladeburner/ui/Console.tsx +++ b/src/Bladeburner/ui/Console.tsx @@ -15,29 +15,97 @@ interface IProps { } export function Console(props: IProps): React.ReactElement { - const lastRef = useRef(null); + const lastRef = useRef(null); const setRerender = useState(false)[1]; - useEffect(() => { + const [consoleHistoryIndex, setConsoleHistoryIndex] = useState(props.bladeburner.consoleHistory.length); + + // TODO: Figure out how to actually make the scrolling work correctly. + function scrollToBottom() { if(lastRef.current) - lastRef.current.scrollIntoView({block: "end", inline: "nearest", behavior: "smooth" }); - const id = setInterval(() => setRerender(old => !old), 1000); - return () => clearInterval(id); + lastRef.current.scrollTop = lastRef.current.scrollHeight; + } + + function rerender() { + setRerender(old => !old); + } + + useEffect(() => { + const id = setInterval(rerender, 1000); + const id2 = setInterval(scrollToBottom, 100); + return () => { + clearInterval(id); + clearInterval(id2); + }; }, []); - return ( - - {/* - TODO: optimize this. - using `i` as a key here isn't great because it'll re-render everything - everytime the console reaches max length. - */} - {props.bladeburner.consoleLogs.map((log: any, i: number) => )} - - - - -
    -
    {"> "}
    -
    ); + function handleKeyDown(event: React.KeyboardEvent): void { + if (event.keyCode === 13) { + event.preventDefault(); + const command = event.currentTarget.value; + event.currentTarget.value = ""; + if (command.length > 0) { + props.bladeburner.postToConsole("> " + command); + props.bladeburner.executeConsoleCommands(command); + setConsoleHistoryIndex(props.bladeburner.consoleHistory.length); + rerender(); + } + } + + const consoleHistory = props.bladeburner.consoleHistory; + + if (event.keyCode === 38) { // up + let i = consoleHistoryIndex; + const len = consoleHistory.length; + if (len === 0) {return;} + if (i < 0 || i > len) { + setConsoleHistoryIndex(len); + } + + if (i !== 0) { + i = i-1; + } + setConsoleHistoryIndex(i); + const prevCommand = consoleHistory[i]; + event.currentTarget.value = prevCommand; + } + + if (event.keyCode === 40) { + const i = consoleHistoryIndex; + const len = consoleHistory.length; + + if (len == 0) {return;} + if (i < 0 || i > len) { + setConsoleHistoryIndex(len); + } + + // Latest command, put nothing + if (i == len || i == len-1) { + setConsoleHistoryIndex(len); + event.currentTarget.value = ""; + } else { + setConsoleHistoryIndex(consoleHistoryIndex+1); + const prevCommand = consoleHistory[consoleHistoryIndex+1]; + event.currentTarget.value = prevCommand; + } + } + } + + return (
    + + + {/* + TODO: optimize this. + using `i` as a key here isn't great because it'll re-render everything + everytime the console reaches max length. + */} + {props.bladeburner.consoleLogs.map((log: any, i: number) => )} + + + + +
    +
    {"> "}
    +
    +
    ); } \ No newline at end of file diff --git a/src/Bladeburner/ui/ContractList.tsx b/src/Bladeburner/ui/ContractList.tsx index dcea7ea5e..6ba3b53f2 100644 --- a/src/Bladeburner/ui/ContractList.tsx +++ b/src/Bladeburner/ui/ContractList.tsx @@ -14,10 +14,9 @@ export function ContractList(props: IProps): React.ReactElement { const names = Object.keys(props.bladeburner.contracts); const contracts = props.bladeburner.contracts; return (<> - {names.map((name: string) => -
  • + {names.map((name: string) =>
  • -
  • + , )} ); } \ No newline at end of file diff --git a/src/Bladeburner/ui/GeneralActionList.tsx b/src/Bladeburner/ui/GeneralActionList.tsx index e459899d4..a099ae8e6 100644 --- a/src/Bladeburner/ui/GeneralActionList.tsx +++ b/src/Bladeburner/ui/GeneralActionList.tsx @@ -19,10 +19,9 @@ export function GeneralActionList(props: IProps): React.ReactElement { } } return (<> - {actions.map((action: Action) => -
  • + {actions.map((action: Action) =>
  • -
  • + , )} ); } \ No newline at end of file diff --git a/src/Bladeburner/ui/OperationElem.tsx b/src/Bladeburner/ui/OperationElem.tsx index 133778c8d..e4ac63898 100644 --- a/src/Bladeburner/ui/OperationElem.tsx +++ b/src/Bladeburner/ui/OperationElem.tsx @@ -7,6 +7,8 @@ import { } from "../../../utils/StringHelperFunctions"; import { stealthIcon, killIcon } from "../data/Icons"; import { BladeburnerConstants } from "../data/Constants"; +import { createPopup } from "../../ui/React/createPopup"; +import { TeamSizePopup } from "./TeamSizePopup"; interface IProps { bladeburner: any; @@ -30,40 +32,12 @@ export function OperationElem(props: IProps): React.ReactElement { } function onTeam() { - // var popupId = "bladeburner-operation-set-team-size-popup"; - // var txt = createElement("p", { - // innerText:"Enter the amount of team members you would like to take on these " + - // "operations. If you do not have the specified number of team members, " + - // "then as many as possible will be used. Note that team members may " + - // "be lost during operations.", - - // }); - // var input = createElement("input", { - // type:"number", placeholder: "Team size", class: "text-input", - // }); - // var setBtn = createElement("a", { - // innerText:"Confirm", class:"a-link-button", - // clickListener:() => { - // var num = Math.round(parseFloat(input.value)); - // if (isNaN(num) || num < 0) { - // dialogBoxCreate("Invalid value entered for number of Team Members (must be numeric, positive)") - // } else { - // action.teamCount = num; - // this.updateOperationsUIElement(el, action); - // } - // removeElementById(popupId); - // return false; - // }, - // }); - // var cancelBtn = createElement("a", { - // innerText:"Cancel", class:"a-link-button", - // clickListener:() => { - // removeElementById(popupId); - // return false; - // }, - // }); - // createPopup(popupId, [txt, input, setBtn, cancelBtn]); - // input.focus(); + const popupId = "bladeburner-operation-set-team-size-popup"; + createPopup(popupId, TeamSizePopup, { + bladeburner: props.bladeburner, + action: props.action, + popupId: popupId, + }); } function increaseLevel() { diff --git a/src/Bladeburner/ui/OperationList.tsx b/src/Bladeburner/ui/OperationList.tsx index d78d46351..73d07cb16 100644 --- a/src/Bladeburner/ui/OperationList.tsx +++ b/src/Bladeburner/ui/OperationList.tsx @@ -14,10 +14,9 @@ export function OperationList(props: IProps): React.ReactElement { const names = Object.keys(props.bladeburner.operations); const operations = props.bladeburner.operations; return (<> - {names.map((name: string) => -
  • + {names.map((name: string) =>
  • -
  • + , )} ); } \ No newline at end of file diff --git a/src/Bladeburner/ui/Root.tsx b/src/Bladeburner/ui/Root.tsx new file mode 100644 index 000000000..1c1f37106 --- /dev/null +++ b/src/Bladeburner/ui/Root.tsx @@ -0,0 +1,27 @@ +import React from "react"; +import { Stats } from "./Stats"; +import { Console } from "./Console"; +import { AllPages } from "./AllPages"; + +import { IPlayer } from "../../PersonObjects/IPlayer"; +import { IEngine } from "../../IEngine"; + +interface IProps { + bladeburner: any; + engine: IEngine; + player: IPlayer; +} + +export function Root(props: IProps): React.ReactElement { + return (
    +
    +
    + +
    + +
    +
    + +
    +
    ); +} \ No newline at end of file diff --git a/src/Bladeburner/ui/SkillList.tsx b/src/Bladeburner/ui/SkillList.tsx index a7fbe2182..ca55033d0 100644 --- a/src/Bladeburner/ui/SkillList.tsx +++ b/src/Bladeburner/ui/SkillList.tsx @@ -9,10 +9,9 @@ interface IProps { export function SkillList(props: IProps): React.ReactElement { return (<> - {Object.keys(Skills).map((skill: string) => -
  • + {Object.keys(Skills).map((skill: string) =>
  • -
  • + , )} ); } \ No newline at end of file diff --git a/src/Bladeburner/ui/Stats.tsx b/src/Bladeburner/ui/Stats.tsx index e766d8c11..6a6899869 100644 --- a/src/Bladeburner/ui/Stats.tsx +++ b/src/Bladeburner/ui/Stats.tsx @@ -5,13 +5,23 @@ import { } from "../../../utils/StringHelperFunctions"; import { BladeburnerConstants } from "../data/Constants"; import { IPlayer } from "../../PersonObjects/IPlayer"; +import { IEngine } from "../../IEngine"; import { Money } from "../../ui/React/Money"; import { StatsTable } from "../../ui/React/StatsTable"; import { numeralWrapper } from "../../ui/numeralFormat"; import { dialogBoxCreate } from "../../../utils/DialogBox"; +import { createPopup } from "../../ui/React/createPopup"; +import { Factions } from "../../Faction/Factions"; +import { + joinFaction, + displayFactionContent, +} from "../../Faction/FactionHelpers"; + +import { TravelPopup } from "./TravelPopup"; interface IProps { bladeburner: any; + engine: IEngine; player: IPlayer; } @@ -53,53 +63,26 @@ export function Stats(props: IProps): React.ReactElement { } function openTravel() { - // var popupId = "bladeburner-travel-popup-cancel-btn"; - // var popupArguments = []; - // popupArguments.push(createElement("a", { // Cancel Button - // innerText:"Cancel", class:"a-link-button", - // clickListener:() => { - // removeElementById(popupId); return false; - // }, - // })) - // popupArguments.push(createElement("p", { // Info Text - // innerText:"Travel to a different city for your Bladeburner " + - // "activities. This does not cost any money. The city you are " + - // "in for your Bladeburner duties does not affect " + - // "your location in the game otherwise", - // })); - // for (var i = 0; i < BladeburnerConstants.CityNames.length; ++i) { - // (function(inst, i) { - // popupArguments.push(createElement("div", { - // // Reusing this css class...it adds a border and makes it - // // so that background color changes when you hover - // class:"cmpy-mgmt-find-employee-option", - // innerText:BladeburnerConstants.CityNames[i], - // clickListener:() => { - // inst.city = BladeburnerConstants.CityNames[i]; - // removeElementById(popupId); - // inst.updateOverviewContent(); - // return false; - // }, - // })); - // })(this, i); - // } - // createPopup(popupId, popupArguments); + const popupId = "bladeburner-travel-popup"; + createPopup(popupId, TravelPopup, { + bladeburner: props.bladeburner, + popupId: popupId, + }); } function openFaction() { - // if (bladeburnerFac.isMember) { - // Engine.loadFactionContent(); - // displayFactionContent(bladeburnersFactionName); - // } else { - // if (this.rank >= BladeburnerConstants.RankNeededForFaction) { - // joinFaction(bladeburnerFac); - // dialogBoxCreate("Congratulations! You were accepted into the Bladeburners faction"); - // removeChildrenFromElement(DomElems.overviewDiv); - // this.createOverviewContent(); - // } else { - // dialogBoxCreate("You need a rank of 25 to join the Bladeburners Faction!") - // } - // } + const faction = Factions["Bladeburners"]; + if (faction.isMember) { + props.engine.loadFactionContent(); + displayFactionContent("Bladeburners"); + } else { + if (props.bladeburner.rank >= BladeburnerConstants.RankNeededForFaction) { + joinFaction(faction); + dialogBoxCreate("Congratulations! You were accepted into the Bladeburners faction"); + } else { + dialogBoxCreate("You need a rank of 25 to join the Bladeburners Faction!") + } + } } return (<> diff --git a/src/Bladeburner/ui/TeamSizePopup.tsx b/src/Bladeburner/ui/TeamSizePopup.tsx new file mode 100644 index 000000000..4eb9b07db --- /dev/null +++ b/src/Bladeburner/ui/TeamSizePopup.tsx @@ -0,0 +1,37 @@ +import React, { useState } from "react"; +import { removePopup } from "../../ui/React/createPopup"; +import { BladeburnerConstants } from "../data/Constants"; +import { dialogBoxCreate } from "../../../utils/DialogBox"; +import { Action } from "../Action"; + +interface IProps { + bladeburner: any; + action: Action; + popupId: string; +} + +export function TeamSizePopup(props: IProps): React.ReactElement { + const [teamSize, setTeamSize] = useState(); + + function confirmTeamSize(): void { + if(teamSize === undefined) return; + const num = Math.round(teamSize); + if (isNaN(num) || num < 0) { + dialogBoxCreate("Invalid value entered for number of Team Members (must be numeric, positive)") + } else { + props.action.teamCount = num; + } + removePopup(props.popupId); + } + + return (<> +

    + Enter the amount of team members you would like to take on this + Op. If you do not have the specified number of team members, + then as many as possible will be used. Note that team members may + be lost during operations. +

    + setTeamSize(parseFloat(event.target.value))} /> + Confirm + ); +} \ No newline at end of file diff --git a/src/Bladeburner/ui/TravelPopup.tsx b/src/Bladeburner/ui/TravelPopup.tsx new file mode 100644 index 000000000..3becd7cc4 --- /dev/null +++ b/src/Bladeburner/ui/TravelPopup.tsx @@ -0,0 +1,31 @@ +import React from "react"; +import { removePopup } from "../../ui/React/createPopup"; +import { BladeburnerConstants } from "../data/Constants"; + +interface IProps { + bladeburner: any; + popupId: string; +} + +export function TravelPopup(props: IProps): React.ReactElement { + function travel(city: string) { + props.bladeburner.city = city; + removePopup(props.popupId); + } + + return (<> +

    + Travel to a different city for your Bladeburner + activities. This does not cost any money. The city you are + in for your Bladeburner duties does not affect + your location in the game otherwise. +

    + {BladeburnerConstants.CityNames.map(city => + // Reusing this css class...it adds a border and makes it + // so that background color changes when you hover +
    travel(city)}> + {city} +
    )} + ); +} \ No newline at end of file diff --git a/src/Faction/ui/FactionList.tsx b/src/Faction/ui/FactionList.tsx index 3b001a4a3..15a6bda48 100644 --- a/src/Faction/ui/FactionList.tsx +++ b/src/Faction/ui/FactionList.tsx @@ -28,8 +28,7 @@ export function FactionList(props: IProps): React.ReactElement {

    Lists all factions you have joined