From 0e9d7450c9eb4ce74fca77cc5c08ec07b1bd18d0 Mon Sep 17 00:00:00 2001
From: Olivier Gagnon {createProgressBarText({progress: computedActionTimeCurrent / props.bladeburner.actionTimeToComplete})}
+ Required Rank: {formatNumber(props.action.reqdRank, 0)}
+
+ Estimated Success Chance: {formatNumber(estimatedSuccessChance*100, 1)}% {props.action.isStealth?stealthIcon:<>>}{props.action.isKill?killIcon:<>>}
+
- Black Operations (Black Ops) are special, one-time covert operations. Each Black Op must be unlocked successively by completing the one before it. {createProgressBarText({progress:computedActionTimeCurrent / props.bladeburner.actionTimeToComplete})} {createProgressBarText({progress:computedActionTimeCurrent / props.bladeburner.actionTimeToComplete})} {createProgressBarText({progress:computedActionTimeCurrent / props.bladeburner.actionTimeToComplete})} Level: {currentLevel} MAX LEVEL Skill Points required: {formatNumber(pointCost, 0)}
+ Black Operations (Black Ops) are special, one-time covert operations.
+ Each Black Op must be unlocked successively by completing
+ the one before it.
+
+ Complete contracts in order to increase your Bladeburner rank and earn money.
+ Failing a contract will cause you to lose HP, which can lead to hospitalization.
+
+ These are generic actions that will assist you in your Bladeburner
+ duties. They will not affect your Bladeburner rank in any way.
+
+ Carry out operations for the Bladeburner division.
+ Failing an operation will reduce your Bladeburner rank. It will also
+ cause you to lose HP, which can lead to hospitalization. In general,
+ operations are harder and more punishing than contracts,
+ but are also more rewarding.
+
+ You will gain one skill point every {BladeburnerConstants.RanksPerSkillPoint} ranks.
+
+ Rank: {formatNumber(props.bladeburner.rank, 2)}
" + action.desc + "
",
- }));
- el.appendChild(createElement("p", {
- display:"block", color:hasReqdRank ? "white" : "red",
- innerHTML:"Required Rank: " + formatNumber(action.reqdRank, 0) + "
",
- }));
- el.appendChild(createElement("p", {
- display:"inline-block",
- innerHTML:`Estimated Success Chance: ${formatNumber(estimatedSuccessChance*100, 1)}% ${action.isStealth?stealthIcon:''}${action.isKill?killIcon:''}\n` +
- "Time Required: " + convertTimeMsToTimeElapsedString(actionTime*1000),
- }))
+ ReactDOM.unmountComponentAtNode(el);
+ ReactDOM.render({props.action.name} (COMPLETED)
);
+ }
+
+ const isActive = props.bladeburner.action.type === ActionTypes["BlackOperation"] && props.action.name === props.bladeburner.action.name;
+ const estimatedSuccessChance = props.action.getSuccessChance(props.bladeburner, {est:true});
+ const actionTime = props.action.getActionTime(props.bladeburner);
+ const hasReqdRank = props.bladeburner.rank >= props.action.reqdRank;
+ const computedActionTimeCurrent = Math.min(props.bladeburner.actionTimeCurrent+props.bladeburner.actionTimeOverflow, props.bladeburner.actionTimeToComplete);
+
+ function onStart() {
+ props.bladeburner.action.type = ActionTypes.BlackOperation;
+ props.bladeburner.action.name = props.action.name;
+ props.bladeburner.startAction(props.bladeburner.action);
+ props.bladeburner.updateActionAndSkillsContent();
+ }
+
+ 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();
+ }
+
+ return (<>
+
+ {isActive ?
+ <>{props.action.name} (IN PROGRESS - {formatNumber(computedActionTimeCurrent, 0)} / {formatNumber(props.bladeburner.actionTimeToComplete, 0)})> :
+ <>{props.action.name}>
+ }
+
+ {isActive ?
+
+
+
+
+
+
+
+ Time Required: {convertTimeMsToTimeElapsedString(actionTime*1000)}
+
" +
- "Your ultimate goal to climb through the ranks of Bladeburners is to complete " +
- "all of the Black Ops.
" +
- "Like normal operations, you may use a team for Black Ops. Failing " +
- "a black op will incur heavy HP and rank losses.";
-
-// Put Black Operations in sequence of required rank
-var blackops = [];
-for (var blackopName in BlackOperations) {
- if (BlackOperations.hasOwnProperty(blackopName)) {
- blackops.push(BlackOperations[blackopName]);
- }
-}
-blackops.sort(function(a, b) {
- return (a.reqdRank - b.reqdRank);
-});
-
-for (var i = blackops.length-1; i >= 0 ; --i) {
- if (this.blackops[[blackops[i].name]] == null && i !== 0 && this.blackops[[blackops[i-1].name]] == null) {continue;} // If this one nor the next are completed then this isn't unlocked yet.
- DomElems.blackops[blackops[i].name] = createElement("div", {
- class:"bladeburner-action", name:blackops[i].name
- });
- DomElems.actionsAndSkillsList.appendChild(DomElems.blackops[blackops[i].name]);
-}
-*/
-
-
-
-import * as React from "react";
-
-export function BlackOperationsPage(): React.ReactElement {
- // Put Black Operations in sequence of required rank
- const blackops = [];
- for (const name in BlackOperations) {
- if (BlackOperations.hasOwnProperty(name)) {
- blackops.push(BlackOperations[name]);
- }
- }
- blackops.sort(function(a, b) {
- return (a.reqdRank - b.reqdRank);
- });
-
- return (
- Your ultimate goal to climb through the ranks of Bladeburners is to complete all of the Black Ops.
- Like normal operations, you may use a team for Black Ops. Failing a black op will incur heavy HP and rank losses.
+ {isActive ?
+ <>{props.action.name} (IN PROGRESS - {formatNumber(computedActionTimeCurrent, 0)} / {formatNumber(props.bladeburner.actionTimeToComplete, 0)})> :
+ <>{props.action.name}>
+ }
+
+ {isActive ?
+
+
+
+
+ {props.action.getSuccessesNeededForNextLevel(BladeburnerConstants.ContractSuccessesPerLevel)} successes needed for next level
+
+ Level: {props.action.level} / {props.action.maxLevel}
+
+
+ {isActive && (WARNING: changing the level will restart the Operation)}
+ ↑
+
+
+ {isActive && (WARNING: changing the level will restart the Operation)}
+ ↓
+
+
+
+
+
+
+
+Estimated success chance: {formatNumber(estimatedSuccessChance*100, 1)}% {props.action.isStealth?stealthIcon:<>>}${props.action.isKill?killIcon:<>>}
+Time Required: {convertTimeMsToTimeElapsedString(actionTime*1000)}
+Contracts remaining: {Math.floor(props.action.count)}
+Successes: {props.action.successes}
+Failures: {props.action.failures}
+
+
+
+ >);
+}
+
+/*
+
+// Autolevel Checkbox
+el.appendChild(createElement("br"));
+var autolevelCheckboxId = "bladeburner-" + action.name + "-autolevel-checkbox";
+el.appendChild(createElement("label", {
+ for:autolevelCheckboxId, innerText:"Autolevel: ",color:"white",
+ tooltip:"Automatically increase contract level when possible",
+}));
+
+const checkboxInput = createElement("input", {
+ type:"checkbox",
+ id: autolevelCheckboxId,
+ checked: action.autoLevel,
+ changeListener: () => {
+ action.autoLevel = checkboxInput.checked;
+ },
+});
+
+el.appendChild(checkboxInput);
+
+*/
\ No newline at end of file
diff --git a/src/Bladeburner/ui/GeneralActionElem.tsx b/src/Bladeburner/ui/GeneralActionElem.tsx
new file mode 100644
index 000000000..93b7b1e2d
--- /dev/null
+++ b/src/Bladeburner/ui/GeneralActionElem.tsx
@@ -0,0 +1,49 @@
+import React, { useState } from "react";
+import { ActionTypes } from "../data/ActionTypes";
+import { createProgressBarText } from "../../../utils/helpers/createProgressBarText";
+import {
+ formatNumber,
+ convertTimeMsToTimeElapsedString,
+} from "../../../utils/StringHelperFunctions";
+import { stealthIcon, killIcon } from "../data/Icons";
+import { BladeburnerConstants } from "../data/Constants";
+
+interface IProps {
+ bladeburner: any;
+ action: any;
+}
+
+export function GeneralActionElem(props: IProps): React.ReactElement {
+ const setRerender = useState(false)[1];
+ const isActive = props.action.name === props.bladeburner.action.name;
+ const computedActionTimeCurrent = Math.min(props.bladeburner.actionTimeCurrent+props.bladeburner.actionTimeOverflow, props.bladeburner.actionTimeToComplete);
+
+ function onStart() {
+ props.bladeburner.action.type = ActionTypes[(props.action.name as string)];
+ props.bladeburner.action.name = props.action.name;
+ props.bladeburner.startAction(props.bladeburner.action);
+ setRerender(old => !old);
+ }
+
+ return (<>
+
+ {isActive ?
+ <>{props.action.name} (IN PROGRESS - {formatNumber(computedActionTimeCurrent, 0)} / {formatNumber(props.bladeburner.actionTimeToComplete, 0)})> :
+ <>{props.action.name}>
+ }
+
+ {isActive ?
+
+
+
+ >);
+}
\ No newline at end of file
diff --git a/src/Bladeburner/ui/OperationElem.tsx b/src/Bladeburner/ui/OperationElem.tsx
new file mode 100644
index 000000000..1dabeb650
--- /dev/null
+++ b/src/Bladeburner/ui/OperationElem.tsx
@@ -0,0 +1,157 @@
+import React, { useState } from "react";
+import { ActionTypes } from "../data/ActionTypes";
+import { createProgressBarText } from "../../../utils/helpers/createProgressBarText";
+import {
+ formatNumber,
+ convertTimeMsToTimeElapsedString,
+} from "../../../utils/StringHelperFunctions";
+import { stealthIcon, killIcon } from "../data/Icons";
+import { BladeburnerConstants } from "../data/Constants";
+
+interface IProps {
+ bladeburner: any;
+ action: any;
+}
+
+export function OperationElem(props: IProps): React.ReactElement {
+ const setRerender = useState(false)[1];
+ const isActive = props.bladeburner.action.type === ActionTypes["Operation"] && props.action.name === props.bladeburner.action.name;
+ const estimatedSuccessChance = props.action.getSuccessChance(props.bladeburner, {est:true});
+ const computedActionTimeCurrent = Math.min(props.bladeburner.actionTimeCurrent+props.bladeburner.actionTimeOverflow,props.bladeburner.actionTimeToComplete);
+ const maxLevel = (props.action.level >= props.action.maxLevel);
+ const actionTime = props.action.getActionTime(props.bladeburner);
+ const autolevelCheckboxId = `bladeburner-${props.action.name}-autolevel-checkbox`;
+
+ function onStart() {
+ props.bladeburner.action.type = ActionTypes.Operation;
+ props.bladeburner.action.name = props.action.name;
+ props.bladeburner.startAction(props.bladeburner.action);
+ props.bladeburner.updateActionAndSkillsContent();
+ setRerender(old => !old);
+ }
+
+ 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();
+ }
+
+ function increaseLevel() {
+ ++props.action.level;
+ if (isActive) props.bladeburner.startAction(props.bladeburner.action);
+ setRerender(old => !old);
+ }
+
+ function decreaseLevel() {
+ --props.action.level;
+ if (isActive) props.bladeburner.startAction(props.bladeburner.action);
+ setRerender(old => !old);
+ }
+
+ function onAutolevel(event: React.ChangeEvent
+ {isActive ?
+ <>{props.action.name} (IN PROGRESS - {formatNumber(computedActionTimeCurrent, 0)} / {formatNumber(props.bladeburner.actionTimeToComplete, 0)})> :
+ <>{props.action.name}>
+ }
+
+ {isActive ?
+
+
+
+
+ {props.action.getSuccessesNeededForNextLevel(BladeburnerConstants.OperationSuccessesPerLevel)} successes needed for next level
+
+ Level: {props.action.level} / {props.action.maxLevel}
+
+
+ {isActive && (WARNING: changing the level will restart the Operation)}
+ ↑
+
+
+ {isActive && (WARNING: changing the level will restart the Operation)}
+ ↓
+
+
+
+
+
+
+
+Estimated success chance: {formatNumber(estimatedSuccessChance*100, 1)}% {props.action.isStealth?stealthIcon:<>>}{props.action.isKill?killIcon:<>>}
+Time Required: {convertTimeMsToTimeElapsedString(actionTime*1000)}
+Operations remaining: {Math.floor(props.action.count)}
+Successes: {props.action.successes}
+Failures: {props.action.failures}
+
+
+
+ >);
+}
diff --git a/src/Bladeburner/ui/SkillElem.tsx b/src/Bladeburner/ui/SkillElem.tsx
new file mode 100644
index 000000000..af7ebfbf1
--- /dev/null
+++ b/src/Bladeburner/ui/SkillElem.tsx
@@ -0,0 +1,46 @@
+import * as React from "react";
+import { CopyableText } from "../../ui/React/CopyableText";
+import { formatNumber } from "../../../utils/StringHelperFunctions";
+
+interface IProps {
+ skill: any;
+ bladeburner: any;
+}
+
+export function SkillElem(props: IProps): React.ReactElement {
+ const skillName = props.skill.name;
+ let currentLevel = 0;
+ if (props.bladeburner.skills[skillName] && !isNaN(props.bladeburner.skills[skillName])) {
+ currentLevel = props.bladeburner.skills[skillName];
+ }
+ const pointCost = props.skill.calculateCost(currentLevel);
+
+ const canLevel = props.bladeburner.skillPoints >= pointCost;
+ const maxLvl = props.skill.maxLvl ? currentLevel >= props.skill.maxLvl : false;
+
+ function onClick() {
+ if (props.bladeburner.skillPoints < pointCost) return;
+ props.bladeburner.skillPoints -= pointCost;
+ props.bladeburner.upgradeSkill(props.skill);
+ props.bladeburner.createActionAndSkillsContent();
+ }
+
+ return (<>
+
+
+
+ Level
+
+
+
+
" +
- "You can unlock higher-level contracts by successfully completing them. " +
- "Higher-level contracts are more difficult, but grant more rank, experience, and money.";
-
- for (var contractName in this.contracts) {
- if (this.contracts.hasOwnProperty(contractName)) {
- DomElems.contracts[contractName] = createElement("div", {
- class:"bladeburner-action", name:contractName,
- });
- DomElems.actionsAndSkillsList.appendChild(DomElems.contracts[contractName]);
- }
- }
-}
-
-Bladeburner.prototype.createOperationsContent = function() {
- if (DomElems.actionsAndSkillsList == null || DomElems.actionsAndSkillsDesc == null) {
- throw new Error("Bladeburner.createOperationsContent called with either " +
- "DomElems.actionsAndSkillsList or DomElems.actionsAndSkillsDesc = null");
- }
-
- DomElems.actionsAndSkillsDesc.innerHTML =
- "Carry out operations for the Bladeburner division. " +
- "Failing an operation will reduce your Bladeburner rank. It will also " +
- "cause you to lose HP, which can lead to hospitalization. In general, " +
- "operations are harder and more punishing than contracts, " +
- "but are also more rewarding.
" +
- "Operations can affect the chaos level and Synthoid population of your " +
- "current city. The exact effects vary between different Operations.
" +
- "For operations, you can use a team. You must first recruit team members. " +
- "Having a larger team will improves your chances of success.
" +
- "You can unlock higher-level operations by successfully completing them. " +
- "Higher-level operations are more difficult, but grant more rank and experience.";
-
- for (var operationName in this.operations) {
- if (this.operations.hasOwnProperty(operationName)) {
- DomElems.operations[operationName] = createElement("div", {
- class:"bladeburner-action", name:operationName,
- });
- DomElems.actionsAndSkillsList.appendChild(DomElems.operations[operationName]);
- }
- }
-}
-
-Bladeburner.prototype.createBlackOpsContent = function() {
-
- if (DomElems.actionsAndSkillsList == null || DomElems.actionsAndSkillsDesc == null) {
- throw new Error("Bladeburner.createBlackOpsContent called with either " +
- "DomElems.actionsAndSkillsList or DomElems.actionsAndSkillsDesc = null");
- }
-
-
- DomElems.actionsAndSkillsDesc.innerHTML =
- "Black Operations (Black Ops) are special, one-time covert operations. " +
- "Each Black Op must be unlocked successively by completing " +
- "the one before it.
" +
- "Your ultimate goal to climb through the ranks of Bladeburners is to complete " +
- "all of the Black Ops.
" +
- "Like normal operations, you may use a team for Black Ops. Failing " +
- "a black op will incur heavy HP and rank losses.";
-
- // Put Black Operations in sequence of required rank
- var blackops = [];
- for (var blackopName in BlackOperations) {
- if (BlackOperations.hasOwnProperty(blackopName)) {
- blackops.push(BlackOperations[blackopName]);
- }
- }
- blackops.sort(function(a, b) {
- return (a.reqdRank - b.reqdRank);
- });
-
- for (var i = blackops.length-1; i >= 0 ; --i) {
- if (this.blackops[[blackops[i].name]] == null && i !== 0 && this.blackops[[blackops[i-1].name]] == null) {continue;} // If this one nor the next are completed then this isn't unlocked yet.
- DomElems.blackops[blackops[i].name] = createElement("div", {
- class:"bladeburner-action", name:blackops[i].name,
- });
- DomElems.actionsAndSkillsList.appendChild(DomElems.blackops[blackops[i].name]);
- }
-}
-
-Bladeburner.prototype.createSkillsContent = function() {
- if (DomElems.actionsAndSkillsList == null || DomElems.actionsAndSkillsDesc == null) {
- throw new Error("Bladeburner.createSkillsContent called with either " +
- "DomElems.actionsAndSkillsList or DomElems.actionsAndSkillsDesc = null");
- }
-
- // Display Current multipliers
- DomElems.actionsAndSkillsDesc.innerHTML =
- "You will gain one skill point every " + BladeburnerConstants.RanksPerSkillPoint + " ranks.
" +
- "Note that when upgrading a skill, the benefit for that skill is additive. " +
- "However, the effects of different skills with each other is multiplicative.
"
- var multKeys = Object.keys(this.skillMultipliers);
- for (var i = 0; i < multKeys.length; ++i) {
- var mult = this.skillMultipliers[multKeys[i]];
- if (mult && mult !== 1) {
- mult = formatNumber(mult, 3);
- switch(multKeys[i]) {
- case "successChanceAll":
- DomElems.actionsAndSkillsDesc.innerHTML += "Total Success Chance: x" + mult + "
";
- break;
- case "successChanceStealth":
- DomElems.actionsAndSkillsDesc.innerHTML += "Stealth Success Chance: x" + mult + "
";
- break;
- case "successChanceKill":
- DomElems.actionsAndSkillsDesc.innerHTML += "Retirement Success Chance: x" + mult + "
";
- break;
- case "successChanceContract":
- DomElems.actionsAndSkillsDesc.innerHTML += "Contract Success Chance: x" + mult + "
";
- break;
- case "successChanceOperation":
- DomElems.actionsAndSkillsDesc.innerHTML += "Operation Success Chance: x" + mult + "
";
- break;
- case "successChanceEstimate":
- DomElems.actionsAndSkillsDesc.innerHTML += "Synthoid Data Estimate: x" + mult + "
";
- break;
- case "actionTime":
- DomElems.actionsAndSkillsDesc.innerHTML += "Action Time: x" + mult + "
";
- break;
- case "effHack":
- DomElems.actionsAndSkillsDesc.innerHTML += "Hacking Skill: x" + mult + "
";
- break;
- case "effStr":
- DomElems.actionsAndSkillsDesc.innerHTML += "Strength: x" + mult + "
";
- break;
- case "effDef":
- DomElems.actionsAndSkillsDesc.innerHTML += "Defense: x" + mult + "
";
- break;
- case "effDex":
- DomElems.actionsAndSkillsDesc.innerHTML += "Dexterity: x" + mult + "
";
- break;
- case "effAgi":
- DomElems.actionsAndSkillsDesc.innerHTML += "Agility: x" + mult + "
";
- break;
- case "effCha":
- DomElems.actionsAndSkillsDesc.innerHTML += "Charisma: x" + mult + "
";
- break;
- case "effInt":
- DomElems.actionsAndSkillsDesc.innerHTML += "Intelligence: x" + mult + "
";
- break;
- case "stamina":
- DomElems.actionsAndSkillsDesc.innerHTML += "Stamina: x" + mult + "
";
- break;
- case "money":
- DomElems.actionsAndSkillsDesc.innerHTML += "Contract Money: x" + mult + "
";
- break;
- case "expGain":
- DomElems.actionsAndSkillsDesc.innerHTML += "Exp Gain: x" + mult + "
";
- break;
- default:
- console.warn(`Unrecognized SkillMult Key: ${multKeys[i]}`);
- break;
- }
- }
- }
-
- // Skill Points
- DomElems.skillPointsDisplay = createElement("p", {
- innerHTML:"
Skill Points: " + formatNumber(this.skillPoints, 0) + "",
- });
- DomElems.actionAndSkillsDiv.appendChild(DomElems.skillPointsDisplay);
-
- // UI Element for each skill
- for (var skillName in Skills) {
- if (Skills.hasOwnProperty(skillName)) {
- DomElems.skills[skillName] = createElement("div", {
- class:"bladeburner-action", name:skillName,
- });
- DomElems.actionsAndSkillsList.appendChild(DomElems.skills[skillName]);
- }
- }
-}
-
Bladeburner.prototype.updateContent = function() {
this.updateOverviewContent();
- this.updateActionAndSkillsContent();
}
Bladeburner.prototype.updateOverviewContent = function() {
- if (!routing.isOn(Page.Bladeburner)) {return;}
- DomElems.overviewRank.childNodes[0].nodeValue = "Rank: " + formatNumber(this.rank, 2);
- DomElems.overviewStamina.innerText = "Stamina: " + formatNumber(this.stamina, 3) + " / " + formatNumber(this.maxStamina, 3);
- ReactDOM.render(<>
- Stamina Penalty: {formatNumber((1-this.calculateStaminaPenalty())*100, 1)}%
- Team Size: {formatNumber(this.teamSize, 0)}
- Team Members Lost: {formatNumber(this.teamLost, 0)}
- Num Times Hospitalized: {this.numHosp}
- Money Lost From Hospitalizations: {Money(this.moneyLost)}
- Current City: {this.city}
- >, DomElems.overviewGen1);
-
- DomElems.overviewEstPop.childNodes[0].nodeValue = "Est. Synthoid Population: " + numeralWrapper.formatPopulation(this.getCurrentCity().popEst);
- DomElems.overviewEstComms.childNodes[0].nodeValue = "Est. Synthoid Communities: " + formatNumber(this.getCurrentCity().comms, 0);
- DomElems.overviewChaos.childNodes[0].nodeValue = "City Chaos: " + formatNumber(this.getCurrentCity().chaos);
- DomElems.overviewSkillPoints.innerText = "Skill Points: " + formatNumber(this.skillPoints, 0);
- DomElems.overviewBonusTime.childNodes[0].nodeValue = "Bonus time: " + convertTimeMsToTimeElapsedString(this.storedCycles/BladeburnerConstants.CyclesPerSecond*1000);
- ReactDOM.render(StatsTable([
- ["Aug. Success Chance mult: ", formatNumber(Player.bladeburner_success_chance_mult*100, 1) + "%"],
- ["Aug. Max Stamina mult: ", formatNumber(Player.bladeburner_max_stamina_mult*100, 1) + "%"],
- ["Aug. Stamina Gain mult: ", formatNumber(Player.bladeburner_stamina_gain_mult*100, 1) + "%"],
- ["Aug. Field Analysis mult: ", formatNumber(Player.bladeburner_analysis_mult*100, 1) + "%"],
- ]), DomElems.overviewAugMults);
+ if (!routing.isOn(Page.Bladeburner)) return;
+ ReactDOM.render(
Skill Points: " + formatNumber(this.skillPoints, 0) + "";
-
- var skillElems = Object.keys(DomElems.skills);
- for (var i = 0; i < skillElems.length; ++i) {
- var skillElem = DomElems.skills[skillElems[i]];
- var name = skillElem.name;
- var skill = Skills[name];
- if (skill == null) {
- throw new Error("Could not find Skill " + name + " in Bladeburner.updateActionAndSkillsContent()");
- }
- this.updateSkillsUIElement(skillElem, skill);
- }
- break;
- default:
- throw new Error("Invalid value for DomElems.currentTab in Bladeburner.createActionAndSkillsContent");
- }
-}
-
-Bladeburner.prototype.updateGeneralActionsUIElement = function(el, action) {
- ReactDOM.unmountComponentAtNode(el);
- ReactDOM.render(
+
+ Your ultimate goal to climb through the ranks of Bladeburners is to complete
+ all of the Black Ops.
+
+
+ Like normal operations, you may use a team for Black Ops. Failing
+ a black op will incur heavy HP and rank losses.
+
+
+ You can unlock higher-level contracts by successfully completing them.
+ Higher-level contracts are more difficult, but grant more rank, experience, and money.
+
+
+ Operations can affect the chaos level and Synthoid population of your
+ current city. The exact effects vary between different Operations.
+
+
+ For operations, you can use a team. You must first recruit team members.
+ Having a larger team will improves your chances of success.
+
+
+ You can unlock higher-level operations by successfully completing them.
+ Higher-level operations are more difficult, but grant more rank and experience.
+
+
+ Note that when upgrading a skill, the benefit for that skill is additive.
+ However, the effects of different skills with each other is multiplicative.
+
+
+
>}
+ {valid(mults["successChanceStealth"]) && <>Stealth Success Chance: x{formatNumber(mults["successChanceStealth"], 3)}
>}
+ {valid(mults["successChanceKill"]) && <>Retirement Success Chance: x{formatNumber(mults["successChanceKill"], 3)}
>}
+ {valid(mults["successChanceContract"]) && <>Contract Success Chance: x{formatNumber(mults["successChanceContract"], 3)}
>}
+ {valid(mults["successChanceOperation"]) && <>Operation Success Chance: x{formatNumber(mults["successChanceOperation"], 3)}
>}
+ {valid(mults["successChanceEstimate"]) && <>Synthoid Data Estimate: x{formatNumber(mults["successChanceEstimate"], 3)}
>}
+ {valid(mults["actionTime"]) && <>Action Time: x{formatNumber(mults["actionTime"], 3)}
>}
+ {valid(mults["effHack"]) && <>Hacking Skill: x{formatNumber(mults["effHack"], 3)}
>}
+ {valid(mults["effStr"]) && <>Strength: x{formatNumber(mults["effStr"], 3)}
>}
+ {valid(mults["effDef"]) && <>Defense: x{formatNumber(mults["effDef"], 3)}
>}
+ {valid(mults["effDex"]) && <>Dexterity: x{formatNumber(mults["effDex"], 3)}
>}
+ {valid(mults["effAgi"]) && <>Agility: x{formatNumber(mults["effAgi"], 3)}
>}
+ {valid(mults["effCha"]) && <>Charisma: x{formatNumber(mults["effCha"], 3)}
>}
+ {valid(mults["effInt"]) && <>Intelligence: x{formatNumber(mults["effInt"], 3)}
>}
+ {valid(mults["stamina"]) && <>Stamina: x{formatNumber(mults["stamina"], 3)}
>}
+ {valid(mults["money"]) && <>Contract Money: x{formatNumber(mults["money"], 3)}
>}
+ {valid(mults["expGain"]) && <>Exp Gain: x{formatNumber(mults["expGain"], 3)}
>}
+
+
" +
+ "Your max stamina is determined primarily by your agility stat.
" +
+ "Your stamina gain rate is determined by both your agility and your " +
+ "max stamina. Higher max stamina leads to a higher gain rate.
" +
+ "Once your " +
+ "stamina falls below 50% of its max value, it begins to negatively " +
+ "affect the success rate of your contracts/operations. This penalty " +
+ "is shown in the overview panel. If the penalty is 15%, then this means " +
+ "your success rate would be multipled by 85% (100 - 15).
" +
+ "Your max stamina and stamina gain rate can also be increased by " +
+ "training, or through skills and Augmentation upgrades.");
+ }
+
+ function openPopulationHelp(): void {
+ dialogBoxCreate("The success rate of your contracts/operations depends on " +
+ "the population of Synthoids in your current city. " +
+ "The success rate that is shown to you is only an estimate, " +
+ "and it is based on your Synthoid population estimate.
" +
+ "Therefore, it is important that this Synthoid population estimate " +
+ "is accurate so that you have a better idea of your " +
+ "success rate for contracts/operations. Certain " +
+ "actions will increase the accuracy of your population " +
+ "estimate.
" +
+ "The Synthoid populations of cities can change due to your " +
+ "actions or random events. If random events occur, they will " +
+ "be logged in the Bladeburner Console.");
+ }
+
+ return (
+ Stamina: {formatNumber(props.bladeburner.stamina, 3)} / {formatNumber(props.bladeburner.maxStamina, 3)}
+
+ Est. Synthoid Population: {numeralWrapper.formatPopulation(props.bladeburner.getCurrentCity().popEst)}
+
+ Est. Synthoid Communities: {formatNumber(props.bladeburner.getCurrentCity().comms, 0)}
+ City Chaos: {formatNumber(props.bladeburner.getCurrentCity().chaos)}
+ Skill Points: {formatNumber(props.bladeburner.skillPoints, 0)}
+ Bonus time: {convertTimeMsToTimeElapsedString(props.bladeburner.storedCycles/BladeburnerConstants.CyclesPerSecond*1000)}
+ Stamina Penalty: {formatNumber((1-props.bladeburner.calculateStaminaPenalty())*100, 1)}%
+ Team Size: {formatNumber(props.bladeburner.teamSize, 0)}
+ Team Members Lost: {formatNumber(props.bladeburner.teamLost, 0)}
+ Num Times Hospitalized: {props.bladeburner.numHosp}
+ Money Lost From Hospitalizations: {Money(props.bladeburner.moneyLost)}
+ Current City: {props.bladeburner.city}
+ {StatsTable([
+ ["Aug. Success Chance mult: ", formatNumber(props.player.bladeburner_success_chance_mult*100, 1) + "%"],
+ ["Aug. Max Stamina mult: ", formatNumber(props.player.bladeburner_max_stamina_mult*100, 1) + "%"],
+ ["Aug. Stamina Gain mult: ", formatNumber(props.player.bladeburner_stamina_gain_mult*100, 1) + "%"],
+ ["Aug. Field Analysis mult: ", formatNumber(props.player.bladeburner_analysis_mult*100, 1) + "%"],
+ ])}
+
+ {"> "}+ |
+
+ Skill Points: {formatNumber(props.bladeburner.skillPoints, 0)} +
You will gain one skill point every {BladeburnerConstants.RanksPerSkillPoint} ranks.
@@ -24,27 +27,27 @@ export function SkillPage(props: IProps): React.ReactElement {
Note that when upgrading a skill, the benefit for that skill is additive.
However, the effects of different skills with each other is multiplicative.
-
Total Success Chance: x{formatNumber(mults["successChanceAll"], 3)}
} + {valid(mults["successChanceStealth"]) &&Stealth Success Chance: x{formatNumber(mults["successChanceStealth"], 3)}
} + {valid(mults["successChanceKill"]) &&Retirement Success Chance: x{formatNumber(mults["successChanceKill"], 3)}
} + {valid(mults["successChanceContract"]) &&Contract Success Chance: x{formatNumber(mults["successChanceContract"], 3)}
} + {valid(mults["successChanceOperation"]) &&Operation Success Chance: x{formatNumber(mults["successChanceOperation"], 3)}
} + {valid(mults["successChanceEstimate"]) &&Synthoid Data Estimate: x{formatNumber(mults["successChanceEstimate"], 3)}
} + {valid(mults["actionTime"]) &&Action Time: x{formatNumber(mults["actionTime"], 3)}
} + {valid(mults["effHack"]) &&Hacking Skill: x{formatNumber(mults["effHack"], 3)}
} + {valid(mults["effStr"]) &&Strength: x{formatNumber(mults["effStr"], 3)}
} + {valid(mults["effDef"]) &&Defense: x{formatNumber(mults["effDef"], 3)}
} + {valid(mults["effDex"]) &&Dexterity: x{formatNumber(mults["effDex"], 3)}
} + {valid(mults["effAgi"]) &&Agility: x{formatNumber(mults["effAgi"], 3)}
} + {valid(mults["effCha"]) &&Charisma: x{formatNumber(mults["effCha"], 3)}
} + {valid(mults["effInt"]) &&Intelligence: x{formatNumber(mults["effInt"], 3)}
} + {valid(mults["stamina"]) &&Stamina: x{formatNumber(mults["stamina"], 3)}
} + {valid(mults["money"]) &&Contract Money: x{formatNumber(mults["money"], 3)}
} + {valid(mults["expGain"]) &&Exp Gain: x{formatNumber(mults["expGain"], 3)}
} +
- Rank: {formatNumber(props.bladeburner.rank, 2)}
- Stamina: {formatNumber(props.bladeburner.stamina, 3)} / {formatNumber(props.bladeburner.maxStamina, 3)}
+ 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);
+ }
+
+ 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!")
+ // }
+ // }
+ }
+
+ return (<>
+
+ Rank: {formatNumber(props.bladeburner.rank, 2)} + Your rank within the Bladeburner division. +
Stamina: {formatNumber(props.bladeburner.stamina, 3)} / {formatNumber(props.bladeburner.maxStamina, 3)}
Stamina Penalty: {formatNumber((1-props.bladeburner.calculateStaminaPenalty())*100, 1)}%
Team Size: {formatNumber(props.bladeburner.teamSize, 0)}
+Team Members Lost: {formatNumber(props.bladeburner.teamLost, 0)}
Num Times Hospitalized: {props.bladeburner.numHosp}
+Money Lost From Hospitalizations: {Money(props.bladeburner.moneyLost)}
Current City: {props.bladeburner.city}
++ Est. Synthoid Population: {numeralWrapper.formatPopulation(props.bladeburner.getCurrentCity().popEst)} + This is your Bladeburner division's estimate of how many Synthoids exist in your current city. +
+ Est. Synthoid Communities: {formatNumber(props.bladeburner.getCurrentCity().comms, 0)} + This is your Bladeburner divison's estimate of how many Synthoid communities exist in your current city. +
+ City Chaos: {formatNumber(props.bladeburner.getCurrentCity().chaos)} + The city's chaos level due to tensions and conflicts between humans and Synthoids. Having too high of a chaos level can make contracts and operations harder. +
+ Bonus time: {convertTimeMsToTimeElapsedString(props.bladeburner.storedCycles/BladeburnerConstants.CyclesPerSecond*1000)}
+
+ You gain bonus time while offline or when the game is inactive (e.g. when the tab is throttled by browser).
+ Bonus time makes the Bladeburner mechanic progress faster, up to 5x the normal speed.
+
+
Skill Points: {formatNumber(props.bladeburner.skillPoints, 0)}
- {"> "}- |
-
+ {"> "}+ |
+
+ 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 +Lists all factions you have joined
Lists factions you have been invited to. You can accept these faction invitations at any time.