From 5f64187a0f44af4d9b1f7a501391b0314174bc4b Mon Sep 17 00:00:00 2001 From: Olivier Gagnon Date: Fri, 10 Sep 2021 16:57:05 -0400 Subject: [PATCH] dev menu in react --- src/DevMenu.jsx | 1647 ---------------------------------- src/DevMenu.tsx | 1607 +++++++++++++++++++++++++++++++++ src/IEngine.ts | 2 + src/PersonObjects/IPlayer.ts | 10 +- src/SaveObject.d.ts | 1 + src/engine.jsx | 49 +- src/index.html | 1 + src/ui/MainMenu/Links.ts | 1 + 8 files changed, 1643 insertions(+), 1675 deletions(-) delete mode 100644 src/DevMenu.jsx create mode 100644 src/DevMenu.tsx create mode 100644 src/SaveObject.d.ts diff --git a/src/DevMenu.jsx b/src/DevMenu.jsx deleted file mode 100644 index c954591b2..000000000 --- a/src/DevMenu.jsx +++ /dev/null @@ -1,1647 +0,0 @@ -import { AugmentationNames } from "./Augmentation/data/AugmentationNames"; -import { CodingContractTypes } from "./CodingContracts"; -import { generateContract, generateRandomContract, generateRandomContractOnHome } from "./CodingContractGenerator"; -import { Companies } from "./Company/Companies"; -import { Programs } from "./Programs/Programs"; -import { Factions } from "./Faction/Factions"; -import { Player } from "./Player"; -import { PlayerOwnedSourceFile } from "./SourceFile/PlayerOwnedSourceFile"; -import { AllServers } from "./Server/AllServers"; -import { GetServerByHostname } from "./Server/ServerHelpers"; -import { hackWorldDaemon } from "./RedPill"; -import { StockMarket } from "./StockMarket/StockMarket"; -import { Bladeburner } from "./Bladeburner/Bladeburner"; -import { Stock } from "./StockMarket/Stock"; -import { Engine } from "./engine"; -import { saveObject } from "./SaveObject"; - -import { dialogBoxCreate } from "../utils/DialogBox"; -import { createElement } from "../utils/uiHelpers/createElement"; -import { removeElementById } from "../utils/uiHelpers/removeElementById"; -import { Money } from "./ui/React/Money"; - -import React from "react"; -import ReactDOM from "react-dom"; - -const Component = React.Component; - -// Update as additional BitNodes get implemented -const validSFN = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]; - -// Some dev menu buttons just add a lot of something for convenience -const tonsPP = 1e27; -const tonsP = 1e12; - -class ValueAdjusterComponent extends Component { - constructor(props) { - super(props); - this.state = { value: "" }; - this.setValue = this.setValue.bind(this); - } - - setValue(event) { - this.setState({ value: parseFloat(event.target.value) }); - } - - render() { - const { title, add, subtract, reset } = this.props; - return ( - <> - - - - - - ); - } -} - -class DevMenuComponent extends Component { - constructor(props) { - super(props); - this.state = { - company: "ECorp", - faction: "Illuminati", - program: "NUKE.exe", - server: "home", - augmentation: "Augmented Targeting I", - codingcontract: "Find Largest Prime Factor", - }; - - this.setSF = this.setSF.bind(this); - this.setAllSF = this.setAllSF.bind(this); - this.clearExploits = this.clearExploits.bind(this); - this.processStocks = this.processStocks.bind(this); - this.setStockPrice = this.setStockPrice.bind(this); - this.viewStockCaps = this.viewStockCaps.bind(this); - - this.setFactionDropdown = this.setFactionDropdown.bind(this); - this.setCompanyDropdown = this.setCompanyDropdown.bind(this); - this.setProgramDropdown = this.setProgramDropdown.bind(this); - this.setServerDropdown = this.setServerDropdown.bind(this); - this.setAugmentationDropdown = this.setAugmentationDropdown.bind(this); - this.setCodingcontractDropdown = this.setCodingcontractDropdown.bind(this); - - this.receiveInvite = this.receiveInvite.bind(this); - this.modifyFactionRep = this.modifyFactionRep.bind(this); - this.resetFactionRep = this.resetFactionRep.bind(this); - this.modifyFactionFavor = this.modifyFactionFavor.bind(this); - this.resetFactionFavor = this.resetFactionFavor.bind(this); - this.queueAug = this.queueAug.bind(this); - this.addProgram = this.addProgram.bind(this); - this.rootServer = this.rootServer.bind(this); - this.minSecurity = this.minSecurity.bind(this); - this.maxMoney = this.maxMoney.bind(this); - this.modifyCompanyRep = this.modifyCompanyRep.bind(this); - this.resetCompanyRep = this.resetCompanyRep.bind(this); - this.modifyCompanyFavor = this.modifyCompanyFavor.bind(this); - this.resetCompanyFavor = this.resetCompanyFavor.bind(this); - this.specificContract = this.specificContract.bind(this); - } - - setFactionDropdown(event) { - this.setState({ faction: event.target.value }); - } - - setCompanyDropdown(event) { - this.setState({ company: event.target.value }); - } - - setProgramDropdown(event) { - this.setState({ program: event.target.value }); - } - - setServerDropdown(event) { - this.setState({ server: event.target.value }); - } - - setAugmentationDropdown(event) { - this.setState({ augmentation: event.target.value }); - } - - setCodingcontractDropdown(event) { - this.setState({ codingcontract: event.target.value }); - } - - addMoney(n) { - return function () { - Player.gainMoney(n); - }; - } - - upgradeRam() { - Player.getHomeComputer().maxRam *= 2; - } - - quickB1tFlum3() { - hackWorldDaemon(Player.bitNodeN, true, true); - } - - b1tflum3() { - hackWorldDaemon(Player.bitNodeN, true); - } - - quickHackW0r1dD43m0n() { - hackWorldDaemon(Player.bitNodeN, false, true); - } - - hackW0r1dD43m0n() { - hackWorldDaemon(Player.bitNodeN); - } - - modifyExp(stat, modifier) { - return function (exp) { - switch (stat) { - case "hacking": - if (exp) { - Player.gainHackingExp(exp * modifier); - } - break; - case "strength": - if (exp) { - Player.gainStrengthExp(exp * modifier); - } - break; - case "defense": - if (exp) { - Player.gainDefenseExp(exp * modifier); - } - break; - case "dexterity": - if (exp) { - Player.gainDexterityExp(exp * modifier); - } - break; - case "agility": - if (exp) { - Player.gainAgilityExp(exp * modifier); - } - break; - case "charisma": - if (exp) { - Player.gainCharismaExp(exp * modifier); - } - break; - case "intelligence": - if (exp) { - Player.gainIntelligenceExp(exp * modifier); - } - break; - } - Player.updateSkillLevels(); - }; - } - - modifyKarma(modifier) { - return function (amt) { - Player.karma += amt * modifier; - }; - } - - tonsOfExp() { - Player.gainHackingExp(tonsPP); - Player.gainStrengthExp(tonsPP); - Player.gainDefenseExp(tonsPP); - Player.gainDexterityExp(tonsPP); - Player.gainAgilityExp(tonsPP); - Player.gainCharismaExp(tonsPP); - Player.gainIntelligenceExp(tonsPP); - Player.updateSkillLevels(); - } - - resetAllExp() { - Player.hacking_exp = 0; - Player.strength_exp = 0; - Player.defense_exp = 0; - Player.dexterity_exp = 0; - Player.agility_exp = 0; - Player.charisma_exp = 0; - Player.intelligence_exp = 0; - Player.updateSkillLevels(); - } - - resetExperience(stat) { - return function () { - switch (stat) { - case "hacking": - Player.hacking_exp = 0; - break; - case "strength": - Player.strength_exp = 0; - break; - case "defense": - Player.defense_exp = 0; - break; - case "dexterity": - Player.dexterity_exp = 0; - break; - case "agility": - Player.agility_exp = 0; - break; - case "charisma": - Player.charisma_exp = 0; - break; - case "intelligence": - Player.intelligence_exp = 0; - break; - } - Player.updateSkillLevels(); - }; - } - - resetKarma() { - return function () { - Player.karma = 0; - }; - } - - enableIntelligence() { - if (Player.intelligence === 0) { - Player.intelligence = 1; - Player.updateSkillLevels(); - } - } - - disableIntelligence() { - Player.intelligence_exp = 0; - Player.intelligence = 0; - Player.updateSkillLevels(); - } - - receiveInvite() { - Player.receiveInvite(this.state.faction); - } - - receiveAllInvites() { - for (const i in Factions) { - Player.receiveInvite(Factions[i].name); - } - } - - modifyFactionRep(modifier) { - return (reputation) => { - const fac = Factions[this.state.faction]; - if (fac != null && !isNaN(reputation)) { - fac.playerReputation += reputation * modifier; - } - }; - } - - resetFactionRep() { - const fac = Factions[this.state.faction]; - if (fac != null) { - fac.playerReputation = 0; - } - } - - modifyFactionFavor(modifier) { - return (favor) => { - const fac = Factions[this.state.faction]; - if (fac != null && !isNaN(favor)) { - fac.favor += favor * modifier; - } - }; - } - - resetFactionFavor() { - const fac = Factions[this.state.faction]; - if (fac != null) { - fac.favor = 0; - } - } - - tonsOfRep() { - for (const i in Factions) { - Factions[i].playerReputation = tonsPP; - } - } - - resetAllRep() { - for (const i in Factions) { - Factions[i].playerReputation = 0; - } - } - - tonsOfFactionFavor() { - for (const i in Factions) { - Factions[i].favor = tonsPP; - } - } - - resetAllFactionFavor() { - for (const i in Factions) { - Factions[i].favor = 0; - } - } - - queueAug() { - Player.queueAugmentation(this.state.augmentation); - } - - queueAllAugs() { - for (const i in AugmentationNames) { - const augName = AugmentationNames[i]; - Player.queueAugmentation(augName); - } - } - - setSF(sfN, sfLvl) { - return function () { - if (sfLvl === 0) { - Player.sourceFiles = Player.sourceFiles.filter((sf) => sf.n !== sfN); - return; - } - - if (!Player.sourceFiles.some((sf) => sf.n === sfN)) { - Player.sourceFiles.push(new PlayerOwnedSourceFile(sfN, sfLvl)); - return; - } - - for (let i = 0; i < Player.sourceFiles.length; i++) { - if (Player.sourceFiles[i].n === sfN) { - Player.sourceFiles[i].lvl = sfLvl; - } - } - }; - } - - setAllSF(sfLvl) { - return () => { - for (let i = 0; i < validSFN.length; i++) { - this.setSF(validSFN[i], sfLvl)(); - } - }; - } - - clearExploits() { - Player.exploits = []; - } - - addProgram() { - const program = this.state.program; - if (!Player.hasProgram(program)) { - Player.getHomeComputer().programs.push(program); - } - } - - addAllPrograms() { - for (const i in Programs) { - if (!Player.hasProgram(Programs[i].name)) { - Player.getHomeComputer().programs.push(Programs[i].name); - } - } - } - - rootServer() { - const serverName = this.state.server; - const server = GetServerByHostname(serverName); - - server.hasAdminRights = true; - server.sshPortOpen = true; - server.ftpPortOpen = true; - server.smtpPortOpen = true; - server.httpPortOpen = true; - server.sqlPortOpen = true; - server.openPortCount = 5; - } - - rootAllServers() { - for (const i in AllServers) { - AllServers[i].hasAdminRights = true; - AllServers[i].sshPortOpen = true; - AllServers[i].ftpPortOpen = true; - AllServers[i].smtpPortOpen = true; - AllServers[i].httpPortOpen = true; - AllServers[i].sqlPortOpen = true; - AllServers[i].openPortCount = 5; - } - } - - minSecurity() { - const serverName = this.state.server; - const server = GetServerByHostname(serverName); - server.hackDifficulty = server.minDifficulty; - } - - minAllSecurity() { - for (const i in AllServers) { - AllServers[i].hackDifficulty = AllServers[i].minDifficulty; - } - } - - maxMoney() { - const serverName = this.state.server; - const server = GetServerByHostname(serverName); - server.moneyAvailable = server.moneyMax; - } - - maxAllMoney() { - for (const i in AllServers) { - AllServers[i].moneyAvailable = AllServers[i].moneyMax; - } - } - - modifyCompanyRep(modifier) { - return (reputation) => { - const company = Companies[this.state.company]; - if (company != null && !isNaN(reputation)) { - company.playerReputation += reputation * modifier; - } - }; - } - - resetCompanyRep() { - const company = Companies[this.state.company]; - company.playerReputation = 0; - } - - modifyCompanyFavor(modifier) { - return (favor) => { - const company = Companies[this.state.company]; - if (company != null && !isNaN(favor)) { - company.favor += favor * modifier; - } - }; - } - - resetCompanyFavor() { - const company = Companies[this.state.company]; - company.favor = 0; - } - - tonsOfRepCompanies() { - for (const c in Companies) { - Companies[c].playerReputation = tonsP; - } - } - - resetAllRepCompanies() { - for (const c in Companies) { - Companies[c].playerReputation = 0; - } - } - - tonsOfFavorCompanies() { - for (const c in Companies) { - Companies[c].favor = tonsP; - } - } - - resetAllFavorCompanies() { - for (const c in Companies) { - Companies[c].favor = 0; - } - } - - modifyBladeburnerRank(modify) { - return function (rank) { - if (Player.bladeburner) { - Player.bladeburner.changeRank(Player, rank * modify); - } - }; - } - - resetBladeburnerRank() { - Player.bladeburner.rank = 0; - Player.bladeburner.maxRank = 0; - } - - addTonsBladeburnerRank() { - if (Player.bladeburner) { - Player.bladeburner.changeRank(Player, tonsP); - } - } - - modifyBladeburnerCycles(modify) { - return function (cycles) { - if (Player.bladeburner) { - Player.bladeburner.storedCycles += cycles * modify; - } - }; - } - - resetBladeburnerCycles() { - if (Player.bladeburner) { - Player.bladeburner.storedCycles = 0; - } - } - - addTonsBladeburnerCycles() { - if (Player.bladeburner) { - Player.bladeburner.storedCycles += tonsP; - } - } - - addTonsGangCycles() { - if (Player.gang) { - Player.gang.storedCycles = tonsP; - } - } - - modifyGangCycles(modify) { - return function (cycles) { - if (Player.gang) { - Player.gang.storedCycles += cycles * modify; - } - }; - } - - resetGangCycles() { - if (Player.gang) { - Player.gang.storedCycles = 0; - } - } - - addTonsCorporationFunds() { - if (Player.corporation) { - Player.corporation.funds = Player.corporation.funds.plus(1e99); - } - } - - resetCorporationFunds() { - if (Player.corporation) { - Player.corporation.funds = Player.corporation.funds.minus(Player.corporation.funds); - } - } - - addTonsCorporationCycles() { - if (Player.corporation) { - Player.corporation.storedCycles = tonsP; - } - } - - modifyCorporationCycles(modify) { - return function (cycles) { - if (Player.corporation) { - Player.corporation.storedCycles += cycles * modify; - } - }; - } - - resetCorporationCycles() { - if (Player.corporation) { - Player.corporation.storedCycles = 0; - } - } - - finishCorporationProducts() { - if (!Player.corporation) return; - Player.corporation.divisions.forEach((div) => { - Object.keys(div.products).forEach((prod) => (div.products[prod].prog = 99.9)); - }); - } - - addCorporationResearch() { - if (!Player.corporation) return; - Player.corporation.divisions.forEach((div) => { - div.sciResearch.qty += 1e10; - }); - } - - specificContract() { - generateContract({ - problemType: this.state.codingcontract, - server: "home", - }); - } - - processStocks(sub) { - const inputSymbols = document.getElementById("dev-stock-symbol").value.toString().replace(/\s/g, ""); - - let match = function () { - return true; - }; - - if (inputSymbols !== "" && inputSymbols !== "all") { - match = function (symbol) { - return inputSymbols.split(",").includes(symbol); - }; - } - - for (const name in StockMarket) { - if (StockMarket.hasOwnProperty(name)) { - const stock = StockMarket[name]; - if (stock instanceof Stock && match(stock.symbol)) { - sub(stock); - } - } - } - } - - setStockPrice() { - const price = parseFloat(document.getElementById("dev-stock-price").value); - - if (!isNaN(price)) { - this.processStocks((stock) => { - stock.price = price; - }); - } - } - - viewStockCaps() { - let stocks = []; - this.processStocks((stock) => { - stocks.push( - - {stock.symbol} - - - - , - ); - }); - dialogBoxCreate( - - - - - - - {stocks} - -
StockPrice cap
, - ); - } - - sleeveMaxAllShock() { - for (let i = 0; i < Player.sleeves.length; ++i) { - Player.sleeves[i].shock = 0; - } - } - - sleeveClearAllShock() { - for (let i = 0; i < Player.sleeves.length; ++i) { - Player.sleeves[i].shock = 100; - } - } - - sleeveSyncMaxAll() { - for (let i = 0; i < Player.sleeves.length; ++i) { - Player.sleeves[i].sync = 100; - } - } - - sleeveSyncClearAll() { - for (let i = 0; i < Player.sleeves.length; ++i) { - Player.sleeves[i].sync = 0; - } - } - - timeskip(time) { - return () => { - Player.lastUpdate -= time; - Engine._lastUpdate -= time; - saveObject.saveGame(Engine.indexedDb); - setTimeout(() => location.reload(), 1000); - }; - } - - render() { - let factions = []; - for (const i in Factions) { - factions.push( - , - ); - } - - let augs = []; - for (const i in AugmentationNames) { - augs.push( - , - ); - } - - let programs = []; - for (const i in Programs) { - programs.push( - , - ); - } - - let sourceFiles = []; - validSFN.forEach((i) => sourceFiles.push( - - - SF-{i}: - - - - - - - - , - ), - ); - - let servers = []; - for (const i in AllServers) { - const hn = AllServers[i].hostname; - servers.push( - , - ); - } - - let companies = []; - for (const c in Companies) { - const name = Companies[c].name; - companies.push( - , - ); - } - - const contractTypes = []; - const contractTypeNames = Object.keys(CodingContractTypes); - for (let i = 0; i < contractTypeNames.length; i++) { - const name = contractTypeNames[i]; - contractTypes.push( - , - ); - } - - return ( -
-
-

Development Menu - Only meant to be used for testing/debugging

-
-
-

Generic

-
-
- - - - - - -
-
- - - - -
-
-
-
-

Experience / Stats

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- All: - - - -
- Hacking: - - -
- Strength: - - -
- Defense: - - -
- Dexterity: - - -
- Agility: - - -
- Charisma: - - -
- Intelligence: - - - - - - -
- Karma: - - -
-
-
-
-
-
-

Factions

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- Faction: - - -
- Invites: - - - - -
- Reputation: - - -
- Favor: - - -
- All Reputation: - - - -
- All Favor: - - - -
-
-
-
-
-
-

Augmentations

-
- - - - - - - - - - - -
- Aug: - - -
- Queue: - - - -
-
-
-
-
-
-

Source-Files

-
- - - - - - - - - - - {sourceFiles} - -
- Exploits: - - -
- All: - - - - - -
-
-
-
-
-
-

Programs

-
- - - - - - - - - - - -
- Program: - - -
- Add: - - - -
-
-
-
-
-
-

Servers

-
- - - - - - - - - - - - - - - - - - - - - - -
- Server: - - -
- Root: - - - - -
- Security: - - - - -
- Money: - - - - -
-
-
-
-
-
-

Companies

-
- - - - - - - - - - - - - - - - - - - - - - - -
- Company: - - -
- Reputation: - - -
- Favor: - - -
- All Reputation: - - - -
- All Favor: - - - -
-
-
- - {Player.bladeburner instanceof Bladeburner && ( -
-
-
-

Bladeburner

-
- - - - - - - - - - - - - -
- Rank: - - - - -
- Cycles: - - - - -
-
-
- )} - - {Player.inGang() && ( -
-
-
-

Gang

-
- - - - - - - - -
- Cycles: - - - - -
-
-
- )} - - {Player.hasCorporation() && ( -
-
-
-

Corporation

-
- - - - - - - - - - - - - - - - - -
- - -
- Cycles: - - - - -
- -
- -
-
-
- )} - -
-
-
-

Coding Contracts

-
- - - - - - - - - -
- - -
- - -
-
-
- - {Player.hasWseAccount && ( -
-
-
-

Stock Market

-
- - - - - - - - - - - - - - - -
- Symbol: - - -
- Price: - - - -
- Caps: - - -
-
-
- )} - - {Player.sleeves.length > 0 && ( -
-
-
-

Sleeves

-
- - - - - - - - - - - - - -
- Shock: - - - - -
- Sync: - - - - -
-
-
- )} - -
-
-
-

Offline time skip:

-
-
- - - -
-
-
-
- ); - } -} - -const devMenuContainerId = "dev-menu-container"; - -export function createDevMenu() { - if (process.env.NODE_ENV !== "development") { - throw new Error("Cannot create Dev Menu because you are not in a dev build"); - } - - // Add everything to container, then append to main menu - const devMenuContainer = createElement("div", { - class: "generic-menupage-container", - id: devMenuContainerId, - }); - - const entireGameContainer = document.getElementById("entire-game-container"); - if (entireGameContainer == null) { - throw new Error("Could not find entire-game-container DOM element"); - } - entireGameContainer.appendChild(devMenuContainer); - - ReactDOM.render(, devMenuContainer); -} - -export function closeDevMenu() { - removeElementById(devMenuContainerId); -} diff --git a/src/DevMenu.tsx b/src/DevMenu.tsx new file mode 100644 index 000000000..8f56df0fe --- /dev/null +++ b/src/DevMenu.tsx @@ -0,0 +1,1607 @@ +import { AugmentationNames } from "./Augmentation/data/AugmentationNames"; +import { CodingContractTypes } from "./CodingContracts"; +import { generateContract, generateRandomContract, generateRandomContractOnHome } from "./CodingContractGenerator"; +import { Companies } from "./Company/Companies"; +import { Programs } from "./Programs/Programs"; +import { Factions } from "./Faction/Factions"; +import { Player } from "./Player"; +import { IPlayer } from "./PersonObjects/IPlayer"; +import { PlayerOwnedSourceFile } from "./SourceFile/PlayerOwnedSourceFile"; +import { AllServers } from "./Server/AllServers"; +import { HacknetServer } from "./Hacknet/HacknetServer"; +import { GetServerByHostname } from "./Server/ServerHelpers"; +import { hackWorldDaemon } from "./RedPill"; +import { StockMarket } from "./StockMarket/StockMarket"; +import { Bladeburner } from "./Bladeburner/Bladeburner"; +import { Stock } from "./StockMarket/Stock"; +import { IEngine } from "./IEngine"; +import { saveObject } from "./SaveObject"; + +import { dialogBoxCreate } from "../utils/DialogBox"; +import { createElement } from "../utils/uiHelpers/createElement"; +import { removeElementById } from "../utils/uiHelpers/removeElementById"; +import { Money } from "./ui/React/Money"; + +import React, { useState } from "react"; +import ReactDOM from "react-dom"; + +const Component = React.Component; + +// Update as additional BitNodes get implemented +const validSFN = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]; + +// Some dev menu buttons just add a lot of something for convenience +const tonsPP = 1e27; +const tonsP = 1e12; + +interface IValueAdjusterProps { + title: string; + add: (x: number) => void; + subtract: (x: number) => void; + reset: () => void; +} + +function ValueAdjusterComponent(props: IValueAdjusterProps) { + const [value, setValue] = useState(0); + + function onChange(event: React.ChangeEvent): void { + setValue(parseFloat(event.target.value)); + } + + const { title, add, subtract, reset } = props; + return ( + <> + + + + + + ); +} + +interface IProps { + player: IPlayer; + engine: IEngine; +} + +export function DevMenuRoot(props: IProps): React.ReactElement { + const [company, setCompany] = useState("ECorp"); + const [faction, setFaction] = useState("Illuminati"); + const [program, setProgram] = useState("NUKE.exe"); + const [server, setServer] = useState("home"); + const [augmentation, setAugmentation] = useState("Augmented Targeting I"); + const [codingcontract, setCodingcontract] = useState("Find Largest Prime Factor"); + const [stockPrice, setStockPrice] = useState(0); + const [stockSymbol, setStockSymbol] = useState(""); + + function setFactionDropdown(event: React.ChangeEvent): void { + setFaction(event.target.value); + } + + function setCompanyDropdown(event: React.ChangeEvent): void { + setCompany(event.target.value); + } + + function setProgramDropdown(event: React.ChangeEvent): void { + setProgram(event.target.value); + } + + function setServerDropdown(event: React.ChangeEvent): void { + setServer(event.target.value); + } + + function setAugmentationDropdown(event: React.ChangeEvent): void { + setAugmentation(event.target.value); + } + + function setCodingcontractDropdown(event: React.ChangeEvent): void { + setCodingcontract(event.target.value); + } + + function setStockPriceField(event: React.ChangeEvent): void { + setStockPrice(parseFloat(event.target.value)); + } + + function setStockSymbolField(event: React.ChangeEvent): void { + setStockSymbol(event.target.value); + } + + function addMoney(n: number) { + return function () { + Player.gainMoney(n); + }; + } + + function upgradeRam() { + Player.getHomeComputer().maxRam *= 2; + } + + function quickB1tFlum3() { + hackWorldDaemon(Player.bitNodeN, true, true); + } + + function b1tflum3() { + hackWorldDaemon(Player.bitNodeN, true); + } + + function quickHackW0r1dD43m0n() { + hackWorldDaemon(Player.bitNodeN, false, true); + } + + function hackW0r1dD43m0n() { + hackWorldDaemon(Player.bitNodeN); + } + + function modifyExp(stat: string, modifier: number) { + return function (exp: number) { + switch (stat) { + case "hacking": + if (exp) { + Player.gainHackingExp(exp * modifier); + } + break; + case "strength": + if (exp) { + Player.gainStrengthExp(exp * modifier); + } + break; + case "defense": + if (exp) { + Player.gainDefenseExp(exp * modifier); + } + break; + case "dexterity": + if (exp) { + Player.gainDexterityExp(exp * modifier); + } + break; + case "agility": + if (exp) { + Player.gainAgilityExp(exp * modifier); + } + break; + case "charisma": + if (exp) { + Player.gainCharismaExp(exp * modifier); + } + break; + case "intelligence": + if (exp) { + Player.gainIntelligenceExp(exp * modifier); + } + break; + } + Player.updateSkillLevels(); + }; + } + + function modifyKarma(modifier: number) { + return function (amt: number) { + Player.karma += amt * modifier; + }; + } + + function tonsOfExp() { + Player.gainHackingExp(tonsPP); + Player.gainStrengthExp(tonsPP); + Player.gainDefenseExp(tonsPP); + Player.gainDexterityExp(tonsPP); + Player.gainAgilityExp(tonsPP); + Player.gainCharismaExp(tonsPP); + Player.gainIntelligenceExp(tonsPP); + Player.updateSkillLevels(); + } + + function resetAllExp() { + Player.hacking_exp = 0; + Player.strength_exp = 0; + Player.defense_exp = 0; + Player.dexterity_exp = 0; + Player.agility_exp = 0; + Player.charisma_exp = 0; + Player.intelligence_exp = 0; + Player.updateSkillLevels(); + } + + function resetExperience(stat: string): () => void { + return function () { + switch (stat) { + case "hacking": + Player.hacking_exp = 0; + break; + case "strength": + Player.strength_exp = 0; + break; + case "defense": + Player.defense_exp = 0; + break; + case "dexterity": + Player.dexterity_exp = 0; + break; + case "agility": + Player.agility_exp = 0; + break; + case "charisma": + Player.charisma_exp = 0; + break; + case "intelligence": + Player.intelligence_exp = 0; + break; + } + Player.updateSkillLevels(); + }; + } + + function resetKarma() { + return function () { + Player.karma = 0; + }; + } + + function enableIntelligence() { + if (Player.intelligence === 0) { + Player.intelligence = 1; + Player.updateSkillLevels(); + } + } + + function disableIntelligence() { + Player.intelligence_exp = 0; + Player.intelligence = 0; + Player.updateSkillLevels(); + } + + function receiveInvite() { + Player.receiveInvite(faction); + } + + function receiveAllInvites() { + for (const i in Factions) { + Player.receiveInvite(Factions[i].name); + } + } + + function modifyFactionRep(modifier: number): (x: number) => void { + return function (reputation: number): void { + const fac = Factions[faction]; + if (fac != null && !isNaN(reputation)) { + fac.playerReputation += reputation * modifier; + } + }; + } + + function resetFactionRep() { + const fac = Factions[faction]; + if (fac != null) { + fac.playerReputation = 0; + } + } + + function modifyFactionFavor(modifier: number): (x: number) => void { + return function (favor: number): void { + const fac = Factions[faction]; + if (fac != null && !isNaN(favor)) { + fac.favor += favor * modifier; + } + }; + } + + function resetFactionFavor() { + const fac = Factions[faction]; + if (fac != null) { + fac.favor = 0; + } + } + + function tonsOfRep() { + for (const i in Factions) { + Factions[i].playerReputation = tonsPP; + } + } + + function resetAllRep() { + for (const i in Factions) { + Factions[i].playerReputation = 0; + } + } + + function tonsOfFactionFavor() { + for (const i in Factions) { + Factions[i].favor = tonsPP; + } + } + + function resetAllFactionFavor() { + for (const i in Factions) { + Factions[i].favor = 0; + } + } + + function queueAug() { + Player.queueAugmentation(augmentation); + } + + function queueAllAugs() { + for (const i in AugmentationNames) { + const augName = AugmentationNames[i]; + Player.queueAugmentation(augName); + } + } + + function setSF(sfN: number, sfLvl: number) { + return function () { + if (sfLvl === 0) { + Player.sourceFiles = Player.sourceFiles.filter((sf) => sf.n !== sfN); + return; + } + + if (!Player.sourceFiles.some((sf) => sf.n === sfN)) { + Player.sourceFiles.push(new PlayerOwnedSourceFile(sfN, sfLvl)); + return; + } + + for (let i = 0; i < Player.sourceFiles.length; i++) { + if (Player.sourceFiles[i].n === sfN) { + Player.sourceFiles[i].lvl = sfLvl; + } + } + }; + } + + function setAllSF(sfLvl: number) { + return () => { + for (let i = 0; i < validSFN.length; i++) { + setSF(validSFN[i], sfLvl)(); + } + }; + } + + function clearExploits() { + Player.exploits = []; + } + + function addProgram() { + if (!Player.hasProgram(program)) { + Player.getHomeComputer().programs.push(program); + } + } + + function addAllPrograms() { + for (const i in Programs) { + if (!Player.hasProgram(Programs[i].name)) { + Player.getHomeComputer().programs.push(Programs[i].name); + } + } + } + + function rootServer() { + const s = GetServerByHostname(server); + if (s === null) return; + if (s instanceof HacknetServer) return; + s.hasAdminRights = true; + s.sshPortOpen = true; + s.ftpPortOpen = true; + s.smtpPortOpen = true; + s.httpPortOpen = true; + s.sqlPortOpen = true; + s.openPortCount = 5; + } + + function rootAllServers() { + for (const i in AllServers) { + const s = AllServers[i]; + if (s instanceof HacknetServer) return; + s.hasAdminRights = true; + s.sshPortOpen = true; + s.ftpPortOpen = true; + s.smtpPortOpen = true; + s.httpPortOpen = true; + s.sqlPortOpen = true; + s.openPortCount = 5; + } + } + + function minSecurity() { + const s = GetServerByHostname(server); + if (s === null) return; + if (s instanceof HacknetServer) return; + s.hackDifficulty = s.minDifficulty; + } + + function minAllSecurity() { + for (const i in AllServers) { + const server = AllServers[i]; + if (server instanceof HacknetServer) continue; + server.hackDifficulty = server.minDifficulty; + } + } + + function maxMoney() { + const s = GetServerByHostname(server); + if (s === null) return; + if (s instanceof HacknetServer) return; + s.moneyAvailable = s.moneyMax; + } + + function maxAllMoney() { + for (const i in AllServers) { + const server = AllServers[i]; + if (server instanceof HacknetServer) continue; + server.moneyAvailable = server.moneyMax; + } + } + + function modifyCompanyRep(modifier: number): (x: number) => void { + return function (reputation: number): void { + const c = Companies[company]; + if (c != null && !isNaN(reputation)) { + c.playerReputation += reputation * modifier; + } + }; + } + + function resetCompanyRep(): void { + Companies[company].playerReputation = 0; + } + + function modifyCompanyFavor(modifier: number): (x: number) => void { + return function (favor: number): void { + const c = Companies[company]; + if (c != null && !isNaN(favor)) { + c.favor += favor * modifier; + } + }; + } + + function resetCompanyFavor(): void { + Companies[company].favor = 0; + } + + function tonsOfRepCompanies(): void { + for (const c in Companies) { + Companies[c].playerReputation = tonsP; + } + } + + function resetAllRepCompanies(): void { + for (const c in Companies) { + Companies[c].playerReputation = 0; + } + } + + function tonsOfFavorCompanies(): void { + for (const c in Companies) { + Companies[c].favor = tonsP; + } + } + + function resetAllFavorCompanies(): void { + for (const c in Companies) { + Companies[c].favor = 0; + } + } + + function modifyBladeburnerRank(modify: number): (x: number) => void { + return function (rank: number): void { + if (Player.bladeburner) { + Player.bladeburner.changeRank(Player, rank * modify); + } + }; + } + + function resetBladeburnerRank(): void { + Player.bladeburner.rank = 0; + Player.bladeburner.maxRank = 0; + } + + function addTonsBladeburnerRank(): void { + if (Player.bladeburner) { + Player.bladeburner.changeRank(Player, tonsP); + } + } + + function modifyBladeburnerCycles(modify: number): (x: number) => void { + return function (cycles: number): void { + if (Player.bladeburner) { + Player.bladeburner.storedCycles += cycles * modify; + } + }; + } + + function resetBladeburnerCycles(): void { + if (Player.bladeburner) { + Player.bladeburner.storedCycles = 0; + } + } + + function addTonsBladeburnerCycles(): void { + if (Player.bladeburner) { + Player.bladeburner.storedCycles += tonsP; + } + } + + function addTonsGangCycles(): void { + if (Player.gang) { + Player.gang.storedCycles = tonsP; + } + } + + function modifyGangCycles(modify: number): (x: number) => void { + return function (cycles: number): void { + if (Player.gang) { + Player.gang.storedCycles += cycles * modify; + } + }; + } + + function resetGangCycles(): void { + if (Player.gang) { + Player.gang.storedCycles = 0; + } + } + + function addTonsCorporationFunds(): void { + if (Player.corporation) { + Player.corporation.funds = Player.corporation.funds.plus(1e99); + } + } + + function resetCorporationFunds(): void { + if (Player.corporation) { + Player.corporation.funds = Player.corporation.funds.minus(Player.corporation.funds); + } + } + + function addTonsCorporationCycles() { + if (Player.corporation) { + Player.corporation.storedCycles = tonsP; + } + } + + function modifyCorporationCycles(modify: number): (x: number) => void { + return function (cycles: number): void { + if (Player.corporation) { + Player.corporation.storedCycles += cycles * modify; + } + }; + } + + function resetCorporationCycles() { + if (Player.corporation) { + Player.corporation.storedCycles = 0; + } + } + + function finishCorporationProducts() { + if (!Player.corporation) return; + Player.corporation.divisions.forEach((div) => { + Object.keys(div.products).forEach((prod) => { + const product = div.products[prod]; + if (product === undefined) throw new Error("Impossible product undefined"); + product.prog = 99.9; + }); + }); + } + + function addCorporationResearch() { + if (!Player.corporation) return; + Player.corporation.divisions.forEach((div) => { + div.sciResearch.qty += 1e10; + }); + } + + function specificContract() { + generateContract({ + problemType: codingcontract, + server: "home", + }); + } + + function processStocks(sub: (arg0: Stock) => void) { + const inputSymbols = stockSymbol.replace(/\s/g, ""); + + let match = function (symbol: string) { + return true; + }; + + if (inputSymbols !== "" && inputSymbols !== "all") { + match = function (symbol: string) { + return inputSymbols.split(",").includes(symbol); + }; + } + + for (const name in StockMarket) { + if (StockMarket.hasOwnProperty(name)) { + const stock = StockMarket[name]; + if (stock instanceof Stock && match(stock.symbol)) { + sub(stock); + } + } + } + } + + function doSetStockPrice() { + if (!isNaN(stockPrice)) { + processStocks((stock: Stock) => { + stock.price = stockPrice; + }); + } + } + + function viewStockCaps() { + let stocks: JSX.Element[] = []; + processStocks((stock: Stock) => { + stocks.push( + + {stock.symbol} + + + + , + ); + }); + dialogBoxCreate( + + + + + + + {stocks} + +
StockPrice cap
, + ); + } + + function sleeveMaxAllShock() { + for (let i = 0; i < Player.sleeves.length; ++i) { + Player.sleeves[i].shock = 0; + } + } + + function sleeveClearAllShock() { + for (let i = 0; i < Player.sleeves.length; ++i) { + Player.sleeves[i].shock = 100; + } + } + + function sleeveSyncMaxAll() { + for (let i = 0; i < Player.sleeves.length; ++i) { + Player.sleeves[i].sync = 100; + } + } + + function sleeveSyncClearAll() { + for (let i = 0; i < Player.sleeves.length; ++i) { + Player.sleeves[i].sync = 0; + } + } + + function timeskip(time: number) { + return () => { + Player.lastUpdate -= time; + props.engine._lastUpdate -= time; + saveObject.saveGame(props.engine.indexedDb); + setTimeout(() => location.reload(), 1000); + }; + } + + let factions = []; + for (const i in Factions) { + factions.push( + , + ); + } + + let augs = []; + for (const i in AugmentationNames) { + augs.push( + , + ); + } + + let programs = []; + for (const i in Programs) { + programs.push( + , + ); + } + + let servers = []; + for (const i in AllServers) { + const hn = AllServers[i].hostname; + servers.push( + , + ); + } + + let companies = []; + for (const c in Companies) { + const name = Companies[c].name; + companies.push( + , + ); + } + + const contractTypes = []; + const contractTypeNames = Object.keys(CodingContractTypes); + for (let i = 0; i < contractTypeNames.length; i++) { + const name = contractTypeNames[i]; + contractTypes.push( + , + ); + } + + return ( +
+
+

Development Menu - Only meant to be used for testing/debugging

+
+
+

Generic

+
+
+ + + + + + +
+
+ + + + +
+
+
+
+

Experience / Stats

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ All: + + + +
+ Hacking: + + +
+ Strength: + + +
+ Defense: + + +
+ Dexterity: + + +
+ Agility: + + +
+ Charisma: + + +
+ Intelligence: + + + + + + +
+ Karma: + + +
+
+
+
+
+
+

Factions

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ Faction: + + +
+ Invites: + + + + +
+ Reputation: + + +
+ Favor: + + +
+ All Reputation: + + + +
+ All Favor: + + + +
+
+
+
+
+
+

Augmentations

+
+ + + + + + + + + + + +
+ Aug: + + +
+ Queue: + + + +
+
+
+
+
+
+

Source-Files

+
+ + + + + + + + + + + {validSFN.map((i) => ( + + + + + ))} + +
+ Exploits: + + +
+ All: + + + + + +
+ SF-{i}: + + + + + +
+
+
+
+
+
+

Programs

+
+ + + + + + + + + + + +
+ Program: + + +
+ Add: + + + +
+
+
+
+
+
+

Servers

+
+ + + + + + + + + + + + + + + + + + + + + + +
+ Server: + + +
+ Root: + + + + +
+ Security: + + + + +
+ Money: + + + + +
+
+
+
+
+
+

Companies

+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ Company: + + +
+ Reputation: + + +
+ Favor: + + +
+ All Reputation: + + + +
+ All Favor: + + + +
+
+
+ + {Player.bladeburner instanceof Bladeburner && ( +
+
+
+

Bladeburner

+
+ + + + + + + + + + + + + +
+ Rank: + + + + +
+ Cycles: + + + + +
+
+
+ )} + + {Player.inGang() && ( +
+
+
+

Gang

+
+ + + + + + + + +
+ Cycles: + + + + +
+
+
+ )} + + {Player.hasCorporation() && ( +
+
+
+

Corporation

+
+ + + + + + + + + + + + + + + + + +
+ + +
+ Cycles: + + + + +
+ +
+ +
+
+
+ )} + +
+
+
+

Coding Contracts

+
+ + + + + + + + + +
+ + +
+ + +
+
+
+ + {Player.hasWseAccount && ( +
+
+
+

Stock Market

+
+ + + + + + + + + + + + + + + +
+ Symbol: + + +
+ Price: + + + +
+ Caps: + + +
+
+
+ )} + + {Player.sleeves.length > 0 && ( +
+
+
+

Sleeves

+
+ + + + + + + + + + + + + +
+ Shock: + + + + +
+ Sync: + + + + +
+
+
+ )} + +
+
+
+

Offline time skip:

+
+
+ + + +
+
+
+
+ ); +} diff --git a/src/IEngine.ts b/src/IEngine.ts index 7dec95fc4..f43e3cdf9 100644 --- a/src/IEngine.ts +++ b/src/IEngine.ts @@ -3,6 +3,8 @@ * to TypeScript at the moment */ export interface IEngine { + indexedDb: any; + _lastUpdate: number; hideAllContent: () => void; loadBladeburnerContent: () => void; loadFactionContent: () => void; diff --git a/src/PersonObjects/IPlayer.ts b/src/PersonObjects/IPlayer.ts index 383e492bf..8d53ae444 100644 --- a/src/PersonObjects/IPlayer.ts +++ b/src/PersonObjects/IPlayer.ts @@ -21,15 +21,18 @@ import { IPlayerOwnedSourceFile } from "../SourceFile/PlayerOwnedSourceFile"; import { MoneySourceTracker } from "../utils/MoneySourceTracker"; import { Exploit } from "../Exploits/Exploit"; import { ICorporation } from "../Corporation/ICorporation"; +import { IGang } from "../Gang/IGang"; +import { IBladeburner } from "../Bladeburner/IBladeburner"; export interface IPlayer { // Class members augmentations: IPlayerOwnedAugmentation[]; - bladeburner: any; bitNodeN: number; city: CityName; companyName: string; corporation: ICorporation; + gang: IGang; + bladeburner: IBladeburner; currentServer: string; factions: string[]; factionInvitations: string[]; @@ -63,6 +66,7 @@ export interface IPlayer { sleevesFromCovenant: number; sourceFiles: IPlayerOwnedSourceFile[]; exploits: Exploit[]; + lastUpdate: number; totalPlaytime: number; // Stats @@ -81,6 +85,7 @@ export interface IPlayer { dexterity_exp: number; agility_exp: number; charisma_exp: number; + intelligence_exp: number; // Multipliers hacking_chance_mult: number; @@ -193,4 +198,7 @@ export interface IPlayer { quitJob(company: string): void; createHacknetServer(): void; startCreateProgramWork(programName: string, time: number, reqLevel: number): void; + queueAugmentation(augmentationName: string): void; + receiveInvite(factionName: string): void; + updateSkillLevels(): void; } diff --git a/src/SaveObject.d.ts b/src/SaveObject.d.ts new file mode 100644 index 000000000..8e1131a79 --- /dev/null +++ b/src/SaveObject.d.ts @@ -0,0 +1 @@ +export declare const saveObject: any; diff --git a/src/engine.jsx b/src/engine.jsx index 7f40aa2bd..7e1165882 100644 --- a/src/engine.jsx +++ b/src/engine.jsx @@ -21,7 +21,7 @@ import { generateRandomContract } from "./CodingContractGenerator"; import { initCompanies } from "./Company/Companies"; import { Corporation } from "./Corporation/Corporation"; import { CONSTANTS } from "./Constants"; -import { createDevMenu, closeDevMenu } from "./DevMenu"; +import { DevMenuRoot } from "./DevMenu"; import { Factions, initFactions } from "./Faction/Factions"; import { processPassiveFactionRepGain, inviteToFaction } from "./Faction/FactionHelpers"; import { FactionList } from "./Faction/ui/FactionList"; @@ -188,6 +188,7 @@ const Engine = { factionContent: null, augmentationsContent: null, milestonesContent: null, + devMenuContent: null, tutorialContent: null, infiltrationContent: null, stockMarketContent: null, @@ -313,7 +314,11 @@ const Engine = { // TODO reactify loadDevMenuContent: function () { Engine.hideAllContent(); - createDevMenu(); + if (process.env.NODE_ENV !== "development") { + throw new Error("Cannot create Dev Menu because you are not in a dev build"); + } + Engine.Display.devMenuContent.style.display = "block"; + ReactDOM.render(, Engine.Display.devMenuContent); routing.navigateTo(Page.DevMenu); MainMenuLinks.DevMenu.classList.add("active"); }, @@ -472,6 +477,7 @@ const Engine = { Engine.Display.activeScriptsContent.style.display = "none"; ReactDOM.unmountComponentAtNode(Engine.Display.activeScriptsContent); + Engine.Display.infiltrationContent.style.display = "none"; ReactDOM.unmountComponentAtNode(Engine.Display.infiltrationContent); @@ -479,6 +485,7 @@ const Engine = { ReactDOM.unmountComponentAtNode(Engine.Display.hacknetNodesContent); Engine.Display.createProgramContent.style.display = "none"; + ReactDOM.unmountComponentAtNode(Engine.Display.createProgramContent); Engine.Display.factionsContent.style.display = "none"; ReactDOM.unmountComponentAtNode(Engine.Display.factionsContent); @@ -489,8 +496,14 @@ const Engine = { Engine.Display.augmentationsContent.style.display = "none"; ReactDOM.unmountComponentAtNode(Engine.Display.augmentationsContent); - Engine.Display.milestonesContent.style.display = "none"; Engine.Display.tutorialContent.style.display = "none"; + ReactDOM.unmountComponentAtNode(Engine.Display.tutorialContent); + + Engine.Display.milestonesContent.style.display = "none"; + ReactDOM.unmountComponentAtNode(Engine.Display.milestonesContent); + + Engine.Display.devMenuContent.style.display = "none"; + ReactDOM.unmountComponentAtNode(Engine.Display.devMenuContent); Engine.Display.locationContent.style.display = "none"; ReactDOM.unmountComponentAtNode(Engine.Display.locationContent); @@ -518,34 +531,13 @@ const Engine = { // Make nav menu tabs inactive Engine.inactivateMainMenuLinks(); - - // Close dev menu - closeDevMenu(); }, // Remove 'active' css class from all main menu links inactivateMainMenuLinks: function () { - MainMenuLinks.Terminal.classList.remove("active"); - MainMenuLinks.ScriptEditor.classList.remove("active"); - MainMenuLinks.ActiveScripts.classList.remove("active"); - MainMenuLinks.CreateProgram.classList.remove("active"); - MainMenuLinks.Stats.classList.remove("active"); - MainMenuLinks.Factions.classList.remove("active"); - MainMenuLinks.Augmentations.classList.remove("active"); - MainMenuLinks.HacknetNodes.classList.remove("active"); - MainMenuLinks.Sleeves.classList.remove("active"); - MainMenuLinks.City.classList.remove("active"); - MainMenuLinks.Travel.classList.remove("active"); - MainMenuLinks.Job.classList.remove("active"); - MainMenuLinks.StockMarket.classList.remove("active"); - MainMenuLinks.Gang.classList.remove("active"); - MainMenuLinks.Bladeburner.classList.remove("active"); - MainMenuLinks.Corporation.classList.remove("active"); - MainMenuLinks.Gang.classList.remove("active"); - MainMenuLinks.Milestones.classList.remove("active"); - MainMenuLinks.Tutorial.classList.remove("active"); - MainMenuLinks.Options.classList.remove("active"); - MainMenuLinks.DevMenu.classList.remove("active"); + for (const link of Object.keys(MainMenuLinks)) { + MainMenuLinks[link].classList.remove("active"); + } }, displayCharacterOverviewInfo: function () { @@ -1225,6 +1217,9 @@ const Engine = { Engine.Display.milestonesContent = document.getElementById("milestones-container"); Engine.Display.milestonesContent.style.display = "none"; + Engine.Display.devMenuContent = document.getElementById("dev-menu-container"); + Engine.Display.devMenuContent.style.display = "none"; + Engine.Display.tutorialContent = document.getElementById("tutorial-container"); Engine.Display.tutorialContent.style.display = "none"; diff --git a/src/index.html b/src/index.html index 943739abd..1359fc3e7 100644 --- a/src/index.html +++ b/src/index.html @@ -166,6 +166,7 @@
+