mirror of
https://github.com/bitburner-official/bitburner-src.git
synced 2024-11-26 01:23:49 +01:00
Merge branch 'dev' of github.com:danielyxie/bitburner into dev
This commit is contained in:
commit
444c74ccd9
@ -3,22 +3,22 @@
|
|||||||
## In General
|
## In General
|
||||||
|
|
||||||
The game is made better because the community as a whole speaks up about
|
The game is made better because the community as a whole speaks up about
|
||||||
ways to improve the game. Here's some of the ways you can make your voice
|
ways to improve the game. Here are some of the ways you can make your voice
|
||||||
heard:
|
heard:
|
||||||
|
|
||||||
- [Discord](https://discord.gg/XKEGvHqVr3)
|
- [Discord](https://discord.gg/XKEGvHqVr3).
|
||||||
There is a dedicated Discord instance set up for more free-form chats
|
There is a dedicated Discord instance set up for more free-form chats
|
||||||
between all members of the community. Regular players, heavy scripters,
|
between all members of the community. Regular players, heavy scripters,
|
||||||
Bitburner contributors, and everyone in between can be found on the
|
Bitburner contributors, and everyone in between can be found on the
|
||||||
server.
|
server.
|
||||||
- [Github Issues](https://github.com/danielyxie/bitburner/issues)
|
- [Github Issues](https://github.com/danielyxie/bitburner/issues).
|
||||||
Although the term "issues" can have a negative connotation, they are a
|
Although the term "issues" can have a negative connotation, they are a
|
||||||
means of communicating with the community. A new Issue can be a
|
means of communicating with the community. A new Issue can be an
|
||||||
interesting new feature that you feel would improve the game. It could be
|
interesting new feature that you feel would improve the game. It could be
|
||||||
an unexpected behavior within the game. Or because the game is about
|
an unexpected behavior within the game. Or because the game is about
|
||||||
scripting perhaps there is something that is conflicting with the
|
scripting perhaps there is something that is conflicting with the
|
||||||
browser's Javascript interaction. So please do not be afraid to open a
|
browser's JavaScript interaction. So please do not be afraid to open a
|
||||||
[new issue](https://github.com/danielyxie/bitburner/issues/new).
|
[new Issue](https://github.com/danielyxie/bitburner/issues/new).
|
||||||
|
|
||||||
## Reporting Bugs
|
## Reporting Bugs
|
||||||
|
|
||||||
@ -33,16 +33,17 @@ already been reported as an [Issue](https://github.com/danielyxie/bitburner/issu
|
|||||||
|
|
||||||
#### How to Submit a Good Bug Report
|
#### How to Submit a Good Bug Report
|
||||||
|
|
||||||
- **Use a clear and descriptive title** for the issue
|
- **Use a clear and descriptive title** for the Issue.
|
||||||
- **State your browser, your browser's version, and your computer's OS**
|
- **State your browser, your browser's version, and your computer's OS.**
|
||||||
- **Attach your save file**, if you think it would help solve the issue
|
- **Attach your save file**, if you think it would help solve the Issue.
|
||||||
|
Zip your save file first, then attach the zipped save file.
|
||||||
- **Provide instructions on how to reproduce the bug** in as much detail
|
- **Provide instructions on how to reproduce the bug** in as much detail
|
||||||
as possible. If you cannot reliably reproduce the bug, then just try
|
as possible. If you cannot reliably reproduce the bug, then just try
|
||||||
your best to explain what was happening when the bug occurred
|
your best to explain what was happening when the bug occurred.
|
||||||
- **Provide any scripts** that triggered the bug if the issue is Netscript-related
|
- **Provide any scripts** that triggered the bug if the Issue is Netscript-related.
|
||||||
- **Open your browser's Dev Console and report any error-related output**
|
- **Open your browser's Dev Console and report any error-related output**
|
||||||
that may be printed there. The Dev Console can be opened on most modern
|
that may be printed there. The Dev Console can be opened on most modern
|
||||||
browsers by pressing F12
|
browsers by pressing F12.
|
||||||
|
|
||||||
## As a Developer
|
## As a Developer
|
||||||
|
|
||||||
@ -71,13 +72,13 @@ changes are okay to contribute:
|
|||||||
|
|
||||||
##### Contributions that Will Most Likely Be Accepted
|
##### Contributions that Will Most Likely Be Accepted
|
||||||
|
|
||||||
- Bug Fixes
|
- Bug fixes
|
||||||
- Quality-of-Life Changes
|
- Quality-of-life changes
|
||||||
- Adding a new, commonly-requested Netscript function
|
- Adding a new, commonly-requested Netscript function
|
||||||
- Fixing or improving UI elements
|
- Fixing or improving UI elements
|
||||||
- Adding game settings/options
|
- Adding game settings/options
|
||||||
- Adding a new Terminal command
|
- Adding a new Terminal command
|
||||||
- Code Refactors that conform to good/standard practices
|
- Code refactors that conform to good/standard practices
|
||||||
|
|
||||||
##### Contributions that will not be Accepted without prior approval
|
##### Contributions that will not be Accepted without prior approval
|
||||||
|
|
||||||
@ -88,67 +89,108 @@ changes are okay to contribute:
|
|||||||
|
|
||||||
## How to setup fork properly
|
## How to setup fork properly
|
||||||
|
|
||||||
Fork and clone the repo
|
Clone and fork the game's repository by using one of these methods: web browser, GitHub
|
||||||
|
Desktop, or command line.
|
||||||
|
|
||||||
```
|
- Web browser. Log in to your GitHub account, navigate to the
|
||||||
# This will add the game original code as a repo in your local copy
|
[game's repository](https://github.com/danielyxie/bitburner), and fork the
|
||||||
$ git remote add danielyxie git@github.com:danielyxie/bitburner.git
|
repository. Refer to
|
||||||
|
[this page](https://docs.github.com/en/get-started/quickstart/fork-a-repo) for more
|
||||||
|
detail.
|
||||||
|
- GitHub Desktop. Click on `File`, then click `Clone repository`. Click on the `URL`
|
||||||
|
tab and type `danielyxie/bitburner` into the text box for repository URL. Choose
|
||||||
|
the path where you want to clone the repository and click the `Clone` button.
|
||||||
|
Refer to [this page](https://docs.github.com/en/desktop/contributing-and-collaborating-using-github-desktop/adding-and-cloning-repositories/cloning-and-forking-repositories-from-github-desktop)
|
||||||
|
for more detail.
|
||||||
|
- Command line.
|
||||||
|
|
||||||
# You can verify you did this right by doing the following command
|
```sh
|
||||||
$ git remote show
|
# This clones the game's code repository. The output you get might vary.
|
||||||
danielyxie
|
$ git clone https://github.com/danielyxie/bitburner.git
|
||||||
origin
|
Cloning into 'bitburner'...
|
||||||
|
remote: Enumerating objects: 57072, done.
|
||||||
|
remote: Counting objects: 100% (404/404), done.
|
||||||
|
remote: Compressing objects: 100% (205/205), done.
|
||||||
|
remote: Total 57072 (delta 210), reused 375 (delta 199), pack-reused 56668
|
||||||
|
Receiving objects: 100% (57072/57072), 339.11 MiB | 5.42 MiB/s, done.
|
||||||
|
Resolving deltas: 100% (43708/43708), done.
|
||||||
|
Updating files: 100% (2561/2561), done.
|
||||||
|
|
||||||
# Then download all the branches from the game. (there might be more branches)
|
# Change to the directory that contains your local copy.
|
||||||
$ git fetch danielyxie
|
$ cd bitburner
|
||||||
From github.com:danielyxie/bitburner
|
|
||||||
* [new branch] dev -> danielyxie/dev
|
|
||||||
* [new branch] master -> danielyxie/master
|
|
||||||
|
|
||||||
# Makes sure you always start from `danielyxie/dev` to avoid merge conflicts.
|
# The upstream is the repository that contains the game's source code. The
|
||||||
|
# upstream is also the place where proposed changes are merged into the game.
|
||||||
|
$ git remote rename origin upstream
|
||||||
|
Renaming remote references: 100% (8/8), done.
|
||||||
|
|
||||||
|
# The origin is your own copy or fork of the game's source code. Assume that
|
||||||
|
# your fork will be on GitHub. Change "myname" to your GitHub username. Change
|
||||||
|
# "myfork" to the name of your forked repository.
|
||||||
|
$ git remote add origin https://github.com/myname/myfork
|
||||||
|
|
||||||
|
# Now "origin" is your fork and "upstream" is where changes should be merged.
|
||||||
|
$ git remote show
|
||||||
|
origin
|
||||||
|
upstream
|
||||||
|
|
||||||
|
# You can now download all changes and branches from the upstream repository.
|
||||||
|
# The output you get might vary.
|
||||||
|
$ git fetch upstream
|
||||||
|
|
||||||
|
# Make sure you always start from "upstream/dev" to avoid merge conflicts.
|
||||||
|
$ git branch
|
||||||
|
* dev
|
||||||
|
$ git branch -r
|
||||||
|
upstream/BN14
|
||||||
|
upstream/HEAD -> upstream/dev
|
||||||
|
upstream/dev
|
||||||
|
upstream/folders
|
||||||
|
upstream/master
|
||||||
```
|
```
|
||||||
|
|
||||||
## Development Workflow Best Practices
|
## Development Workflow Best Practices
|
||||||
|
|
||||||
- Work in a new branch forked from the `dev` branch to isolate your new code
|
- Work in a new branch forked from the `dev` branch to isolate your new code.
|
||||||
- Keep code-changes on a branch as small as possible. This makes it easier for code review. Each branch should be its own independent feature.
|
- Keep code-changes on a branch as small as possible. This makes it easier for code review. Each branch should be its own independent feature.
|
||||||
- Regularly rebase your branch against `dev` to make sure you have the latest updates pulled.
|
- Regularly rebase your branch against `dev` to make sure you have the latest updates pulled.
|
||||||
- When merging, always merge your branch into `dev`. When releasing a new update, then merge `dev` into `master`
|
- When merging, always merge your branch into `dev`. When releasing a new update, merge `dev` into `master`.
|
||||||
|
|
||||||
## Running locally.
|
## Running locally
|
||||||
|
|
||||||
Install
|
Install
|
||||||
|
|
||||||
- `npm` (maybe via `nvm`)
|
- `npm` (maybe via `nvm`)
|
||||||
- Github Desktop (windows only)
|
- Github Desktop (Windows only)
|
||||||
- Visual Studio code (optional)
|
- Visual Studio Code (optional)
|
||||||
|
|
||||||
Inside the root of the repo run
|
Inside the root of the repository run:
|
||||||
`npm install` to install all the dependencies
|
|
||||||
`npm run start:dev` to launch the game in dev mode.
|
- `npm install` to install all the dependencies; and
|
||||||
|
- `npm run start:dev` to launch the game in dev mode.
|
||||||
|
|
||||||
After that you can open any browser and navigate to `localhost:8000` and play the game.
|
After that you can open any browser and navigate to `localhost:8000` and play the game.
|
||||||
Saving a file will reload the game automatically.
|
Saving a file will reload the game automatically.
|
||||||
|
|
||||||
### How to build the electron app
|
### How to build the electron app
|
||||||
|
|
||||||
Tested on Node v16.13.1 (LTS) on Windows
|
Tested on Node v16.13.1 (LTS) on Windows.
|
||||||
These steps only work in a bash-like environment, like MinGW for Windows.
|
These steps only work in a Bash-like environment, like MinGW for Windows.
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
# Install the main game dependencies & build the app in debug mode
|
# Install the main game dependencies & build the app in debug mode.
|
||||||
npm install
|
$ npm install
|
||||||
npm run build:dev
|
$ npm run build:dev
|
||||||
|
|
||||||
# Use electron-packager to build the app to the .build/ folder
|
# Use electron-packager to build the app to the .build/ folder.
|
||||||
npm run electron
|
$ npm run electron
|
||||||
|
|
||||||
# When launching the .exe directly, you'll need the steam_appid.txt file in the root
|
# When launching the .exe directly, you'll need the steam_appid.txt file in the root.
|
||||||
# If not using windows, change this line accordingly
|
# If not using Windows, change this line accordingly.
|
||||||
cp .build/bitburner-win32-x64/resources/app/steam_appid.txt .build/bitburner-win32-x64/steam_appid.txt
|
$ cp .build/bitburner-win32-x64/resources/app/steam_appid.txt .build/bitburner-win32-x64/steam_appid.txt
|
||||||
|
|
||||||
# And run the game...
|
# And run the game...
|
||||||
.build/bitburner-win32-x64/bitburner.exe
|
$ .build/bitburner-win32-x64/bitburner.exe
|
||||||
```
|
```
|
||||||
|
|
||||||
### Submitting a Pull Request
|
### Submitting a Pull Request
|
||||||
@ -156,15 +198,15 @@ cp .build/bitburner-win32-x64/resources/app/steam_appid.txt .build/bitburner-win
|
|||||||
When submitting a pull request with your code contributions, please abide by
|
When submitting a pull request with your code contributions, please abide by
|
||||||
the following rules:
|
the following rules:
|
||||||
|
|
||||||
- Work in a branch forked from `dev` to isolate the new code
|
- Work in a branch forked from `dev` to isolate the new code.
|
||||||
- Ensure you have latest from the [game's main
|
- Ensure you have the latest from the [game's main
|
||||||
repository](danielyxie/bitburner@dev)
|
repository](../../../tree/dev).
|
||||||
- Rebase your branch if necessary
|
- Rebase your branch if necessary.
|
||||||
- Run the game locally to test out your changes
|
- Run the game locally to test out your changes.
|
||||||
- When submitting the pull request, make sure that the base fork is
|
- When submitting the pull request, make sure that the base fork is
|
||||||
_danielyxie/bitburner_ and the base is _dev_.
|
_danielyxie/bitburner_ and the base is _dev_.
|
||||||
- If your changes affect the game's UI, attach some screenshots or GIFs showing
|
- If your changes affect the game's UI, attach some screenshots or GIFs showing
|
||||||
the changes to the UI
|
the changes to the UI.
|
||||||
- If your changes affect Netscript, provide some
|
- If your changes affect Netscript, provide some
|
||||||
scripts that can be used to test the Netscript changes.
|
scripts that can be used to test the Netscript changes.
|
||||||
- Ensure you have run `npm run lint` to make sure your changes conform to the
|
- Ensure you have run `npm run lint` to make sure your changes conform to the
|
||||||
@ -174,23 +216,23 @@ the following rules:
|
|||||||
in the root of the repository. These will be updated as part of official
|
in the root of the repository. These will be updated as part of official
|
||||||
releases.
|
releases.
|
||||||
|
|
||||||
## As a Documentor
|
## As a Documenter
|
||||||
|
|
||||||
To contribute to and view your changes to the BitBurner documentation on [Read The
|
To contribute to and view your changes to the BitBurner documentation on [Read The
|
||||||
Docs](http://bitburner.readthedocs.io/), you will
|
Docs](http://bitburner.readthedocs.io/), you will
|
||||||
need to have Python installed, along with [Sphinx](http://www.sphinx-doc.org).
|
need to have Python installed, along with [Sphinx](http://www.sphinx-doc.org).
|
||||||
|
|
||||||
To make change to the [in-game documentation](../markdown/bitburner.md), you will need to modify the [TypeScript definitions](../src/ScriptEditor/NetscriptDefinitions.d.ts), not the markdown files.
|
To make change to the [in-game documentation](../markdown/bitburner.md), you will need to modify the [TypeScript definitions](../src/ScriptEditor/NetscriptDefinitions.d.ts), not the Markdown files.
|
||||||
|
|
||||||
We are using [API Extractor](https://api-extractor.com/pages/tsdoc/doc_comment_syntax/) (tsdoc hints) to generate the markdown doc. Make your changes to the TypeScript definitions and then run `npm run doc`.
|
We are using [API Extractor](https://api-extractor.com/pages/tsdoc/doc_comment_syntax/) (tsdoc hints) to generate the Markdown doc. Make your changes to the TypeScript definitions and then run `npm run doc`.
|
||||||
|
|
||||||
Before submitting your code for a pull request, please try to follow these
|
Before submitting your code for a pull request, please try to follow these
|
||||||
rules:
|
rules:
|
||||||
|
|
||||||
- Work in a branch forked from `dev` to isolate the new code
|
- Work in a branch forked from `dev` to isolate the new code.
|
||||||
- Ensure you have latest from the [game's main
|
- Ensure you have the latest from the [game's main
|
||||||
repository](danielyxie/bitburner@dev)
|
repository](../../../tree/dev).
|
||||||
- Rebase your branch if necessary
|
- Rebase your branch if necessary.
|
||||||
- When submitting the pull request, make sure that the base fork is
|
- When submitting the pull request, make sure that the base fork is
|
||||||
_danielyxie/bitburner_ and the base is _dev_.
|
_danielyxie/bitburner_ and the base is _dev_.
|
||||||
- Do not check in any generated files under `doc\`. The documentation is built
|
- Do not check in any generated files under `doc\`. The documentation is built
|
||||||
@ -204,5 +246,5 @@ Update the following
|
|||||||
- `package.json` `version`
|
- `package.json` `version`
|
||||||
- `doc/source/conf.py` `version` and `release`
|
- `doc/source/conf.py` `version` and `release`
|
||||||
- `doc/source/changelog.rst`
|
- `doc/source/changelog.rst`
|
||||||
- post to discord
|
- post to Discord
|
||||||
- post to reddit.com/r/Bitburner
|
- post to reddit.com/r/Bitburner
|
||||||
|
@ -347,18 +347,18 @@ export const achievements: IMap<Achievement> = {
|
|||||||
FIRST_HACKNET_NODE: {
|
FIRST_HACKNET_NODE: {
|
||||||
...achievementData["FIRST_HACKNET_NODE"],
|
...achievementData["FIRST_HACKNET_NODE"],
|
||||||
Icon: "node",
|
Icon: "node",
|
||||||
Condition: () => !hasHacknetServers(Player) && Player.hacknetNodes.length > 0,
|
Condition: () => !hasHacknetServers() && Player.hacknetNodes.length > 0,
|
||||||
},
|
},
|
||||||
"30_HACKNET_NODE": {
|
"30_HACKNET_NODE": {
|
||||||
...achievementData["30_HACKNET_NODE"],
|
...achievementData["30_HACKNET_NODE"],
|
||||||
Icon: "hacknet-all",
|
Icon: "hacknet-all",
|
||||||
Condition: () => !hasHacknetServers(Player) && Player.hacknetNodes.length >= 30,
|
Condition: () => !hasHacknetServers() && Player.hacknetNodes.length >= 30,
|
||||||
},
|
},
|
||||||
MAX_HACKNET_NODE: {
|
MAX_HACKNET_NODE: {
|
||||||
...achievementData["MAX_HACKNET_NODE"],
|
...achievementData["MAX_HACKNET_NODE"],
|
||||||
Icon: "hacknet-max",
|
Icon: "hacknet-max",
|
||||||
Condition: (): boolean => {
|
Condition: (): boolean => {
|
||||||
if (hasHacknetServers(Player)) return false;
|
if (hasHacknetServers()) return false;
|
||||||
for (const h of Player.hacknetNodes) {
|
for (const h of Player.hacknetNodes) {
|
||||||
if (!(h instanceof HacknetNode)) return false;
|
if (!(h instanceof HacknetNode)) return false;
|
||||||
if (
|
if (
|
||||||
@ -374,7 +374,7 @@ export const achievements: IMap<Achievement> = {
|
|||||||
HACKNET_NODE_10M: {
|
HACKNET_NODE_10M: {
|
||||||
...achievementData["HACKNET_NODE_10M"],
|
...achievementData["HACKNET_NODE_10M"],
|
||||||
Icon: "hacknet-10m",
|
Icon: "hacknet-10m",
|
||||||
Condition: () => !hasHacknetServers(Player) && Player.moneySourceB.hacknet >= 10e6,
|
Condition: () => !hasHacknetServers() && Player.moneySourceB.hacknet >= 10e6,
|
||||||
},
|
},
|
||||||
REPUTATION_10M: {
|
REPUTATION_10M: {
|
||||||
...achievementData["REPUTATION_10M"],
|
...achievementData["REPUTATION_10M"],
|
||||||
@ -515,14 +515,14 @@ export const achievements: IMap<Achievement> = {
|
|||||||
...achievementData["FIRST_HACKNET_SERVER"],
|
...achievementData["FIRST_HACKNET_SERVER"],
|
||||||
Icon: "HASHNET",
|
Icon: "HASHNET",
|
||||||
Visible: () => hasAccessToSF(Player, 9),
|
Visible: () => hasAccessToSF(Player, 9),
|
||||||
Condition: () => hasHacknetServers(Player) && Player.hacknetNodes.length > 0,
|
Condition: () => hasHacknetServers() && Player.hacknetNodes.length > 0,
|
||||||
AdditionalUnlock: [achievementData.FIRST_HACKNET_NODE.ID],
|
AdditionalUnlock: [achievementData.FIRST_HACKNET_NODE.ID],
|
||||||
},
|
},
|
||||||
ALL_HACKNET_SERVER: {
|
ALL_HACKNET_SERVER: {
|
||||||
...achievementData["ALL_HACKNET_SERVER"],
|
...achievementData["ALL_HACKNET_SERVER"],
|
||||||
Icon: "HASHNETALL",
|
Icon: "HASHNETALL",
|
||||||
Visible: () => hasAccessToSF(Player, 9),
|
Visible: () => hasAccessToSF(Player, 9),
|
||||||
Condition: () => hasHacknetServers(Player) && Player.hacknetNodes.length === HacknetServerConstants.MaxServers,
|
Condition: () => hasHacknetServers() && Player.hacknetNodes.length === HacknetServerConstants.MaxServers,
|
||||||
AdditionalUnlock: [achievementData["30_HACKNET_NODE"].ID],
|
AdditionalUnlock: [achievementData["30_HACKNET_NODE"].ID],
|
||||||
},
|
},
|
||||||
MAX_HACKNET_SERVER: {
|
MAX_HACKNET_SERVER: {
|
||||||
@ -530,7 +530,7 @@ export const achievements: IMap<Achievement> = {
|
|||||||
Icon: "HASHNETALL",
|
Icon: "HASHNETALL",
|
||||||
Visible: () => hasAccessToSF(Player, 9),
|
Visible: () => hasAccessToSF(Player, 9),
|
||||||
Condition: (): boolean => {
|
Condition: (): boolean => {
|
||||||
if (!hasHacknetServers(Player)) return false;
|
if (!hasHacknetServers()) return false;
|
||||||
for (const h of Player.hacknetNodes) {
|
for (const h of Player.hacknetNodes) {
|
||||||
if (typeof h !== "string") return false;
|
if (typeof h !== "string") return false;
|
||||||
const hs = GetServer(h);
|
const hs = GetServer(h);
|
||||||
@ -551,7 +551,7 @@ export const achievements: IMap<Achievement> = {
|
|||||||
...achievementData["HACKNET_SERVER_1B"],
|
...achievementData["HACKNET_SERVER_1B"],
|
||||||
Icon: "HASHNETMONEY",
|
Icon: "HASHNETMONEY",
|
||||||
Visible: () => hasAccessToSF(Player, 9),
|
Visible: () => hasAccessToSF(Player, 9),
|
||||||
Condition: () => hasHacknetServers(Player) && Player.moneySourceB.hacknet >= 1e9,
|
Condition: () => hasHacknetServers() && Player.moneySourceB.hacknet >= 1e9,
|
||||||
AdditionalUnlock: [achievementData.HACKNET_NODE_10M.ID],
|
AdditionalUnlock: [achievementData.HACKNET_NODE_10M.ID],
|
||||||
},
|
},
|
||||||
MAX_CACHE: {
|
MAX_CACHE: {
|
||||||
@ -559,7 +559,7 @@ export const achievements: IMap<Achievement> = {
|
|||||||
Icon: "HASHNETCAP",
|
Icon: "HASHNETCAP",
|
||||||
Visible: () => hasAccessToSF(Player, 9),
|
Visible: () => hasAccessToSF(Player, 9),
|
||||||
Condition: () =>
|
Condition: () =>
|
||||||
hasHacknetServers(Player) &&
|
hasHacknetServers() &&
|
||||||
Player.hashManager.hashes === Player.hashManager.capacity &&
|
Player.hashManager.hashes === Player.hashManager.capacity &&
|
||||||
Player.hashManager.capacity > 0,
|
Player.hashManager.capacity > 0,
|
||||||
},
|
},
|
||||||
|
@ -2,7 +2,7 @@ import React, { useState } from "react";
|
|||||||
import { BBCabinetRoot } from "./BBCabinet";
|
import { BBCabinetRoot } from "./BBCabinet";
|
||||||
|
|
||||||
import Button from "@mui/material/Button";
|
import Button from "@mui/material/Button";
|
||||||
import { use } from "../../ui/Context";
|
import { Player } from "../../Player";
|
||||||
import { AlertEvents } from "../../ui/React/AlertManager";
|
import { AlertEvents } from "../../ui/React/AlertManager";
|
||||||
|
|
||||||
enum Page {
|
enum Page {
|
||||||
@ -11,11 +11,10 @@ enum Page {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function ArcadeRoot(): React.ReactElement {
|
export function ArcadeRoot(): React.ReactElement {
|
||||||
const player = use.Player();
|
|
||||||
const [page, setPage] = useState(Page.None);
|
const [page, setPage] = useState(Page.None);
|
||||||
|
|
||||||
function mbBurner2000(): void {
|
function mbBurner2000(): void {
|
||||||
if (player.sourceFileLvl(1) === 0) {
|
if (Player.sourceFileLvl(1) === 0) {
|
||||||
AlertEvents.emit("This machine is broken.");
|
AlertEvents.emit("This machine is broken.");
|
||||||
} else {
|
} else {
|
||||||
setPage(Page.Megabyteburner2000);
|
setPage(Page.Megabyteburner2000);
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import React, { useEffect } from "react";
|
import React, { useEffect } from "react";
|
||||||
import Typography from "@mui/material/Typography";
|
import Typography from "@mui/material/Typography";
|
||||||
import { use } from "../../ui/Context";
|
import { Player } from "../../Player";
|
||||||
import { Exploit } from "../../Exploits/Exploit";
|
import { Exploit } from "../../Exploits/Exploit";
|
||||||
|
|
||||||
const metaBB = "https://bitburner-official.github.io/bitburner-legacy/";
|
const metaBB = "https://bitburner-official.github.io/bitburner-legacy/";
|
||||||
@ -12,11 +12,10 @@ const style = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export function BBCabinetRoot(): React.ReactElement {
|
export function BBCabinetRoot(): React.ReactElement {
|
||||||
const player = use.Player();
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
window.addEventListener("message", function (this: Window, ev: MessageEvent<boolean>) {
|
window.addEventListener("message", function (this: Window, ev: MessageEvent<boolean>) {
|
||||||
if (ev.isTrusted && ev.origin == "https://bitburner-official.github.io" && ev.data) {
|
if (ev.isTrusted && ev.origin == "https://bitburner-official.github.io" && ev.data) {
|
||||||
player.giveExploit(Exploit.TrueRecursion);
|
Player.giveExploit(Exploit.TrueRecursion);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -8,7 +8,7 @@ import { Money } from "../ui/React/Money";
|
|||||||
|
|
||||||
import { Generic_fromJSON, Generic_toJSON, IReviverValue, Reviver } from "../utils/JSONReviver";
|
import { Generic_fromJSON, Generic_toJSON, IReviverValue, Reviver } from "../utils/JSONReviver";
|
||||||
import { FactionNames } from "../Faction/data/FactionNames";
|
import { FactionNames } from "../Faction/data/FactionNames";
|
||||||
import { IPlayer } from "../PersonObjects/IPlayer";
|
import { Player } from "../Player";
|
||||||
import { AugmentationNames } from "./data/AugmentationNames";
|
import { AugmentationNames } from "./data/AugmentationNames";
|
||||||
import { CONSTANTS } from "../Constants";
|
import { CONSTANTS } from "../Constants";
|
||||||
import { StaticAugmentations } from "./StaticAugmentations";
|
import { StaticAugmentations } from "./StaticAugmentations";
|
||||||
@ -531,26 +531,26 @@ export class Augmentation {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
getCost(player: IPlayer): AugmentationCosts {
|
getCost(): AugmentationCosts {
|
||||||
const augmentationReference = StaticAugmentations[this.name];
|
const augmentationReference = StaticAugmentations[this.name];
|
||||||
let moneyCost = augmentationReference.baseCost;
|
let moneyCost = augmentationReference.baseCost;
|
||||||
let repCost = augmentationReference.baseRepRequirement;
|
let repCost = augmentationReference.baseRepRequirement;
|
||||||
|
|
||||||
if (augmentationReference.name === AugmentationNames.NeuroFluxGovernor) {
|
if (augmentationReference.name === AugmentationNames.NeuroFluxGovernor) {
|
||||||
let nextLevel = this.getLevel(player);
|
let nextLevel = this.getLevel();
|
||||||
--nextLevel;
|
--nextLevel;
|
||||||
const multiplier = Math.pow(CONSTANTS.NeuroFluxGovernorLevelMult, nextLevel);
|
const multiplier = Math.pow(CONSTANTS.NeuroFluxGovernorLevelMult, nextLevel);
|
||||||
repCost = augmentationReference.baseRepRequirement * multiplier * BitNodeMultipliers.AugmentationRepCost;
|
repCost = augmentationReference.baseRepRequirement * multiplier * BitNodeMultipliers.AugmentationRepCost;
|
||||||
moneyCost = augmentationReference.baseCost * multiplier * BitNodeMultipliers.AugmentationMoneyCost;
|
moneyCost = augmentationReference.baseCost * multiplier * BitNodeMultipliers.AugmentationMoneyCost;
|
||||||
|
|
||||||
for (let i = 0; i < player.queuedAugmentations.length; ++i) {
|
for (let i = 0; i < Player.queuedAugmentations.length; ++i) {
|
||||||
moneyCost *= getBaseAugmentationPriceMultiplier();
|
moneyCost *= getBaseAugmentationPriceMultiplier();
|
||||||
}
|
}
|
||||||
} else if (augmentationReference.factions.includes(FactionNames.ShadowsOfAnarchy)) {
|
} else if (augmentationReference.factions.includes(FactionNames.ShadowsOfAnarchy)) {
|
||||||
const soaAugmentationNames = initSoAAugmentations().map((augmentation) => augmentation.name);
|
const soaAugmentationNames = initSoAAugmentations().map((augmentation) => augmentation.name);
|
||||||
const soaMultiplier = Math.pow(
|
const soaMultiplier = Math.pow(
|
||||||
CONSTANTS.SoACostMult,
|
CONSTANTS.SoACostMult,
|
||||||
soaAugmentationNames.filter((augmentationName) => player.hasAugmentation(augmentationName)).length,
|
soaAugmentationNames.filter((augmentationName) => Player.hasAugmentation(augmentationName)).length,
|
||||||
);
|
);
|
||||||
moneyCost = augmentationReference.baseCost * soaMultiplier;
|
moneyCost = augmentationReference.baseCost * soaMultiplier;
|
||||||
if (soaAugmentationNames.find((augmentationName) => augmentationName === augmentationReference.name)) {
|
if (soaAugmentationNames.find((augmentationName) => augmentationName === augmentationReference.name)) {
|
||||||
@ -566,19 +566,19 @@ export class Augmentation {
|
|||||||
return { moneyCost, repCost };
|
return { moneyCost, repCost };
|
||||||
}
|
}
|
||||||
|
|
||||||
getLevel(player: IPlayer): number {
|
getLevel(): number {
|
||||||
// Get current Neuroflux level based on Player's augmentations
|
// Get current Neuroflux level based on Player's augmentations
|
||||||
if (this.name === AugmentationNames.NeuroFluxGovernor) {
|
if (this.name === AugmentationNames.NeuroFluxGovernor) {
|
||||||
let currLevel = 0;
|
let currLevel = 0;
|
||||||
for (let i = 0; i < player.augmentations.length; ++i) {
|
for (let i = 0; i < Player.augmentations.length; ++i) {
|
||||||
if (player.augmentations[i].name === AugmentationNames.NeuroFluxGovernor) {
|
if (Player.augmentations[i].name === AugmentationNames.NeuroFluxGovernor) {
|
||||||
currLevel = player.augmentations[i].level;
|
currLevel = Player.augmentations[i].level;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Account for purchased but uninstalled Augmentations
|
// Account for purchased but uninstalled Augmentations
|
||||||
for (let i = 0; i < player.queuedAugmentations.length; ++i) {
|
for (let i = 0; i < Player.queuedAugmentations.length; ++i) {
|
||||||
if (player.queuedAugmentations[i].name == AugmentationNames.NeuroFluxGovernor) {
|
if (Player.queuedAugmentations[i].name == AugmentationNames.NeuroFluxGovernor) {
|
||||||
++currLevel;
|
++currLevel;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { Augmentation } from "./Augmentation";
|
import { Augmentation } from "./Augmentation";
|
||||||
import { StaticAugmentations } from "./StaticAugmentations";
|
import { StaticAugmentations } from "./StaticAugmentations";
|
||||||
import { PlayerOwnedAugmentation, IPlayerOwnedAugmentation } from "./PlayerOwnedAugmentation";
|
import { PlayerOwnedAugmentation } from "./PlayerOwnedAugmentation";
|
||||||
import { AugmentationNames } from "./data/AugmentationNames";
|
import { AugmentationNames } from "./data/AugmentationNames";
|
||||||
|
|
||||||
import { CONSTANTS } from "../Constants";
|
import { CONSTANTS } from "../Constants";
|
||||||
@ -21,7 +21,7 @@ import {
|
|||||||
initUnstableCircadianModulator,
|
initUnstableCircadianModulator,
|
||||||
} from "./data/AugmentationCreator";
|
} from "./data/AugmentationCreator";
|
||||||
import { Router } from "../ui/GameRoot";
|
import { Router } from "../ui/GameRoot";
|
||||||
import { mergeAugmentation } from "../PersonObjects/Multipliers";
|
import { mergeMultipliers } from "../PersonObjects/Multipliers";
|
||||||
|
|
||||||
export function AddToStaticAugmentations(aug: Augmentation): void {
|
export function AddToStaticAugmentations(aug: Augmentation): void {
|
||||||
const name = aug.name;
|
const name = aug.name;
|
||||||
@ -71,11 +71,11 @@ function resetAugmentation(aug: Augmentation): void {
|
|||||||
AddToStaticAugmentations(aug);
|
AddToStaticAugmentations(aug);
|
||||||
}
|
}
|
||||||
|
|
||||||
function applyAugmentation(aug: IPlayerOwnedAugmentation, reapply = false): void {
|
function applyAugmentation(aug: PlayerOwnedAugmentation, reapply = false): void {
|
||||||
const staticAugmentation = StaticAugmentations[aug.name];
|
const staticAugmentation = StaticAugmentations[aug.name];
|
||||||
|
|
||||||
// Apply multipliers
|
// Apply multipliers
|
||||||
Player.mults = mergeAugmentation(Player.mults, staticAugmentation.mults);
|
Player.mults = mergeMultipliers(Player.mults, staticAugmentation.mults);
|
||||||
|
|
||||||
// Special logic for Congruity Implant
|
// Special logic for Congruity Implant
|
||||||
if (aug.name === AugmentationNames.CongruityImplant && !reapply) {
|
if (aug.name === AugmentationNames.CongruityImplant && !reapply) {
|
||||||
@ -126,15 +126,15 @@ function installAugmentations(force?: boolean): boolean {
|
|||||||
if (ownedAug.name === AugmentationNames.NeuroFluxGovernor) {
|
if (ownedAug.name === AugmentationNames.NeuroFluxGovernor) {
|
||||||
level = ` - ${ownedAug.level}`;
|
level = ` - ${ownedAug.level}`;
|
||||||
}
|
}
|
||||||
augmentationList += aug.name + level + "<br>";
|
augmentationList += aug.name + level + "\n";
|
||||||
}
|
}
|
||||||
Player.queuedAugmentations = [];
|
Player.queuedAugmentations = [];
|
||||||
if (!force) {
|
if (!force) {
|
||||||
dialogBoxCreate(
|
dialogBoxCreate(
|
||||||
"You slowly drift to sleep as scientists put you under in order " +
|
"You slowly drift to sleep as scientists put you under in order " +
|
||||||
"to install the following Augmentations:<br>" +
|
"to install the following Augmentations:\n" +
|
||||||
augmentationList +
|
augmentationList +
|
||||||
"<br>You wake up in your home...you feel different...",
|
"\nYou wake up in your home...you feel different...",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
prestigeAugmentation();
|
prestigeAugmentation();
|
||||||
@ -146,8 +146,8 @@ function augmentationExists(name: string): boolean {
|
|||||||
return StaticAugmentations.hasOwnProperty(name);
|
return StaticAugmentations.hasOwnProperty(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isRepeatableAug(aug: Augmentation): boolean {
|
export function isRepeatableAug(aug: Augmentation | string): boolean {
|
||||||
const augName = aug instanceof Augmentation ? aug.name : aug;
|
const augName = typeof aug === "string" ? aug : aug.name;
|
||||||
return augName === AugmentationNames.NeuroFluxGovernor;
|
return augName === AugmentationNames.NeuroFluxGovernor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,8 +6,3 @@ export class PlayerOwnedAugmentation {
|
|||||||
this.name = name;
|
this.name = name;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IPlayerOwnedAugmentation {
|
|
||||||
level: number;
|
|
||||||
name: string;
|
|
||||||
}
|
|
||||||
|
@ -6,7 +6,6 @@ import { WHRNG } from "../../Casino/RNG";
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import { FactionNames } from "../../Faction/data/FactionNames";
|
import { FactionNames } from "../../Faction/data/FactionNames";
|
||||||
import { CONSTANTS } from "../../Constants";
|
import { CONSTANTS } from "../../Constants";
|
||||||
import { Faction } from "src/Faction/Faction";
|
|
||||||
|
|
||||||
interface CircadianBonus {
|
interface CircadianBonus {
|
||||||
bonuses: {
|
bonuses: {
|
||||||
|
@ -10,8 +10,6 @@ import { PurchasedAugmentations } from "./PurchasedAugmentations";
|
|||||||
import { SourceFilesElement } from "./SourceFiles";
|
import { SourceFilesElement } from "./SourceFiles";
|
||||||
|
|
||||||
import { canGetBonus } from "../../ExportBonus";
|
import { canGetBonus } from "../../ExportBonus";
|
||||||
import { use } from "../../ui/Context";
|
|
||||||
|
|
||||||
import Typography from "@mui/material/Typography";
|
import Typography from "@mui/material/Typography";
|
||||||
import Button from "@mui/material/Button";
|
import Button from "@mui/material/Button";
|
||||||
import Tooltip from "@mui/material/Tooltip";
|
import Tooltip from "@mui/material/Tooltip";
|
||||||
@ -20,7 +18,7 @@ import Paper from "@mui/material/Paper";
|
|||||||
import Container from "@mui/material/Container";
|
import Container from "@mui/material/Container";
|
||||||
import { Settings } from "../../Settings/Settings";
|
import { Settings } from "../../Settings/Settings";
|
||||||
import { ConfirmationModal } from "../../ui/React/ConfirmationModal";
|
import { ConfirmationModal } from "../../ui/React/ConfirmationModal";
|
||||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
import { Player } from "../../Player";
|
||||||
import { AugmentationNames } from "../data/AugmentationNames";
|
import { AugmentationNames } from "../data/AugmentationNames";
|
||||||
import { StaticAugmentations } from "../StaticAugmentations";
|
import { StaticAugmentations } from "../StaticAugmentations";
|
||||||
import { CONSTANTS } from "../../Constants";
|
import { CONSTANTS } from "../../Constants";
|
||||||
@ -29,12 +27,8 @@ import { Info } from "@mui/icons-material";
|
|||||||
import { Link } from "@mui/material";
|
import { Link } from "@mui/material";
|
||||||
import { AlertEvents } from "../../ui/React/AlertManager";
|
import { AlertEvents } from "../../ui/React/AlertManager";
|
||||||
|
|
||||||
interface NFGDisplayProps {
|
const NeuroFluxDisplay = (): React.ReactElement => {
|
||||||
player: IPlayer;
|
const level = Player.augmentations.find((e) => e.name === AugmentationNames.NeuroFluxGovernor)?.level ?? 0;
|
||||||
}
|
|
||||||
|
|
||||||
const NeuroFluxDisplay = ({ player }: NFGDisplayProps): React.ReactElement => {
|
|
||||||
const level = player.augmentations.find((e) => e.name === AugmentationNames.NeuroFluxGovernor)?.level ?? 0;
|
|
||||||
|
|
||||||
const openBloodDonation = () => {
|
const openBloodDonation = () => {
|
||||||
AlertEvents.emit(
|
AlertEvents.emit(
|
||||||
@ -67,18 +61,14 @@ const NeuroFluxDisplay = ({ player }: NFGDisplayProps): React.ReactElement => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
interface EntropyDisplayProps {
|
const EntropyDisplay = (): React.ReactElement => {
|
||||||
player: IPlayer;
|
return Player.entropy > 0 ? (
|
||||||
}
|
|
||||||
|
|
||||||
const EntropyDisplay = ({ player }: EntropyDisplayProps): React.ReactElement => {
|
|
||||||
return player.entropy > 0 ? (
|
|
||||||
<Paper sx={{ p: 1 }}>
|
<Paper sx={{ p: 1 }}>
|
||||||
<Typography variant="h5" color={Settings.theme.error}>
|
<Typography variant="h5" color={Settings.theme.error}>
|
||||||
Entropy Virus - Level {player.entropy}
|
Entropy Virus - Level {Player.entropy}
|
||||||
</Typography>
|
</Typography>
|
||||||
<Typography color={Settings.theme.error}>
|
<Typography color={Settings.theme.error}>
|
||||||
<b>All multipliers decreased by:</b> {formatNumber((1 - CONSTANTS.EntropyEffect ** player.entropy) * 100, 3)}%
|
<b>All multipliers decreased by:</b> {formatNumber((1 - CONSTANTS.EntropyEffect ** Player.entropy) * 100, 3)}%
|
||||||
(multiplicative)
|
(multiplicative)
|
||||||
</Typography>
|
</Typography>
|
||||||
</Paper>
|
</Paper>
|
||||||
@ -94,7 +84,6 @@ interface IProps {
|
|||||||
|
|
||||||
export function AugmentationsRoot(props: IProps): React.ReactElement {
|
export function AugmentationsRoot(props: IProps): React.ReactElement {
|
||||||
const [installOpen, setInstallOpen] = useState(false);
|
const [installOpen, setInstallOpen] = useState(false);
|
||||||
const player = use.Player();
|
|
||||||
const setRerender = useState(false)[1];
|
const setRerender = useState(false)[1];
|
||||||
function rerender(): void {
|
function rerender(): void {
|
||||||
setRerender((o) => !o);
|
setRerender((o) => !o);
|
||||||
@ -187,7 +176,7 @@ export function AugmentationsRoot(props: IProps): React.ReactElement {
|
|||||||
<Box sx={{ display: "grid", width: "100%", gridTemplateColumns: "1fr 1fr" }}>
|
<Box sx={{ display: "grid", width: "100%", gridTemplateColumns: "1fr 1fr" }}>
|
||||||
<Tooltip title={<Typography>'I never asked for this'</Typography>}>
|
<Tooltip title={<Typography>'I never asked for this'</Typography>}>
|
||||||
<span>
|
<span>
|
||||||
<Button sx={{ width: "100%" }} disabled={player.queuedAugmentations.length === 0} onClick={doInstall}>
|
<Button sx={{ width: "100%" }} disabled={Player.queuedAugmentations.length === 0} onClick={doInstall}>
|
||||||
Install Augmentations
|
Install Augmentations
|
||||||
</Button>
|
</Button>
|
||||||
</span>
|
</span>
|
||||||
@ -199,7 +188,7 @@ export function AugmentationsRoot(props: IProps): React.ReactElement {
|
|||||||
</Tooltip>
|
</Tooltip>
|
||||||
</Box>
|
</Box>
|
||||||
</Paper>
|
</Paper>
|
||||||
{player.queuedAugmentations.length > 0 ? (
|
{Player.queuedAugmentations.length > 0 ? (
|
||||||
<Box sx={{ display: "grid", gridTemplateColumns: "1fr 3fr" }}>
|
<Box sx={{ display: "grid", gridTemplateColumns: "1fr 3fr" }}>
|
||||||
<PurchasedAugmentations />
|
<PurchasedAugmentations />
|
||||||
<PlayerMultipliers />
|
<PlayerMultipliers />
|
||||||
@ -216,14 +205,14 @@ export function AugmentationsRoot(props: IProps): React.ReactElement {
|
|||||||
my: 1,
|
my: 1,
|
||||||
display: "grid",
|
display: "grid",
|
||||||
gridTemplateColumns: `repeat(${
|
gridTemplateColumns: `repeat(${
|
||||||
+!!((player.augmentations.find((e) => e.name === AugmentationNames.NeuroFluxGovernor)?.level ?? 0) > 0) +
|
+!!((Player.augmentations.find((e) => e.name === AugmentationNames.NeuroFluxGovernor)?.level ?? 0) > 0) +
|
||||||
+!!(player.entropy > 0)
|
+!!(Player.entropy > 0)
|
||||||
}, 1fr)`,
|
}, 1fr)`,
|
||||||
gap: 1,
|
gap: 1,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<NeuroFluxDisplay player={player} />
|
<NeuroFluxDisplay />
|
||||||
<EntropyDisplay player={player} />
|
<EntropyDisplay />
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
<Box>
|
<Box>
|
||||||
|
@ -12,14 +12,13 @@ import Tooltip from "@mui/material/Tooltip";
|
|||||||
import React, { useState } from "react";
|
import React, { useState } from "react";
|
||||||
import { OwnedAugmentationsOrderSetting } from "../../Settings/SettingEnums";
|
import { OwnedAugmentationsOrderSetting } from "../../Settings/SettingEnums";
|
||||||
import { Settings } from "../../Settings/Settings";
|
import { Settings } from "../../Settings/Settings";
|
||||||
import { use } from "../../ui/Context";
|
import { Player } from "../../Player";
|
||||||
import { StaticAugmentations } from "../StaticAugmentations";
|
import { StaticAugmentations } from "../StaticAugmentations";
|
||||||
import { AugmentationNames } from "../data/AugmentationNames";
|
import { AugmentationNames } from "../data/AugmentationNames";
|
||||||
|
|
||||||
export function InstalledAugmentations(): React.ReactElement {
|
export function InstalledAugmentations(): React.ReactElement {
|
||||||
const setRerender = useState(true)[1];
|
const setRerender = useState(true)[1];
|
||||||
const player = use.Player();
|
const sourceAugs = Player.augmentations.slice().filter((aug) => aug.name !== AugmentationNames.NeuroFluxGovernor);
|
||||||
const sourceAugs = player.augmentations.slice().filter((aug) => aug.name !== AugmentationNames.NeuroFluxGovernor);
|
|
||||||
|
|
||||||
const [selectedAug, setSelectedAug] = useState(sourceAugs[0]);
|
const [selectedAug, setSelectedAug] = useState(sourceAugs[0]);
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
import { DoubleArrow } from "@mui/icons-material";
|
import { DoubleArrow } from "@mui/icons-material";
|
||||||
import { List, ListItem, ListItemText, Paper, Typography } from "@mui/material";
|
import { List, ListItem, ListItemText, Paper, Typography } from "@mui/material";
|
||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import { Multipliers, defaultMultipliers, mergeAugmentation } from "../../PersonObjects/Multipliers";
|
import { Multipliers, defaultMultipliers, mergeMultipliers } from "../../PersonObjects/Multipliers";
|
||||||
import { BitNodeMultipliers } from "../../BitNode/BitNodeMultipliers";
|
import { BitNodeMultipliers } from "../../BitNode/BitNodeMultipliers";
|
||||||
import { Player } from "../../Player";
|
import { Player } from "../../Player";
|
||||||
import { Settings } from "../../Settings/Settings";
|
import { Settings } from "../../Settings/Settings";
|
||||||
@ -15,7 +15,7 @@ function calculateAugmentedStats(): Multipliers {
|
|||||||
let augP: Multipliers = defaultMultipliers();
|
let augP: Multipliers = defaultMultipliers();
|
||||||
for (const aug of Player.queuedAugmentations) {
|
for (const aug of Player.queuedAugmentations) {
|
||||||
const augObj = StaticAugmentations[aug.name];
|
const augObj = StaticAugmentations[aug.name];
|
||||||
augP = mergeAugmentation(augP, augObj.mults);
|
augP = mergeMultipliers(augP, augObj.mults);
|
||||||
}
|
}
|
||||||
return augP;
|
return augP;
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,7 @@ import { CheckBox, CheckBoxOutlineBlank, CheckCircle, NewReleases, Report } from
|
|||||||
import { Box, Button, Container, Paper, Tooltip, Typography } from "@mui/material";
|
import { Box, Button, Container, Paper, Tooltip, Typography } from "@mui/material";
|
||||||
import React, { useState } from "react";
|
import React, { useState } from "react";
|
||||||
import { Faction } from "../../Faction/Faction";
|
import { Faction } from "../../Faction/Faction";
|
||||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
import { Player } from "../../Player";
|
||||||
import { Settings } from "../../Settings/Settings";
|
import { Settings } from "../../Settings/Settings";
|
||||||
import { numeralWrapper } from "../../ui/numeralFormat";
|
import { numeralWrapper } from "../../ui/numeralFormat";
|
||||||
import { Augmentation } from "../Augmentation";
|
import { Augmentation } from "../Augmentation";
|
||||||
@ -15,12 +15,11 @@ import { StaticAugmentations } from "../StaticAugmentations";
|
|||||||
import { PurchaseAugmentationModal } from "./PurchaseAugmentationModal";
|
import { PurchaseAugmentationModal } from "./PurchaseAugmentationModal";
|
||||||
|
|
||||||
interface IPreReqsProps {
|
interface IPreReqsProps {
|
||||||
player: IPlayer;
|
|
||||||
aug: Augmentation;
|
aug: Augmentation;
|
||||||
}
|
}
|
||||||
|
|
||||||
const PreReqs = (props: IPreReqsProps): React.ReactElement => {
|
const PreReqs = (props: IPreReqsProps): React.ReactElement => {
|
||||||
const ownedPreReqs = props.aug.prereqs.filter((aug) => props.player.hasAugmentation(aug));
|
const ownedPreReqs = props.aug.prereqs.filter((aug) => Player.hasAugmentation(aug));
|
||||||
const hasPreReqs = props.aug.prereqs.length > 0 && ownedPreReqs.length === props.aug.prereqs.length;
|
const hasPreReqs = props.aug.prereqs.length > 0 && ownedPreReqs.length === props.aug.prereqs.length;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -32,7 +31,7 @@ const PreReqs = (props: IPreReqsProps): React.ReactElement => {
|
|||||||
</Typography>
|
</Typography>
|
||||||
{props.aug.prereqs.map((preAug) => (
|
{props.aug.prereqs.map((preAug) => (
|
||||||
<Requirement
|
<Requirement
|
||||||
fulfilled={props.player.hasAugmentation(preAug)}
|
fulfilled={Player.hasAugmentation(preAug)}
|
||||||
value={preAug}
|
value={preAug}
|
||||||
color={Settings.theme.money}
|
color={Settings.theme.money}
|
||||||
key={preAug}
|
key={preAug}
|
||||||
@ -68,7 +67,6 @@ const PreReqs = (props: IPreReqsProps): React.ReactElement => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
interface IExclusiveProps {
|
interface IExclusiveProps {
|
||||||
player: IPlayer;
|
|
||||||
aug: Augmentation;
|
aug: Augmentation;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -85,18 +83,16 @@ const Exclusive = (props: IExclusiveProps): React.ReactElement => {
|
|||||||
<li>
|
<li>
|
||||||
<b>{props.aug.factions[0]}</b> faction
|
<b>{props.aug.factions[0]}</b> faction
|
||||||
</li>
|
</li>
|
||||||
{props.player.isAwareOfGang() && !props.aug.isSpecial && (
|
{Player.isAwareOfGang() && !props.aug.isSpecial && (
|
||||||
<li>
|
<li>
|
||||||
Certain <b>gangs</b>
|
Certain <b>gangs</b>
|
||||||
</li>
|
</li>
|
||||||
)}
|
)}
|
||||||
{props.player.canAccessGrafting() &&
|
{Player.canAccessGrafting() && !props.aug.isSpecial && props.aug.name !== AugmentationNames.TheRedPill && (
|
||||||
!props.aug.isSpecial &&
|
<li>
|
||||||
props.aug.name !== AugmentationNames.TheRedPill && (
|
<b>Grafting</b>
|
||||||
<li>
|
</li>
|
||||||
<b>Grafting</b>
|
)}
|
||||||
</li>
|
|
||||||
)}
|
|
||||||
</Typography>
|
</Typography>
|
||||||
</ul>
|
</ul>
|
||||||
</>
|
</>
|
||||||
@ -130,10 +126,9 @@ const Requirement = (props: IReqProps): React.ReactElement => {
|
|||||||
interface IPurchasableAugsProps {
|
interface IPurchasableAugsProps {
|
||||||
augNames: string[];
|
augNames: string[];
|
||||||
ownedAugNames: string[];
|
ownedAugNames: string[];
|
||||||
player: IPlayer;
|
|
||||||
|
|
||||||
canPurchase: (player: IPlayer, aug: Augmentation) => boolean;
|
canPurchase: (aug: Augmentation) => boolean;
|
||||||
purchaseAugmentation: (player: IPlayer, aug: Augmentation, showModal: (open: boolean) => void) => void;
|
purchaseAugmentation: (aug: Augmentation, showModal: (open: boolean) => void) => void;
|
||||||
|
|
||||||
rep?: number;
|
rep?: number;
|
||||||
sleeveAugs?: boolean;
|
sleeveAugs?: boolean;
|
||||||
@ -167,7 +162,7 @@ export function PurchasableAugmentation(props: IPurchasableAugProps): React.Reac
|
|||||||
const [open, setOpen] = useState(false);
|
const [open, setOpen] = useState(false);
|
||||||
|
|
||||||
const aug = StaticAugmentations[props.augName];
|
const aug = StaticAugmentations[props.augName];
|
||||||
const augCosts = aug.getCost(props.parent.player);
|
const augCosts = aug.getCost();
|
||||||
const cost = props.parent.sleeveAugs ? aug.baseCost : augCosts.moneyCost;
|
const cost = props.parent.sleeveAugs ? aug.baseCost : augCosts.moneyCost;
|
||||||
const repCost = augCosts.repCost;
|
const repCost = augCosts.repCost;
|
||||||
const info = typeof aug.info === "string" ? <span>{aug.info}</span> : aug.info;
|
const info = typeof aug.info === "string" ? <span>{aug.info}</span> : aug.info;
|
||||||
@ -195,11 +190,11 @@ export function PurchasableAugmentation(props: IPurchasableAugProps): React.Reac
|
|||||||
<Box sx={{ display: "flex", alignItems: "center" }}>
|
<Box sx={{ display: "flex", alignItems: "center" }}>
|
||||||
<Button
|
<Button
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
props.parent.purchaseAugmentation(props.parent.player, aug, (open): void => {
|
props.parent.purchaseAugmentation(aug, (open): void => {
|
||||||
setOpen(open);
|
setOpen(open);
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
disabled={!props.parent.canPurchase(props.parent.player, aug) || props.owned}
|
disabled={!props.parent.canPurchase(aug) || props.owned}
|
||||||
sx={{ width: "48px", height: "36px", float: "left", clear: "none", mr: 1 }}
|
sx={{ width: "48px", height: "36px", float: "left", clear: "none", mr: 1 }}
|
||||||
>
|
>
|
||||||
{props.owned ? "Owned" : "Buy"}
|
{props.owned ? "Owned" : "Buy"}
|
||||||
@ -212,8 +207,7 @@ export function PurchasableAugmentation(props: IPurchasableAugProps): React.Reac
|
|||||||
<>
|
<>
|
||||||
<Typography variant="h5">
|
<Typography variant="h5">
|
||||||
{props.augName}
|
{props.augName}
|
||||||
{props.augName === AugmentationNames.NeuroFluxGovernor &&
|
{props.augName === AugmentationNames.NeuroFluxGovernor && ` - Level ${aug.getLevel()}`}
|
||||||
` - Level ${aug.getLevel(props.parent.player)}`}
|
|
||||||
</Typography>
|
</Typography>
|
||||||
<Typography>{description}</Typography>
|
<Typography>{description}</Typography>
|
||||||
</>
|
</>
|
||||||
@ -226,20 +220,16 @@ export function PurchasableAugmentation(props: IPurchasableAugProps): React.Reac
|
|||||||
whiteSpace: "nowrap",
|
whiteSpace: "nowrap",
|
||||||
overflow: "hidden",
|
overflow: "hidden",
|
||||||
color:
|
color:
|
||||||
props.owned || !props.parent.canPurchase(props.parent.player, aug)
|
props.owned || !props.parent.canPurchase(aug) ? Settings.theme.disabled : Settings.theme.primary,
|
||||||
? Settings.theme.disabled
|
|
||||||
: Settings.theme.primary,
|
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{aug.name}
|
{aug.name}
|
||||||
{aug.name === AugmentationNames.NeuroFluxGovernor && ` - Level ${aug.getLevel(props.parent.player)}`}
|
{aug.name === AugmentationNames.NeuroFluxGovernor && ` - Level ${aug.getLevel()}`}
|
||||||
</Typography>
|
</Typography>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
|
|
||||||
{aug.factions.length === 1 && !props.parent.sleeveAugs && (
|
{aug.factions.length === 1 && !props.parent.sleeveAugs && <Exclusive aug={aug} />}
|
||||||
<Exclusive player={props.parent.player} aug={aug} />
|
{aug.prereqs.length > 0 && !props.parent.sleeveAugs && <PreReqs aug={aug} />}
|
||||||
)}
|
|
||||||
{aug.prereqs.length > 0 && !props.parent.sleeveAugs && <PreReqs player={props.parent.player} aug={aug} />}
|
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
@ -247,7 +237,7 @@ export function PurchasableAugmentation(props: IPurchasableAugProps): React.Reac
|
|||||||
{props.owned || (
|
{props.owned || (
|
||||||
<Box sx={{ display: "grid", alignItems: "center", gridTemplateColumns: "1fr 1fr" }}>
|
<Box sx={{ display: "grid", alignItems: "center", gridTemplateColumns: "1fr 1fr" }}>
|
||||||
<Requirement
|
<Requirement
|
||||||
fulfilled={cost === 0 || props.parent.player.money > cost}
|
fulfilled={cost === 0 || Player.money > cost}
|
||||||
value={numeralWrapper.formatMoney(cost)}
|
value={numeralWrapper.formatMoney(cost)}
|
||||||
color={Settings.theme.money}
|
color={Settings.theme.money}
|
||||||
/>
|
/>
|
||||||
|
@ -6,7 +6,7 @@ import { purchaseAugmentation } from "../../Faction/FactionHelpers";
|
|||||||
import { isRepeatableAug } from "../AugmentationHelpers";
|
import { isRepeatableAug } from "../AugmentationHelpers";
|
||||||
import { Money } from "../../ui/React/Money";
|
import { Money } from "../../ui/React/Money";
|
||||||
import { Modal } from "../../ui/React/Modal";
|
import { Modal } from "../../ui/React/Modal";
|
||||||
import { use } from "../../ui/Context";
|
import { Player } from "../../Player";
|
||||||
import Typography from "@mui/material/Typography";
|
import Typography from "@mui/material/Typography";
|
||||||
import Button from "@mui/material/Button";
|
import Button from "@mui/material/Button";
|
||||||
|
|
||||||
@ -18,14 +18,12 @@ interface IProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function PurchaseAugmentationModal(props: IProps): React.ReactElement {
|
export function PurchaseAugmentationModal(props: IProps): React.ReactElement {
|
||||||
if (typeof props.aug === "undefined" || typeof props.faction === "undefined") {
|
if (!props.aug || !props.faction) {
|
||||||
return <></>;
|
return <></>;
|
||||||
}
|
}
|
||||||
|
|
||||||
const player = use.Player();
|
|
||||||
|
|
||||||
function buy(): void {
|
function buy(): void {
|
||||||
if (!isRepeatableAug(props.aug as Augmentation) && player.hasAugmentation(props.aug as Augmentation)) {
|
if (!props.aug || (!isRepeatableAug(props.aug) && Player.hasAugmentation(props.aug.name))) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -44,7 +42,7 @@ export function PurchaseAugmentationModal(props: IProps): React.ReactElement {
|
|||||||
<br />
|
<br />
|
||||||
<br />
|
<br />
|
||||||
Would you like to purchase the {props.aug.name} Augmentation for
|
Would you like to purchase the {props.aug.name} Augmentation for
|
||||||
<Money money={props.aug.getCost(player).moneyCost} />?
|
<Money money={props.aug.getCost().moneyCost} />?
|
||||||
<br />
|
<br />
|
||||||
<br />
|
<br />
|
||||||
</Typography>
|
</Typography>
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import { BitNodeMultipliers, IBitNodeMultipliers } from "./BitNodeMultipliers";
|
import { BitNodeMultipliers, IBitNodeMultipliers } from "./BitNodeMultipliers";
|
||||||
import { IPlayer } from "../PersonObjects/IPlayer";
|
import { Player } from "../Player";
|
||||||
import { IMap } from "../types";
|
import { IMap } from "../types";
|
||||||
import { FactionNames } from "../Faction/data/FactionNames";
|
import { FactionNames } from "../Faction/data/FactionNames";
|
||||||
import { CityName } from "../Locations/data/CityNames";
|
import { CityName } from "../Locations/data/CityNames";
|
||||||
@ -876,6 +876,6 @@ export function getBitNodeMultipliers(n: number, lvl: number): IBitNodeMultiplie
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function initBitNodeMultipliers(p: IPlayer): void {
|
export function initBitNodeMultipliers(): void {
|
||||||
Object.assign(BitNodeMultipliers, getBitNodeMultipliers(p.bitNodeN, p.sourceFileLvl(p.bitNodeN)));
|
Object.assign(BitNodeMultipliers, getBitNodeMultipliers(Player.bitNodeN, Player.sourceFileLvl(Player.bitNodeN)));
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import React, { useState, useEffect } from "react";
|
import React, { useState, useEffect } from "react";
|
||||||
import { Modal } from "../../ui/React/Modal";
|
import { Modal } from "../../ui/React/Modal";
|
||||||
import { use } from "../../ui/Context";
|
import { Router } from "../../ui/GameRoot";
|
||||||
import { EventEmitter } from "../../utils/EventEmitter";
|
import { EventEmitter } from "../../utils/EventEmitter";
|
||||||
import Typography from "@mui/material/Typography";
|
import Typography from "@mui/material/Typography";
|
||||||
import Button from "@mui/material/Button";
|
import Button from "@mui/material/Button";
|
||||||
@ -8,10 +8,9 @@ import Button from "@mui/material/Button";
|
|||||||
export const BitFlumeEvent = new EventEmitter<[]>();
|
export const BitFlumeEvent = new EventEmitter<[]>();
|
||||||
|
|
||||||
export function BitFlumeModal(): React.ReactElement {
|
export function BitFlumeModal(): React.ReactElement {
|
||||||
const router = use.Router();
|
|
||||||
const [open, setOpen] = useState(false);
|
const [open, setOpen] = useState(false);
|
||||||
function flume(): void {
|
function flume(): void {
|
||||||
router.toBitVerse(true, false);
|
Router.toBitVerse(true, false);
|
||||||
setOpen(false);
|
setOpen(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@ import { uniqueId } from "lodash";
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import { SpecialServers } from "../../Server/data/SpecialServers";
|
import { SpecialServers } from "../../Server/data/SpecialServers";
|
||||||
import { Settings } from "../../Settings/Settings";
|
import { Settings } from "../../Settings/Settings";
|
||||||
import { use } from "../../ui/Context";
|
import { Player } from "../../Player";
|
||||||
import { StatsRow } from "../../ui/React/StatsRow";
|
import { StatsRow } from "../../ui/React/StatsRow";
|
||||||
import { defaultMultipliers, getBitNodeMultipliers } from "../BitNode";
|
import { defaultMultipliers, getBitNodeMultipliers } from "../BitNode";
|
||||||
import { IBitNodeMultipliers } from "../BitNodeMultipliers";
|
import { IBitNodeMultipliers } from "../BitNodeMultipliers";
|
||||||
@ -33,13 +33,12 @@ export function BitnodeMultiplierDescription({ n, level }: IProps): React.ReactE
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const BitNodeMultipliersDisplay = ({ n, level }: IProps): React.ReactElement => {
|
export const BitNodeMultipliersDisplay = ({ n, level }: IProps): React.ReactElement => {
|
||||||
const player = use.Player();
|
|
||||||
// If a level argument has been provided, use that as the multiplier level
|
// If a level argument has been provided, use that as the multiplier level
|
||||||
// If not, then we have to assume that we want the next level up from the
|
// If not, then we have to assume that we want the next level up from the
|
||||||
// current node's source file, so we get the min of that, the SF's max level,
|
// current node's source file, so we get the min of that, the SF's max level,
|
||||||
// or if it's BN12, ∞
|
// or if it's BN12, ∞
|
||||||
const maxSfLevel = n === 12 ? Infinity : 3;
|
const maxSfLevel = n === 12 ? Infinity : 3;
|
||||||
const mults = getBitNodeMultipliers(n, level ?? Math.min(player.sourceFileLvl(n) + 1, maxSfLevel));
|
const mults = getBitNodeMultipliers(n, level ?? Math.min(Player.sourceFileLvl(n) + 1, maxSfLevel));
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box sx={{ columnCount: 2, columnGap: 1, mb: -2 }}>
|
<Box sx={{ columnCount: 2, columnGap: 1, mb: -2 }}>
|
||||||
@ -277,8 +276,7 @@ function InfiltrationMults({ mults }: IMultsProps): React.ReactElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function BladeburnerMults({ mults }: IMultsProps): React.ReactElement {
|
function BladeburnerMults({ mults }: IMultsProps): React.ReactElement {
|
||||||
const player = use.Player();
|
if (!Player.canAccessBladeburner()) return <></>;
|
||||||
if (!player.canAccessBladeburner()) return <></>;
|
|
||||||
|
|
||||||
if (mults.BladeburnerRank === 0) {
|
if (mults.BladeburnerRank === 0) {
|
||||||
const rows: IBNMultRows = {
|
const rows: IBNMultRows = {
|
||||||
@ -297,8 +295,7 @@ function BladeburnerMults({ mults }: IMultsProps): React.ReactElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function StanekMults({ mults }: IMultsProps): React.ReactElement {
|
function StanekMults({ mults }: IMultsProps): React.ReactElement {
|
||||||
const player = use.Player();
|
if (!Player.canAccessCotMG()) return <></>;
|
||||||
if (!player.canAccessCotMG()) return <></>;
|
|
||||||
|
|
||||||
const extraSize = mults.StaneksGiftExtraSize.toFixed(3);
|
const extraSize = mults.StaneksGiftExtraSize.toFixed(3);
|
||||||
const rows: IBNMultRows = {
|
const rows: IBNMultRows = {
|
||||||
@ -313,8 +310,7 @@ function StanekMults({ mults }: IMultsProps): React.ReactElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function GangMults({ mults }: IMultsProps): React.ReactElement {
|
function GangMults({ mults }: IMultsProps): React.ReactElement {
|
||||||
const player = use.Player();
|
if (Player.bitNodeN !== 2 && Player.sourceFileLvl(2) <= 0) return <></>;
|
||||||
if (player.bitNodeN !== 2 && player.sourceFileLvl(2) <= 0) return <></>;
|
|
||||||
|
|
||||||
const rows: IBNMultRows = {
|
const rows: IBNMultRows = {
|
||||||
GangSoftcap: {
|
GangSoftcap: {
|
||||||
@ -328,8 +324,7 @@ function GangMults({ mults }: IMultsProps): React.ReactElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function CorporationMults({ mults }: IMultsProps): React.ReactElement {
|
function CorporationMults({ mults }: IMultsProps): React.ReactElement {
|
||||||
const player = use.Player();
|
if (!Player.canAccessCorporation()) return <></>;
|
||||||
if (!player.canAccessCorporation()) return <></>;
|
|
||||||
|
|
||||||
if (mults.CorporationSoftcap < 0.15) {
|
if (mults.CorporationSoftcap < 0.15) {
|
||||||
const rows: IBNMultRows = {
|
const rows: IBNMultRows = {
|
||||||
|
@ -1,10 +1,8 @@
|
|||||||
import React, { useState } from "react";
|
import React, { useState } from "react";
|
||||||
import { IRouter } from "../../ui/Router";
|
|
||||||
import { BitNodes } from "../BitNode";
|
import { BitNodes } from "../BitNode";
|
||||||
import { enterBitNode } from "../../RedPill";
|
|
||||||
import { PortalModal } from "./PortalModal";
|
import { PortalModal } from "./PortalModal";
|
||||||
import { CinematicText } from "../../ui/React/CinematicText";
|
import { CinematicText } from "../../ui/React/CinematicText";
|
||||||
import { use } from "../../ui/Context";
|
import { Player } from "../../Player";
|
||||||
import makeStyles from "@mui/styles/makeStyles";
|
import makeStyles from "@mui/styles/makeStyles";
|
||||||
import createStyles from "@mui/styles/createStyles";
|
import createStyles from "@mui/styles/createStyles";
|
||||||
import IconButton from "@mui/material/IconButton";
|
import IconButton from "@mui/material/IconButton";
|
||||||
@ -46,7 +44,6 @@ interface IPortalProps {
|
|||||||
level: number;
|
level: number;
|
||||||
destroyedBitNode: number;
|
destroyedBitNode: number;
|
||||||
flume: boolean;
|
flume: boolean;
|
||||||
enter: (router: IRouter, flume: boolean, destroyedBitNode: number, newBitNode: number) => void;
|
|
||||||
}
|
}
|
||||||
function BitNodePortal(props: IPortalProps): React.ReactElement {
|
function BitNodePortal(props: IPortalProps): React.ReactElement {
|
||||||
const [portalOpen, setPortalOpen] = useState(false);
|
const [portalOpen, setPortalOpen] = useState(false);
|
||||||
@ -105,7 +102,6 @@ function BitNodePortal(props: IPortalProps): React.ReactElement {
|
|||||||
onClose={() => setPortalOpen(false)}
|
onClose={() => setPortalOpen(false)}
|
||||||
n={props.n}
|
n={props.n}
|
||||||
level={props.level}
|
level={props.level}
|
||||||
enter={props.enter}
|
|
||||||
destroyedBitNode={props.destroyedBitNode}
|
destroyedBitNode={props.destroyedBitNode}
|
||||||
flume={props.flume}
|
flume={props.flume}
|
||||||
/>
|
/>
|
||||||
@ -118,13 +114,10 @@ function BitNodePortal(props: IPortalProps): React.ReactElement {
|
|||||||
interface IProps {
|
interface IProps {
|
||||||
flume: boolean;
|
flume: boolean;
|
||||||
quick: boolean;
|
quick: boolean;
|
||||||
enter: (router: IRouter, flume: boolean, destroyedBitNode: number, newBitNode: number) => void;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function BitverseRoot(props: IProps): React.ReactElement {
|
export function BitverseRoot(props: IProps): React.ReactElement {
|
||||||
const player = use.Player();
|
const destroyed = Player.bitNodeN;
|
||||||
const enter = enterBitNode;
|
|
||||||
const destroyed = player.bitNodeN;
|
|
||||||
const [destroySequence, setDestroySequence] = useState(!props.quick);
|
const [destroySequence, setDestroySequence] = useState(!props.quick);
|
||||||
|
|
||||||
if (destroySequence) {
|
if (destroySequence) {
|
||||||
@ -158,7 +151,7 @@ export function BitverseRoot(props: IProps): React.ReactElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const nextSourceFileLvl = (n: number): number => {
|
const nextSourceFileLvl = (n: number): number => {
|
||||||
const lvl = player.sourceFileLvl(n);
|
const lvl = Player.sourceFileLvl(n);
|
||||||
if (n !== destroyed) {
|
if (n !== destroyed) {
|
||||||
return lvl;
|
return lvl;
|
||||||
}
|
}
|
||||||
@ -181,7 +174,6 @@ export function BitverseRoot(props: IProps): React.ReactElement {
|
|||||||
key={node.number}
|
key={node.number}
|
||||||
n={node.number}
|
n={node.number}
|
||||||
level={nextSourceFileLvl(node.number)}
|
level={nextSourceFileLvl(node.number)}
|
||||||
enter={enter}
|
|
||||||
flume={props.flume}
|
flume={props.flume}
|
||||||
destroyedBitNode={destroyed}
|
destroyedBitNode={destroyed}
|
||||||
/>
|
/>
|
||||||
@ -234,19 +226,19 @@ export function BitverseRoot(props: IProps): React.ReactElement {
|
|||||||
<Typography sx={{lineHeight: '1em',whiteSpace: 'pre'}}>O | | | \| | O / _/ | / O | |/ | | | O</Typography>
|
<Typography sx={{lineHeight: '1em',whiteSpace: 'pre'}}>O | | | \| | O / _/ | / O | |/ | | | O</Typography>
|
||||||
<Typography sx={{lineHeight: '1em',whiteSpace: 'pre'}}>| | | |O / | | O / | O O | | \ O| | | |</Typography>
|
<Typography sx={{lineHeight: '1em',whiteSpace: 'pre'}}>| | | |O / | | O / | O O | | \ O| | | |</Typography>
|
||||||
<Typography sx={{lineHeight: '1em',whiteSpace: 'pre'}}>| | |/ \/ / __| | |/ \ | \ | |__ \ \/ \| | |</Typography>
|
<Typography sx={{lineHeight: '1em',whiteSpace: 'pre'}}>| | |/ \/ / __| | |/ \ | \ | |__ \ \/ \| | |</Typography>
|
||||||
<Typography sx={{lineHeight: '1em',whiteSpace: 'pre'}}> \| O | |_/ |\| \ <BitNodePortal n={13} level={n(13)} enter={enter} flume={props.flume} destroyedBitNode={destroyed} /> \__| \_| | O |/ </Typography>
|
<Typography sx={{lineHeight: '1em',whiteSpace: 'pre'}}> \| O | |_/ |\| \ <BitNodePortal n={13} level={n(13)} flume={props.flume} destroyedBitNode={destroyed} /> \__| \_| | O |/ </Typography>
|
||||||
<Typography sx={{lineHeight: '1em',whiteSpace: 'pre'}}> | | |_/ | | \| / | \_| | | </Typography>
|
<Typography sx={{lineHeight: '1em',whiteSpace: 'pre'}}> | | |_/ | | \| / | \_| | | </Typography>
|
||||||
<Typography sx={{lineHeight: '1em',whiteSpace: 'pre'}}> \| / \| | / / \ |/ </Typography>
|
<Typography sx={{lineHeight: '1em',whiteSpace: 'pre'}}> \| / \| | / / \ |/ </Typography>
|
||||||
<Typography sx={{lineHeight: '1em',whiteSpace: 'pre'}}> | <BitNodePortal n={10} level={n(10)} enter={enter} flume={props.flume} destroyedBitNode={destroyed} /> | | / | <BitNodePortal n={11} level={n(11)} enter={enter} flume={props.flume} destroyedBitNode={destroyed} /> | </Typography>
|
<Typography sx={{lineHeight: '1em',whiteSpace: 'pre'}}> | <BitNodePortal n={10} level={n(10)} flume={props.flume} destroyedBitNode={destroyed} /> | | / | <BitNodePortal n={11} level={n(11)} flume={props.flume} destroyedBitNode={destroyed} /> | </Typography>
|
||||||
<Typography sx={{lineHeight: '1em',whiteSpace: 'pre'}}> <BitNodePortal n={9} level={n(9)} enter={enter} flume={props.flume} destroyedBitNode={destroyed} /> | | | | | | | <BitNodePortal n={12} level={n(12)} enter={enter} flume={props.flume} destroyedBitNode={destroyed} /> </Typography>
|
<Typography sx={{lineHeight: '1em',whiteSpace: 'pre'}}> <BitNodePortal n={9} level={n(9)} flume={props.flume} destroyedBitNode={destroyed} /> | | | | | | | <BitNodePortal n={12} level={n(12)} flume={props.flume} destroyedBitNode={destroyed} /> </Typography>
|
||||||
<Typography sx={{lineHeight: '1em',whiteSpace: 'pre'}}> | | | / / \ \ | | | </Typography>
|
<Typography sx={{lineHeight: '1em',whiteSpace: 'pre'}}> | | | / / \ \ | | | </Typography>
|
||||||
<Typography sx={{lineHeight: '1em',whiteSpace: 'pre'}}> \| | / <BitNodePortal n={7} level={n(7)} enter={enter} flume={props.flume} destroyedBitNode={destroyed} /> / \ <BitNodePortal n={8} level={n(8)} enter={enter} flume={props.flume} destroyedBitNode={destroyed} /> \ | |/ </Typography>
|
<Typography sx={{lineHeight: '1em',whiteSpace: 'pre'}}> \| | / <BitNodePortal n={7} level={n(7)} flume={props.flume} destroyedBitNode={destroyed} /> / \ <BitNodePortal n={8} level={n(8)} flume={props.flume} destroyedBitNode={destroyed} /> \ | |/ </Typography>
|
||||||
<Typography sx={{lineHeight: '1em',whiteSpace: 'pre'}}> \ | / / | | \ \ | / </Typography>
|
<Typography sx={{lineHeight: '1em',whiteSpace: 'pre'}}> \ | / / | | \ \ | / </Typography>
|
||||||
<Typography sx={{lineHeight: '1em',whiteSpace: 'pre'}}> \ \JUMP <BitNodePortal n={5} level={n(5)} enter={enter} flume={props.flume} destroyedBitNode={destroyed} />3R | | | | | | R3<BitNodePortal n={6} level={n(6)} enter={enter} flume={props.flume} destroyedBitNode={destroyed} /> PMUJ/ / </Typography>
|
<Typography sx={{lineHeight: '1em',whiteSpace: 'pre'}}> \ \JUMP <BitNodePortal n={5} level={n(5)} flume={props.flume} destroyedBitNode={destroyed} />3R | | | | | | R3<BitNodePortal n={6} level={n(6)} flume={props.flume} destroyedBitNode={destroyed} /> PMUJ/ / </Typography>
|
||||||
<Typography sx={{lineHeight: '1em',whiteSpace: 'pre'}}> \|| | | | | | | | | ||/ </Typography>
|
<Typography sx={{lineHeight: '1em',whiteSpace: 'pre'}}> \|| | | | | | | | | ||/ </Typography>
|
||||||
<Typography sx={{lineHeight: '1em',whiteSpace: 'pre'}}> \| \_ | | | | | | _/ |/ </Typography>
|
<Typography sx={{lineHeight: '1em',whiteSpace: 'pre'}}> \| \_ | | | | | | _/ |/ </Typography>
|
||||||
<Typography sx={{lineHeight: '1em',whiteSpace: 'pre'}}> \ \| / \ / \ |/ / </Typography>
|
<Typography sx={{lineHeight: '1em',whiteSpace: 'pre'}}> \ \| / \ / \ |/ / </Typography>
|
||||||
<Typography sx={{lineHeight: '1em',whiteSpace: 'pre'}}> <BitNodePortal n={1} level={n(1)} enter={enter} flume={props.flume} destroyedBitNode={destroyed} /> |/ <BitNodePortal n={2} level={n(2)} enter={enter} flume={props.flume} destroyedBitNode={destroyed} /> | | <BitNodePortal n={3} level={n(3)} enter={enter} flume={props.flume} destroyedBitNode={destroyed} /> \| <BitNodePortal n={4} level={n(4)} enter={enter} flume={props.flume} destroyedBitNode={destroyed} /> </Typography>
|
<Typography sx={{lineHeight: '1em',whiteSpace: 'pre'}}> <BitNodePortal n={1} level={n(1)} flume={props.flume} destroyedBitNode={destroyed} /> |/ <BitNodePortal n={2} level={n(2)} flume={props.flume} destroyedBitNode={destroyed} /> | | <BitNodePortal n={3} level={n(3)} flume={props.flume} destroyedBitNode={destroyed} /> \| <BitNodePortal n={4} level={n(4)} flume={props.flume} destroyedBitNode={destroyed} /> </Typography>
|
||||||
<Typography sx={{lineHeight: '1em',whiteSpace: 'pre'}}> | | | | | | | | </Typography>
|
<Typography sx={{lineHeight: '1em',whiteSpace: 'pre'}}> | | | | | | | | </Typography>
|
||||||
<Typography sx={{lineHeight: '1em',whiteSpace: 'pre'}}> \JUMP3R|JUMP|3R| |R3|PMUJ|R3PMUJ/ </Typography>
|
<Typography sx={{lineHeight: '1em',whiteSpace: 'pre'}}> \JUMP3R|JUMP|3R| |R3|PMUJ|R3PMUJ/ </Typography>
|
||||||
<br />
|
<br />
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
|
|
||||||
|
import { enterBitNode } from "../../RedPill";
|
||||||
import { BitNodes } from "../BitNode";
|
import { BitNodes } from "../BitNode";
|
||||||
import { IRouter } from "../../ui/Router";
|
|
||||||
import { use } from "../../ui/Context";
|
|
||||||
import { Modal } from "../../ui/React/Modal";
|
import { Modal } from "../../ui/React/Modal";
|
||||||
import Typography from "@mui/material/Typography";
|
import Typography from "@mui/material/Typography";
|
||||||
import Button from "@mui/material/Button";
|
import Button from "@mui/material/Button";
|
||||||
@ -15,11 +14,9 @@ interface IProps {
|
|||||||
level: number;
|
level: number;
|
||||||
destroyedBitNode: number;
|
destroyedBitNode: number;
|
||||||
flume: boolean;
|
flume: boolean;
|
||||||
enter: (router: IRouter, flume: boolean, destroyedBitNode: number, newBitNode: number) => void;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function PortalModal(props: IProps): React.ReactElement {
|
export function PortalModal(props: IProps): React.ReactElement {
|
||||||
const router = use.Router();
|
|
||||||
const bitNodeKey = "BitNode" + props.n;
|
const bitNodeKey = "BitNode" + props.n;
|
||||||
const bitNode = BitNodes[bitNodeKey];
|
const bitNode = BitNodes[bitNodeKey];
|
||||||
if (bitNode == null) throw new Error(`Could not find BitNode object for number: ${props.n}`);
|
if (bitNode == null) throw new Error(`Could not find BitNode object for number: ${props.n}`);
|
||||||
@ -48,7 +45,7 @@ export function PortalModal(props: IProps): React.ReactElement {
|
|||||||
aria-label={`enter-bitnode-${bitNode.number.toString()}`}
|
aria-label={`enter-bitnode-${bitNode.number.toString()}`}
|
||||||
autoFocus={true}
|
autoFocus={true}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
props.enter(router, props.flume, props.destroyedBitNode, props.n);
|
enterBitNode(props.flume, props.destroyedBitNode, props.n);
|
||||||
props.onClose();
|
props.onClose();
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
@ -3,9 +3,12 @@ import { getRandomInt } from "../utils/helpers/getRandomInt";
|
|||||||
import { addOffset } from "../utils/helpers/addOffset";
|
import { addOffset } from "../utils/helpers/addOffset";
|
||||||
import { Generic_fromJSON, Generic_toJSON, IReviverValue, Reviver } from "../utils/JSONReviver";
|
import { Generic_fromJSON, Generic_toJSON, IReviverValue, Reviver } from "../utils/JSONReviver";
|
||||||
import { BladeburnerConstants } from "./data/Constants";
|
import { BladeburnerConstants } from "./data/Constants";
|
||||||
import { IBladeburner } from "./IBladeburner";
|
import { Bladeburner } from "./Bladeburner";
|
||||||
import { IAction, ISuccessChanceParams } from "./IAction";
|
import { Person } from "../PersonObjects/Person";
|
||||||
import { IPerson } from "../PersonObjects/IPerson";
|
|
||||||
|
interface ISuccessChanceParams {
|
||||||
|
est: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
class StatsMultiplier {
|
class StatsMultiplier {
|
||||||
[key: string]: number;
|
[key: string]: number;
|
||||||
@ -41,7 +44,7 @@ export interface IActionParams {
|
|||||||
teamCount?: number;
|
teamCount?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Action implements IAction {
|
export class Action {
|
||||||
name = "";
|
name = "";
|
||||||
|
|
||||||
// Difficulty scales with level. See getDifficulty() method
|
// Difficulty scales with level. See getDifficulty() method
|
||||||
@ -153,7 +156,7 @@ export class Action implements IAction {
|
|||||||
* Tests for success. Should be called when an action has completed
|
* Tests for success. Should be called when an action has completed
|
||||||
* @param inst {Bladeburner} - Bladeburner instance
|
* @param inst {Bladeburner} - Bladeburner instance
|
||||||
*/
|
*/
|
||||||
attempt(inst: IBladeburner, person: IPerson): boolean {
|
attempt(inst: Bladeburner, person: Person): boolean {
|
||||||
return Math.random() < this.getSuccessChance(inst, person);
|
return Math.random() < this.getSuccessChance(inst, person);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -162,7 +165,7 @@ export class Action implements IAction {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
getActionTime(inst: IBladeburner, person: IPerson): number {
|
getActionTime(inst: Bladeburner, person: Person): number {
|
||||||
const difficulty = this.getDifficulty();
|
const difficulty = this.getDifficulty();
|
||||||
let baseTime = difficulty / BladeburnerConstants.DifficultyToTimeFactor;
|
let baseTime = difficulty / BladeburnerConstants.DifficultyToTimeFactor;
|
||||||
const skillFac = inst.skillMultipliers.actionTime; // Always < 1
|
const skillFac = inst.skillMultipliers.actionTime; // Always < 1
|
||||||
@ -183,16 +186,16 @@ export class Action implements IAction {
|
|||||||
|
|
||||||
// For actions that have teams. To be implemented by subtypes.
|
// For actions that have teams. To be implemented by subtypes.
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
getTeamSuccessBonus(inst: IBladeburner): number {
|
getTeamSuccessBonus(inst: Bladeburner): number {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
getActionTypeSkillSuccessBonus(inst: IBladeburner): number {
|
getActionTypeSkillSuccessBonus(inst: Bladeburner): number {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
getChaosCompetencePenalty(inst: IBladeburner, params: ISuccessChanceParams): number {
|
getChaosCompetencePenalty(inst: Bladeburner, params: ISuccessChanceParams): number {
|
||||||
const city = inst.getCurrentCity();
|
const city = inst.getCurrentCity();
|
||||||
if (params.est) {
|
if (params.est) {
|
||||||
return Math.pow(city.popEst / BladeburnerConstants.PopulationThreshold, BladeburnerConstants.PopulationExponent);
|
return Math.pow(city.popEst / BladeburnerConstants.PopulationThreshold, BladeburnerConstants.PopulationExponent);
|
||||||
@ -201,7 +204,7 @@ export class Action implements IAction {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
getChaosDifficultyBonus(inst: IBladeburner /*, params: ISuccessChanceParams*/): number {
|
getChaosDifficultyBonus(inst: Bladeburner /*, params: ISuccessChanceParams*/): number {
|
||||||
const city = inst.getCurrentCity();
|
const city = inst.getCurrentCity();
|
||||||
if (city.chaos > BladeburnerConstants.ChaosThreshold) {
|
if (city.chaos > BladeburnerConstants.ChaosThreshold) {
|
||||||
const diff = 1 + (city.chaos - BladeburnerConstants.ChaosThreshold);
|
const diff = 1 + (city.chaos - BladeburnerConstants.ChaosThreshold);
|
||||||
@ -212,7 +215,7 @@ export class Action implements IAction {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
getEstSuccessChance(inst: IBladeburner, person: IPerson): [number, number] {
|
getEstSuccessChance(inst: Bladeburner, person: Person): [number, number] {
|
||||||
function clamp(x: number): number {
|
function clamp(x: number): number {
|
||||||
return Math.max(0, Math.min(x, 1));
|
return Math.max(0, Math.min(x, 1));
|
||||||
}
|
}
|
||||||
@ -233,7 +236,7 @@ export class Action implements IAction {
|
|||||||
* @params - options:
|
* @params - options:
|
||||||
* est (bool): Get success chance estimate instead of real success chance
|
* est (bool): Get success chance estimate instead of real success chance
|
||||||
*/
|
*/
|
||||||
getSuccessChance(inst: IBladeburner, person: IPerson, params: ISuccessChanceParams = { est: false }): number {
|
getSuccessChance(inst: Bladeburner, person: Person, params: ISuccessChanceParams = { est: false }): number {
|
||||||
if (inst == null) {
|
if (inst == null) {
|
||||||
throw new Error("Invalid Bladeburner instance passed into Action.getSuccessChance");
|
throw new Error("Invalid Bladeburner instance passed into Action.getSuccessChance");
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
import { IActionIdentifier } from "./IActionIdentifier";
|
|
||||||
import { Generic_fromJSON, Generic_toJSON, IReviverValue, Reviver } from "../utils/JSONReviver";
|
import { Generic_fromJSON, Generic_toJSON, IReviverValue, Reviver } from "../utils/JSONReviver";
|
||||||
|
|
||||||
interface IParams {
|
interface IParams {
|
||||||
@ -6,7 +5,7 @@ interface IParams {
|
|||||||
type?: number;
|
type?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class ActionIdentifier implements IActionIdentifier {
|
export class ActionIdentifier {
|
||||||
name = "";
|
name = "";
|
||||||
type = -1;
|
type = -1;
|
||||||
|
|
||||||
|
@ -12,11 +12,11 @@ export class BlackOperation extends Operation {
|
|||||||
return 1.5;
|
return 1.5;
|
||||||
}
|
}
|
||||||
|
|
||||||
getChaosCompetencePenalty(/*inst: IBladeburner, params: ISuccessChanceParams*/): number {
|
getChaosCompetencePenalty(/*inst: Bladeburner, params: ISuccessChanceParams*/): number {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
getChaosDifficultyBonus(/*inst: IBladeburner, params: ISuccessChanceParams*/): number {
|
getChaosDifficultyBonus(/*inst: Bladeburner, params: ISuccessChanceParams*/): number {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,4 @@
|
|||||||
import { Reviver, Generic_toJSON, Generic_fromJSON, IReviverValue } from "../utils/JSONReviver";
|
import { Reviver, Generic_toJSON, Generic_fromJSON, IReviverValue } from "../utils/JSONReviver";
|
||||||
import { IBladeburner } from "./IBladeburner";
|
|
||||||
import { IActionIdentifier } from "./IActionIdentifier";
|
|
||||||
import { ActionIdentifier } from "./ActionIdentifier";
|
import { ActionIdentifier } from "./ActionIdentifier";
|
||||||
import { ActionTypes } from "./data/ActionTypes";
|
import { ActionTypes } from "./data/ActionTypes";
|
||||||
import { Growths } from "./data/Growths";
|
import { Growths } from "./data/Growths";
|
||||||
@ -13,11 +11,11 @@ import { formatNumber } from "../utils/StringHelperFunctions";
|
|||||||
import { Skills } from "./Skills";
|
import { Skills } from "./Skills";
|
||||||
import { Skill } from "./Skill";
|
import { Skill } from "./Skill";
|
||||||
import { City } from "./City";
|
import { City } from "./City";
|
||||||
import { IAction } from "./IAction";
|
import { Action } from "./Action";
|
||||||
import { IPlayer } from "../PersonObjects/IPlayer";
|
import { Player } from "../Player";
|
||||||
import { createTaskTracker, ITaskTracker } from "../PersonObjects/ITaskTracker";
|
import { createTaskTracker, ITaskTracker } from "../PersonObjects/ITaskTracker";
|
||||||
import { IPerson } from "../PersonObjects/IPerson";
|
import { Person } from "../PersonObjects/Person";
|
||||||
import { IRouter } from "../ui/Router";
|
import { Router } from "../ui/GameRoot";
|
||||||
import { ConsoleHelpText } from "./data/Help";
|
import { ConsoleHelpText } from "./data/Help";
|
||||||
import { exceptionAlert } from "../utils/helpers/exceptionAlert";
|
import { exceptionAlert } from "../utils/helpers/exceptionAlert";
|
||||||
import { getRandomInt } from "../utils/helpers/getRandomInt";
|
import { getRandomInt } from "../utils/helpers/getRandomInt";
|
||||||
@ -25,7 +23,6 @@ import { BladeburnerConstants } from "./data/Constants";
|
|||||||
import { numeralWrapper } from "../ui/numeralFormat";
|
import { numeralWrapper } from "../ui/numeralFormat";
|
||||||
import { BitNodeMultipliers } from "../BitNode/BitNodeMultipliers";
|
import { BitNodeMultipliers } from "../BitNode/BitNodeMultipliers";
|
||||||
import { addOffset } from "../utils/helpers/addOffset";
|
import { addOffset } from "../utils/helpers/addOffset";
|
||||||
import { Faction } from "../Faction/Faction";
|
|
||||||
import { Factions, factionExists } from "../Faction/Factions";
|
import { Factions, factionExists } from "../Faction/Factions";
|
||||||
import { calculateHospitalizationCost } from "../Hospital/Hospital";
|
import { calculateHospitalizationCost } from "../Hospital/Hospital";
|
||||||
import { dialogBoxCreate } from "../ui/React/DialogBox";
|
import { dialogBoxCreate } from "../ui/React/DialogBox";
|
||||||
@ -39,13 +36,13 @@ import { KEY } from "../utils/helpers/keyCodes";
|
|||||||
import { isSleeveInfiltrateWork } from "../PersonObjects/Sleeve/Work/SleeveInfiltrateWork";
|
import { isSleeveInfiltrateWork } from "../PersonObjects/Sleeve/Work/SleeveInfiltrateWork";
|
||||||
import { isSleeveSupportWork } from "../PersonObjects/Sleeve/Work/SleeveSupportWork";
|
import { isSleeveSupportWork } from "../PersonObjects/Sleeve/Work/SleeveSupportWork";
|
||||||
|
|
||||||
interface BlackOpsAttempt {
|
export interface BlackOpsAttempt {
|
||||||
error?: string;
|
error?: string;
|
||||||
isAvailable?: boolean;
|
isAvailable?: boolean;
|
||||||
action?: BlackOperation;
|
action?: BlackOperation;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Bladeburner implements IBladeburner {
|
export class Bladeburner {
|
||||||
numHosp = 0;
|
numHosp = 0;
|
||||||
moneyLost = 0;
|
moneyLost = 0;
|
||||||
rank = 0;
|
rank = 0;
|
||||||
@ -67,7 +64,7 @@ export class Bladeburner implements IBladeburner {
|
|||||||
actionTimeCurrent = 0;
|
actionTimeCurrent = 0;
|
||||||
actionTimeOverflow = 0;
|
actionTimeOverflow = 0;
|
||||||
|
|
||||||
action: IActionIdentifier = new ActionIdentifier({
|
action: ActionIdentifier = new ActionIdentifier({
|
||||||
type: ActionTypes["Idle"],
|
type: ActionTypes["Idle"],
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -89,18 +86,18 @@ export class Bladeburner implements IBladeburner {
|
|||||||
events: true,
|
events: true,
|
||||||
};
|
};
|
||||||
automateEnabled = false;
|
automateEnabled = false;
|
||||||
automateActionHigh: IActionIdentifier = new ActionIdentifier({
|
automateActionHigh: ActionIdentifier = new ActionIdentifier({
|
||||||
type: ActionTypes["Idle"],
|
type: ActionTypes["Idle"],
|
||||||
});
|
});
|
||||||
automateThreshHigh = 0;
|
automateThreshHigh = 0;
|
||||||
automateActionLow: IActionIdentifier = new ActionIdentifier({
|
automateActionLow: ActionIdentifier = new ActionIdentifier({
|
||||||
type: ActionTypes["Idle"],
|
type: ActionTypes["Idle"],
|
||||||
});
|
});
|
||||||
automateThreshLow = 0;
|
automateThreshLow = 0;
|
||||||
consoleHistory: string[] = [];
|
consoleHistory: string[] = [];
|
||||||
consoleLogs: string[] = ["Bladeburner Console", "Type 'help' to see console commands"];
|
consoleLogs: string[] = ["Bladeburner Console", "Type 'help' to see console commands"];
|
||||||
|
|
||||||
constructor(player?: IPlayer) {
|
constructor() {
|
||||||
for (let i = 0; i < BladeburnerConstants.CityNames.length; ++i) {
|
for (let i = 0; i < BladeburnerConstants.CityNames.length; ++i) {
|
||||||
this.cities[BladeburnerConstants.CityNames[i]] = new City(BladeburnerConstants.CityNames[i]);
|
this.cities[BladeburnerConstants.CityNames[i]] = new City(BladeburnerConstants.CityNames[i]);
|
||||||
}
|
}
|
||||||
@ -108,16 +105,14 @@ export class Bladeburner implements IBladeburner {
|
|||||||
this.updateSkillMultipliers(); // Calls resetSkillMultipliers()
|
this.updateSkillMultipliers(); // Calls resetSkillMultipliers()
|
||||||
|
|
||||||
// Max Stamina is based on stats and Bladeburner-specific bonuses
|
// Max Stamina is based on stats and Bladeburner-specific bonuses
|
||||||
if (player) this.calculateMaxStamina(player);
|
this.calculateMaxStamina();
|
||||||
this.stamina = this.maxStamina;
|
this.stamina = this.maxStamina;
|
||||||
this.create();
|
this.create();
|
||||||
}
|
}
|
||||||
|
|
||||||
getCurrentCity(): City {
|
getCurrentCity(): City {
|
||||||
const city = this.cities[this.city];
|
const city = this.cities[this.city];
|
||||||
if (!(city instanceof City)) {
|
if (!city) throw new Error("Invalid city in Bladeburner.getCurrentCity()");
|
||||||
throw new Error("Bladeburner.getCurrentCity() did not properly return a City object");
|
|
||||||
}
|
|
||||||
return city;
|
return city;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -125,7 +120,7 @@ export class Bladeburner implements IBladeburner {
|
|||||||
return Math.min(1, this.stamina / (0.5 * this.maxStamina));
|
return Math.min(1, this.stamina / (0.5 * this.maxStamina));
|
||||||
}
|
}
|
||||||
|
|
||||||
canAttemptBlackOp(actionId: IActionIdentifier): BlackOpsAttempt {
|
canAttemptBlackOp(actionId: ActionIdentifier): BlackOpsAttempt {
|
||||||
// Safety measure - don't repeat BlackOps that are already done
|
// Safety measure - don't repeat BlackOps that are already done
|
||||||
if (this.blackops[actionId.name] != null) {
|
if (this.blackops[actionId.name] != null) {
|
||||||
return { error: "Tried to start a Black Operation that had already been completed" };
|
return { error: "Tried to start a Black Operation that had already been completed" };
|
||||||
@ -162,7 +157,8 @@ export class Bladeburner implements IBladeburner {
|
|||||||
return { isAvailable: true, action };
|
return { isAvailable: true, action };
|
||||||
}
|
}
|
||||||
|
|
||||||
startAction(person: IPerson, actionId: IActionIdentifier): void {
|
/** This function is only for the player. Sleeves use their own functions to perform blade work. */
|
||||||
|
startAction(actionId: ActionIdentifier): void {
|
||||||
if (actionId == null) return;
|
if (actionId == null) return;
|
||||||
this.action = actionId;
|
this.action = actionId;
|
||||||
this.actionTimeCurrent = 0;
|
this.actionTimeCurrent = 0;
|
||||||
@ -179,7 +175,7 @@ export class Bladeburner implements IBladeburner {
|
|||||||
if (action.count < 1) {
|
if (action.count < 1) {
|
||||||
return this.resetAction();
|
return this.resetAction();
|
||||||
}
|
}
|
||||||
this.actionTimeToComplete = action.getActionTime(this, person);
|
this.actionTimeToComplete = action.getActionTime(this, Player);
|
||||||
} catch (e: unknown) {
|
} catch (e: unknown) {
|
||||||
exceptionAlert(e);
|
exceptionAlert(e);
|
||||||
}
|
}
|
||||||
@ -196,7 +192,7 @@ export class Bladeburner implements IBladeburner {
|
|||||||
if (actionId.name === "Raid" && this.getCurrentCity().comms === 0) {
|
if (actionId.name === "Raid" && this.getCurrentCity().comms === 0) {
|
||||||
return this.resetAction();
|
return this.resetAction();
|
||||||
}
|
}
|
||||||
this.actionTimeToComplete = action.getActionTime(this, person);
|
this.actionTimeToComplete = action.getActionTime(this, Player);
|
||||||
} catch (e: unknown) {
|
} catch (e: unknown) {
|
||||||
exceptionAlert(e);
|
exceptionAlert(e);
|
||||||
}
|
}
|
||||||
@ -214,14 +210,14 @@ export class Bladeburner implements IBladeburner {
|
|||||||
if (testBlackOp.action === undefined) {
|
if (testBlackOp.action === undefined) {
|
||||||
throw new Error("action should not be null");
|
throw new Error("action should not be null");
|
||||||
}
|
}
|
||||||
this.actionTimeToComplete = testBlackOp.action.getActionTime(this, person);
|
this.actionTimeToComplete = testBlackOp.action.getActionTime(this, Player);
|
||||||
} catch (e: unknown) {
|
} catch (e: unknown) {
|
||||||
exceptionAlert(e);
|
exceptionAlert(e);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ActionTypes["Recruitment"]:
|
case ActionTypes["Recruitment"]:
|
||||||
this.actionTimeToComplete = this.getRecruitmentTime(person);
|
this.actionTimeToComplete = this.getRecruitmentTime(Player);
|
||||||
break;
|
break;
|
||||||
case ActionTypes["Training"]:
|
case ActionTypes["Training"]:
|
||||||
case ActionTypes["FieldAnalysis"]:
|
case ActionTypes["FieldAnalysis"]:
|
||||||
@ -234,7 +230,7 @@ export class Bladeburner implements IBladeburner {
|
|||||||
this.actionTimeToComplete = 60;
|
this.actionTimeToComplete = 60;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new Error("Invalid Action Type in startAction(Bladeburner,player, ): " + actionId.type);
|
throw new Error("Invalid Action Type in bladeburner.startAction(): " + actionId.type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -252,7 +248,7 @@ export class Bladeburner implements IBladeburner {
|
|||||||
this.updateSkillMultipliers();
|
this.updateSkillMultipliers();
|
||||||
}
|
}
|
||||||
|
|
||||||
executeConsoleCommands(player: IPlayer, commands: string): void {
|
executeConsoleCommands(commands: string): void {
|
||||||
try {
|
try {
|
||||||
// Console History
|
// Console History
|
||||||
if (this.consoleHistory[this.consoleHistory.length - 1] != commands) {
|
if (this.consoleHistory[this.consoleHistory.length - 1] != commands) {
|
||||||
@ -264,7 +260,7 @@ export class Bladeburner implements IBladeburner {
|
|||||||
|
|
||||||
const arrayOfCommands = commands.split(";");
|
const arrayOfCommands = commands.split(";");
|
||||||
for (let i = 0; i < arrayOfCommands.length; ++i) {
|
for (let i = 0; i < arrayOfCommands.length; ++i) {
|
||||||
this.executeConsoleCommand(player, arrayOfCommands[i]);
|
this.executeConsoleCommand(arrayOfCommands[i]);
|
||||||
}
|
}
|
||||||
} catch (e: unknown) {
|
} catch (e: unknown) {
|
||||||
exceptionAlert(e);
|
exceptionAlert(e);
|
||||||
@ -309,7 +305,7 @@ export class Bladeburner implements IBladeburner {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// working on
|
// working on
|
||||||
getActionIdFromTypeAndName(type = "", name = ""): IActionIdentifier | null {
|
getActionIdFromTypeAndName(type = "", name = ""): ActionIdentifier | null {
|
||||||
if (type === "" || name === "") {
|
if (type === "" || name === "") {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -394,7 +390,7 @@ export class Bladeburner implements IBladeburner {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
executeStartConsoleCommand(player: IPlayer, args: string[]): void {
|
executeStartConsoleCommand(args: string[]): void {
|
||||||
if (args.length !== 3) {
|
if (args.length !== 3) {
|
||||||
this.postToConsole("Invalid usage of 'start' console command: start [type] [name]");
|
this.postToConsole("Invalid usage of 'start' console command: start [type] [name]");
|
||||||
this.postToConsole("Use 'help start' for more info");
|
this.postToConsole("Use 'help start' for more info");
|
||||||
@ -407,7 +403,7 @@ export class Bladeburner implements IBladeburner {
|
|||||||
if (GeneralActions[name] != null) {
|
if (GeneralActions[name] != null) {
|
||||||
this.action.type = ActionTypes[name];
|
this.action.type = ActionTypes[name];
|
||||||
this.action.name = name;
|
this.action.name = name;
|
||||||
this.startAction(player, this.action);
|
this.startAction(this.action);
|
||||||
} else {
|
} else {
|
||||||
this.postToConsole("Invalid action name specified: " + args[2]);
|
this.postToConsole("Invalid action name specified: " + args[2]);
|
||||||
}
|
}
|
||||||
@ -417,7 +413,7 @@ export class Bladeburner implements IBladeburner {
|
|||||||
if (this.contracts[name] != null) {
|
if (this.contracts[name] != null) {
|
||||||
this.action.type = ActionTypes.Contract;
|
this.action.type = ActionTypes.Contract;
|
||||||
this.action.name = name;
|
this.action.name = name;
|
||||||
this.startAction(player, this.action);
|
this.startAction(this.action);
|
||||||
} else {
|
} else {
|
||||||
this.postToConsole("Invalid contract name specified: " + args[2]);
|
this.postToConsole("Invalid contract name specified: " + args[2]);
|
||||||
}
|
}
|
||||||
@ -429,7 +425,7 @@ export class Bladeburner implements IBladeburner {
|
|||||||
if (this.operations[name] != null) {
|
if (this.operations[name] != null) {
|
||||||
this.action.type = ActionTypes.Operation;
|
this.action.type = ActionTypes.Operation;
|
||||||
this.action.name = name;
|
this.action.name = name;
|
||||||
this.startAction(player, this.action);
|
this.startAction(this.action);
|
||||||
} else {
|
} else {
|
||||||
this.postToConsole("Invalid Operation name specified: " + args[2]);
|
this.postToConsole("Invalid Operation name specified: " + args[2]);
|
||||||
}
|
}
|
||||||
@ -441,7 +437,7 @@ export class Bladeburner implements IBladeburner {
|
|||||||
if (BlackOperations[name] != null) {
|
if (BlackOperations[name] != null) {
|
||||||
this.action.type = ActionTypes.BlackOperation;
|
this.action.type = ActionTypes.BlackOperation;
|
||||||
this.action.name = name;
|
this.action.name = name;
|
||||||
this.startAction(player, this.action);
|
this.startAction(this.action);
|
||||||
} else {
|
} else {
|
||||||
this.postToConsole("Invalid BlackOp name specified: " + args[2]);
|
this.postToConsole("Invalid BlackOp name specified: " + args[2]);
|
||||||
}
|
}
|
||||||
@ -542,7 +538,7 @@ export class Bladeburner implements IBladeburner {
|
|||||||
case 3: {
|
case 3: {
|
||||||
const skillName = args[2];
|
const skillName = args[2];
|
||||||
const skill = Skills[skillName];
|
const skill = Skills[skillName];
|
||||||
if (skill == null || !(skill instanceof Skill)) {
|
if (!skill) {
|
||||||
this.postToConsole("Invalid skill name (Note that it is case-sensitive): " + skillName);
|
this.postToConsole("Invalid skill name (Note that it is case-sensitive): " + skillName);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -684,10 +680,7 @@ export class Bladeburner implements IBladeburner {
|
|||||||
".",
|
".",
|
||||||
);
|
);
|
||||||
} else if (flag.toLowerCase().includes("en")) {
|
} else if (flag.toLowerCase().includes("en")) {
|
||||||
if (
|
if (!this.automateActionLow || !this.automateActionHigh) {
|
||||||
!(this.automateActionLow instanceof ActionIdentifier) ||
|
|
||||||
!(this.automateActionHigh instanceof ActionIdentifier)
|
|
||||||
) {
|
|
||||||
return this.log("Failed to enable automation. Actions were not set");
|
return this.log("Failed to enable automation. Actions were not set");
|
||||||
}
|
}
|
||||||
this.automateEnabled = true;
|
this.automateEnabled = true;
|
||||||
@ -820,7 +813,7 @@ export class Bladeburner implements IBladeburner {
|
|||||||
return args;
|
return args;
|
||||||
}
|
}
|
||||||
|
|
||||||
executeConsoleCommand(player: IPlayer, command: string): void {
|
executeConsoleCommand(command: string): void {
|
||||||
command = command.trim();
|
command = command.trim();
|
||||||
command = command.replace(/\s\s+/g, " "); // Replace all whitespace w/ a single space
|
command = command.replace(/\s\s+/g, " "); // Replace all whitespace w/ a single space
|
||||||
|
|
||||||
@ -845,7 +838,7 @@ export class Bladeburner implements IBladeburner {
|
|||||||
this.executeSkillConsoleCommand(args);
|
this.executeSkillConsoleCommand(args);
|
||||||
break;
|
break;
|
||||||
case "start":
|
case "start":
|
||||||
this.executeStartConsoleCommand(player, args);
|
this.executeStartConsoleCommand(args);
|
||||||
break;
|
break;
|
||||||
case "stop":
|
case "stop":
|
||||||
this.resetAction();
|
this.resetAction();
|
||||||
@ -898,9 +891,7 @@ export class Bladeburner implements IBladeburner {
|
|||||||
// Choose random source/destination city for events
|
// Choose random source/destination city for events
|
||||||
const sourceCityName = BladeburnerConstants.CityNames[getRandomInt(0, 5)];
|
const sourceCityName = BladeburnerConstants.CityNames[getRandomInt(0, 5)];
|
||||||
const sourceCity = this.cities[sourceCityName];
|
const sourceCity = this.cities[sourceCityName];
|
||||||
if (!(sourceCity instanceof City)) {
|
if (!sourceCity) throw new Error("Invalid sourceCity in Bladeburner.randomEvent()");
|
||||||
throw new Error("sourceCity was not a City object in Bladeburner.randomEvent()");
|
|
||||||
}
|
|
||||||
|
|
||||||
let destCityName = BladeburnerConstants.CityNames[getRandomInt(0, 5)];
|
let destCityName = BladeburnerConstants.CityNames[getRandomInt(0, 5)];
|
||||||
while (destCityName === sourceCityName) {
|
while (destCityName === sourceCityName) {
|
||||||
@ -908,9 +899,7 @@ export class Bladeburner implements IBladeburner {
|
|||||||
}
|
}
|
||||||
const destCity = this.cities[destCityName];
|
const destCity = this.cities[destCityName];
|
||||||
|
|
||||||
if (!(sourceCity instanceof City) || !(destCity instanceof City)) {
|
if (!sourceCity || !destCity) throw new Error("Invalid sourceCity or destCity in Bladeburner.randomEvent()");
|
||||||
throw new Error("sourceCity/destCity was not a City object in Bladeburner.randomEvent()");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (chance <= 0.05) {
|
if (chance <= 0.05) {
|
||||||
// New Synthoid Community, 5%
|
// New Synthoid Community, 5%
|
||||||
@ -994,7 +983,7 @@ export class Bladeburner implements IBladeburner {
|
|||||||
* @param action(Action obj) - Derived action class
|
* @param action(Action obj) - Derived action class
|
||||||
* @param success(bool) - Whether action was successful
|
* @param success(bool) - Whether action was successful
|
||||||
*/
|
*/
|
||||||
getActionStats(action: IAction, person: IPerson, success: boolean): ITaskTracker {
|
getActionStats(action: Action, person: Person, success: boolean): ITaskTracker {
|
||||||
const difficulty = action.getDifficulty();
|
const difficulty = action.getDifficulty();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1024,7 +1013,7 @@ export class Bladeburner implements IBladeburner {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
getDiplomacyEffectiveness(person: IPerson): number {
|
getDiplomacyEffectiveness(person: Person): number {
|
||||||
// Returns a decimal by which the city's chaos level should be multiplied (e.g. 0.98)
|
// Returns a decimal by which the city's chaos level should be multiplied (e.g. 0.98)
|
||||||
const CharismaLinearFactor = 1e3;
|
const CharismaLinearFactor = 1e3;
|
||||||
const CharismaExponentialFactor = 0.045;
|
const CharismaExponentialFactor = 0.045;
|
||||||
@ -1034,11 +1023,11 @@ export class Bladeburner implements IBladeburner {
|
|||||||
return (100 - charismaEff) / 100;
|
return (100 - charismaEff) / 100;
|
||||||
}
|
}
|
||||||
|
|
||||||
getRecruitmentSuccessChance(person: IPerson): number {
|
getRecruitmentSuccessChance(person: Person): number {
|
||||||
return Math.pow(person.skills.charisma, 0.45) / (this.teamSize - this.sleeveSize + 1);
|
return Math.pow(person.skills.charisma, 0.45) / (this.teamSize - this.sleeveSize + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
getRecruitmentTime(person: IPerson): number {
|
getRecruitmentTime(person: Person): number {
|
||||||
const effCharisma = person.skills.charisma * this.skillMultipliers.effCha;
|
const effCharisma = person.skills.charisma * this.skillMultipliers.effCha;
|
||||||
const charismaFactor = Math.pow(effCharisma, 0.81) + effCharisma / 90;
|
const charismaFactor = Math.pow(effCharisma, 0.81) + effCharisma / 90;
|
||||||
return Math.max(10, Math.round(BladeburnerConstants.BaseRecruitmentTimeNeeded - charismaFactor));
|
return Math.max(10, Math.round(BladeburnerConstants.BaseRecruitmentTimeNeeded - charismaFactor));
|
||||||
@ -1105,7 +1094,7 @@ export class Bladeburner implements IBladeburner {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
completeOperation(success: boolean, player: IPlayer): void {
|
completeOperation(success: boolean): void {
|
||||||
if (this.action.type !== ActionTypes.Operation) {
|
if (this.action.type !== ActionTypes.Operation) {
|
||||||
throw new Error("completeOperation() called even though current action is not an Operation");
|
throw new Error("completeOperation() called even though current action is not an Operation");
|
||||||
}
|
}
|
||||||
@ -1126,7 +1115,7 @@ export class Bladeburner implements IBladeburner {
|
|||||||
const losses = getRandomInt(0, max);
|
const losses = getRandomInt(0, max);
|
||||||
this.teamSize -= losses;
|
this.teamSize -= losses;
|
||||||
if (this.teamSize < this.sleeveSize) {
|
if (this.teamSize < this.sleeveSize) {
|
||||||
const sup = player.sleeves.filter((x) => isSleeveSupportWork(x.currentWork));
|
const sup = Player.sleeves.filter((x) => isSleeveSupportWork(x.currentWork));
|
||||||
for (let i = 0; i > this.teamSize - this.sleeveSize; i--) {
|
for (let i = 0; i > this.teamSize - this.sleeveSize; i--) {
|
||||||
const r = Math.floor(Math.random() * sup.length);
|
const r = Math.floor(Math.random() * sup.length);
|
||||||
sup[r].takeDamage(sup[r].hp.max);
|
sup[r].takeDamage(sup[r].hp.max);
|
||||||
@ -1201,7 +1190,7 @@ export class Bladeburner implements IBladeburner {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
getActionObject(actionId: IActionIdentifier): IAction | null {
|
getActionObject(actionId: ActionIdentifier): Action | null {
|
||||||
/**
|
/**
|
||||||
* Given an ActionIdentifier object, returns the corresponding
|
* Given an ActionIdentifier object, returns the corresponding
|
||||||
* GeneralAction, Contract, Operation, or BlackOperation object
|
* GeneralAction, Contract, Operation, or BlackOperation object
|
||||||
@ -1231,7 +1220,7 @@ export class Bladeburner implements IBladeburner {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
completeContract(success: boolean, actionIdent: IActionIdentifier): void {
|
completeContract(success: boolean, actionIdent: ActionIdentifier): void {
|
||||||
if (actionIdent.type !== ActionTypes.Contract) {
|
if (actionIdent.type !== ActionTypes.Contract) {
|
||||||
throw new Error("completeContract() called even though current action is not a Contract");
|
throw new Error("completeContract() called even though current action is not a Contract");
|
||||||
}
|
}
|
||||||
@ -1256,7 +1245,7 @@ export class Bladeburner implements IBladeburner {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
completeAction(player: IPlayer, person: IPerson, actionIdent: IActionIdentifier, isPlayer = true): ITaskTracker {
|
completeAction(person: Person, actionIdent: ActionIdentifier, isPlayer = true): ITaskTracker {
|
||||||
let retValue = createTaskTracker();
|
let retValue = createTaskTracker();
|
||||||
switch (actionIdent.type) {
|
switch (actionIdent.type) {
|
||||||
case ActionTypes["Contract"]:
|
case ActionTypes["Contract"]:
|
||||||
@ -1304,24 +1293,16 @@ export class Bladeburner implements IBladeburner {
|
|||||||
this.changeRank(person, gain);
|
this.changeRank(person, gain);
|
||||||
if (isOperation && this.logging.ops) {
|
if (isOperation && this.logging.ops) {
|
||||||
this.log(
|
this.log(
|
||||||
`${person.whoAmI()}: ` +
|
`${person.whoAmI()}: ${action.name} successfully completed! Gained ${formatNumber(gain, 3)} rank`,
|
||||||
action.name +
|
|
||||||
" successfully completed! Gained " +
|
|
||||||
formatNumber(gain, 3) +
|
|
||||||
" rank",
|
|
||||||
);
|
);
|
||||||
} else if (!isOperation && this.logging.contracts) {
|
} else if (!isOperation && this.logging.contracts) {
|
||||||
this.log(
|
this.log(
|
||||||
`${person.whoAmI()}: ` +
|
`${person.whoAmI()}: ${action.name} contract successfully completed! Gained ` +
|
||||||
action.name +
|
`${formatNumber(gain, 3)} rank and ${numeralWrapper.formatMoney(moneyGain)}`,
|
||||||
" contract successfully completed! Gained " +
|
|
||||||
formatNumber(gain, 3) +
|
|
||||||
" rank and " +
|
|
||||||
numeralWrapper.formatMoney(moneyGain),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
isOperation ? this.completeOperation(true, player) : this.completeContract(true, actionIdent);
|
isOperation ? this.completeOperation(true) : this.completeContract(true, actionIdent);
|
||||||
} else {
|
} else {
|
||||||
retValue = this.getActionStats(action, person, false);
|
retValue = this.getActionStats(action, person, false);
|
||||||
++action.failures;
|
++action.failures;
|
||||||
@ -1335,7 +1316,7 @@ export class Bladeburner implements IBladeburner {
|
|||||||
damage = action.hpLoss * difficultyMultiplier;
|
damage = action.hpLoss * difficultyMultiplier;
|
||||||
damage = Math.ceil(addOffset(damage, 10));
|
damage = Math.ceil(addOffset(damage, 10));
|
||||||
this.hpLost += damage;
|
this.hpLost += damage;
|
||||||
const cost = calculateHospitalizationCost(player, damage);
|
const cost = calculateHospitalizationCost(damage);
|
||||||
if (person.takeDamage(damage)) {
|
if (person.takeDamage(damage)) {
|
||||||
++this.numHosp;
|
++this.numHosp;
|
||||||
this.moneyLost += cost;
|
this.moneyLost += cost;
|
||||||
@ -1353,7 +1334,7 @@ export class Bladeburner implements IBladeburner {
|
|||||||
} else if (!isOperation && this.logging.contracts) {
|
} else if (!isOperation && this.logging.contracts) {
|
||||||
this.log(`${person.whoAmI()}: ` + action.name + " contract failed! " + logLossText);
|
this.log(`${person.whoAmI()}: ` + action.name + " contract failed! " + logLossText);
|
||||||
}
|
}
|
||||||
isOperation ? this.completeOperation(false, player) : this.completeContract(false, actionIdent);
|
isOperation ? this.completeOperation(false) : this.completeContract(false, actionIdent);
|
||||||
}
|
}
|
||||||
if (action.autoLevel) {
|
if (action.autoLevel) {
|
||||||
action.level = action.maxLevel;
|
action.level = action.maxLevel;
|
||||||
@ -1412,7 +1393,7 @@ export class Bladeburner implements IBladeburner {
|
|||||||
if (action.hpLoss) {
|
if (action.hpLoss) {
|
||||||
damage = action.hpLoss * difficultyMultiplier;
|
damage = action.hpLoss * difficultyMultiplier;
|
||||||
damage = Math.ceil(addOffset(damage, 10));
|
damage = Math.ceil(addOffset(damage, 10));
|
||||||
const cost = calculateHospitalizationCost(player, damage);
|
const cost = calculateHospitalizationCost(damage);
|
||||||
if (person.takeDamage(damage)) {
|
if (person.takeDamage(damage)) {
|
||||||
++this.numHosp;
|
++this.numHosp;
|
||||||
this.moneyLost += cost;
|
this.moneyLost += cost;
|
||||||
@ -1440,7 +1421,7 @@ export class Bladeburner implements IBladeburner {
|
|||||||
const losses = getRandomInt(1, teamLossMax);
|
const losses = getRandomInt(1, teamLossMax);
|
||||||
this.teamSize -= losses;
|
this.teamSize -= losses;
|
||||||
if (this.teamSize < this.sleeveSize) {
|
if (this.teamSize < this.sleeveSize) {
|
||||||
const sup = player.sleeves.filter((x) => isSleeveSupportWork(x.currentWork));
|
const sup = Player.sleeves.filter((x) => isSleeveSupportWork(x.currentWork));
|
||||||
for (let i = 0; i > this.teamSize - this.sleeveSize; i--) {
|
for (let i = 0; i > this.teamSize - this.sleeveSize; i--) {
|
||||||
const r = Math.floor(Math.random() * sup.length);
|
const r = Math.floor(Math.random() * sup.length);
|
||||||
sup[r].takeDamage(sup[r].hp.max);
|
sup[r].takeDamage(sup[r].hp.max);
|
||||||
@ -1603,8 +1584,8 @@ export class Bladeburner implements IBladeburner {
|
|||||||
return retValue;
|
return retValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
infiltrateSynthoidCommunities(p: IPlayer): void {
|
infiltrateSynthoidCommunities(): void {
|
||||||
const infilSleeves = p.sleeves.filter((s) => isSleeveInfiltrateWork(s.currentWork)).length;
|
const infilSleeves = Player.sleeves.filter((s) => isSleeveInfiltrateWork(s.currentWork)).length;
|
||||||
const amt = Math.pow(infilSleeves, -0.5) / 2;
|
const amt = Math.pow(infilSleeves, -0.5) / 2;
|
||||||
for (const contract of Object.keys(this.contracts)) {
|
for (const contract of Object.keys(this.contracts)) {
|
||||||
this.contracts[contract].count += amt;
|
this.contracts[contract].count += amt;
|
||||||
@ -1617,7 +1598,7 @@ export class Bladeburner implements IBladeburner {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
changeRank(person: IPerson, change: number): void {
|
changeRank(person: Person, change: number): void {
|
||||||
if (isNaN(change)) {
|
if (isNaN(change)) {
|
||||||
throw new Error("NaN passed into Bladeburner.changeRank()");
|
throw new Error("NaN passed into Bladeburner.changeRank()");
|
||||||
}
|
}
|
||||||
@ -1630,7 +1611,7 @@ export class Bladeburner implements IBladeburner {
|
|||||||
const bladeburnersFactionName = FactionNames.Bladeburners;
|
const bladeburnersFactionName = FactionNames.Bladeburners;
|
||||||
if (factionExists(bladeburnersFactionName)) {
|
if (factionExists(bladeburnersFactionName)) {
|
||||||
const bladeburnerFac = Factions[bladeburnersFactionName];
|
const bladeburnerFac = Factions[bladeburnersFactionName];
|
||||||
if (!(bladeburnerFac instanceof Faction)) {
|
if (!bladeburnerFac) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`Could not properly get ${FactionNames.Bladeburners} Faction object in ${FactionNames.Bladeburners} UI Overview Faction button`,
|
`Could not properly get ${FactionNames.Bladeburners} Faction object in ${FactionNames.Bladeburners} UI Overview Faction button`,
|
||||||
);
|
);
|
||||||
@ -1654,12 +1635,12 @@ export class Bladeburner implements IBladeburner {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
processAction(router: IRouter, player: IPlayer, seconds: number): void {
|
processAction(seconds: number): void {
|
||||||
if (this.action.type === ActionTypes["Idle"]) return;
|
if (this.action.type === ActionTypes["Idle"]) return;
|
||||||
if (this.actionTimeToComplete <= 0) {
|
if (this.actionTimeToComplete <= 0) {
|
||||||
throw new Error(`Invalid actionTimeToComplete value: ${this.actionTimeToComplete}, type; ${this.action.type}`);
|
throw new Error(`Invalid actionTimeToComplete value: ${this.actionTimeToComplete}, type; ${this.action.type}`);
|
||||||
}
|
}
|
||||||
if (!(this.action instanceof ActionIdentifier)) {
|
if (!this.action) {
|
||||||
throw new Error("Bladeburner.action is not an ActionIdentifier Object");
|
throw new Error("Bladeburner.action is not an ActionIdentifier Object");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1670,31 +1651,31 @@ export class Bladeburner implements IBladeburner {
|
|||||||
if (this.actionTimeCurrent >= this.actionTimeToComplete) {
|
if (this.actionTimeCurrent >= this.actionTimeToComplete) {
|
||||||
this.actionTimeOverflow = this.actionTimeCurrent - this.actionTimeToComplete;
|
this.actionTimeOverflow = this.actionTimeCurrent - this.actionTimeToComplete;
|
||||||
const action = this.getActionObject(this.action);
|
const action = this.getActionObject(this.action);
|
||||||
const retValue = this.completeAction(player, player, this.action);
|
const retValue = this.completeAction(Player, this.action);
|
||||||
player.gainMoney(retValue.money, "bladeburner");
|
Player.gainMoney(retValue.money, "bladeburner");
|
||||||
player.gainStats(retValue);
|
Player.gainStats(retValue);
|
||||||
// Operation Daedalus
|
// Operation Daedalus
|
||||||
if (action == null) {
|
if (action == null) {
|
||||||
throw new Error("Failed to get BlackOperation Object for: " + this.action.name);
|
throw new Error("Failed to get BlackOperation Object for: " + this.action.name);
|
||||||
} else if (this.action.type != ActionTypes["BlackOperation"] && this.action.type != ActionTypes["BlackOp"]) {
|
} else if (this.action.type != ActionTypes["BlackOperation"] && this.action.type != ActionTypes["BlackOp"]) {
|
||||||
this.startAction(player, this.action); // Repeat action
|
this.startAction(this.action); // Repeat action
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
calculateStaminaGainPerSecond(player: IPlayer): number {
|
calculateStaminaGainPerSecond(): number {
|
||||||
const effAgility = player.skills.agility * this.skillMultipliers.effAgi;
|
const effAgility = Player.skills.agility * this.skillMultipliers.effAgi;
|
||||||
const maxStaminaBonus = this.maxStamina / BladeburnerConstants.MaxStaminaToGainFactor;
|
const maxStaminaBonus = this.maxStamina / BladeburnerConstants.MaxStaminaToGainFactor;
|
||||||
const gain = (BladeburnerConstants.StaminaGainPerSecond + maxStaminaBonus) * Math.pow(effAgility, 0.17);
|
const gain = (BladeburnerConstants.StaminaGainPerSecond + maxStaminaBonus) * Math.pow(effAgility, 0.17);
|
||||||
return gain * (this.skillMultipliers.stamina * player.mults.bladeburner_stamina_gain);
|
return gain * (this.skillMultipliers.stamina * Player.mults.bladeburner_stamina_gain);
|
||||||
}
|
}
|
||||||
|
|
||||||
calculateMaxStamina(player: IPlayer): void {
|
calculateMaxStamina(): void {
|
||||||
const effAgility = player.skills.agility * this.skillMultipliers.effAgi;
|
const effAgility = Player.skills.agility * this.skillMultipliers.effAgi;
|
||||||
const maxStamina =
|
const maxStamina =
|
||||||
(Math.pow(effAgility, 0.8) + this.staminaBonus) *
|
(Math.pow(effAgility, 0.8) + this.staminaBonus) *
|
||||||
this.skillMultipliers.stamina *
|
this.skillMultipliers.stamina *
|
||||||
player.mults.bladeburner_max_stamina;
|
Player.mults.bladeburner_max_stamina;
|
||||||
if (this.maxStamina !== maxStamina) {
|
if (this.maxStamina !== maxStamina) {
|
||||||
const oldMax = this.maxStamina;
|
const oldMax = this.maxStamina;
|
||||||
this.maxStamina = maxStamina;
|
this.maxStamina = maxStamina;
|
||||||
@ -1974,12 +1955,12 @@ export class Bladeburner implements IBladeburner {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
process(router: IRouter, player: IPlayer): void {
|
process(): void {
|
||||||
// Edge race condition when the engine checks the processing counters and attempts to route before the router is initialized.
|
// Edge race condition when the engine checks the processing counters and attempts to route before the router is initialized.
|
||||||
if (!router.isInitialized) return;
|
if (!Router.isInitialized) return;
|
||||||
|
|
||||||
// If the Player starts doing some other actions, set action to idle and alert
|
// If the Player starts doing some other actions, set action to idle and alert
|
||||||
if (!player.hasAugmentation(AugmentationNames.BladesSimulacrum, true) && player.currentWork) {
|
if (!Player.hasAugmentation(AugmentationNames.BladesSimulacrum, true) && Player.currentWork) {
|
||||||
if (this.action.type !== ActionTypes["Idle"]) {
|
if (this.action.type !== ActionTypes["Idle"]) {
|
||||||
let msg = "Your Bladeburner action was cancelled because you started doing something else.";
|
let msg = "Your Bladeburner action was cancelled because you started doing something else.";
|
||||||
if (this.automateEnabled) {
|
if (this.automateEnabled) {
|
||||||
@ -2006,8 +1987,8 @@ export class Bladeburner implements IBladeburner {
|
|||||||
this.storedCycles -= seconds * BladeburnerConstants.CyclesPerSecond;
|
this.storedCycles -= seconds * BladeburnerConstants.CyclesPerSecond;
|
||||||
|
|
||||||
// Stamina
|
// Stamina
|
||||||
this.calculateMaxStamina(player);
|
this.calculateMaxStamina();
|
||||||
this.stamina += this.calculateStaminaGainPerSecond(player) * seconds;
|
this.stamina += this.calculateStaminaGainPerSecond() * seconds;
|
||||||
this.stamina = Math.min(this.maxStamina, this.stamina);
|
this.stamina = Math.min(this.maxStamina, this.stamina);
|
||||||
|
|
||||||
// Count increase for contracts/operations
|
// Count increase for contracts/operations
|
||||||
@ -2027,9 +2008,7 @@ export class Bladeburner implements IBladeburner {
|
|||||||
// Chaos goes down very slowly
|
// Chaos goes down very slowly
|
||||||
for (const cityName of BladeburnerConstants.CityNames) {
|
for (const cityName of BladeburnerConstants.CityNames) {
|
||||||
const city = this.cities[cityName];
|
const city = this.cities[cityName];
|
||||||
if (!(city instanceof City)) {
|
if (!city) throw new Error("Invalid city when processing passive chaos reduction in Bladeburner.process");
|
||||||
throw new Error("Invalid City object when processing passive chaos reduction in Bladeburner.process");
|
|
||||||
}
|
|
||||||
city.chaos -= 0.0001 * seconds;
|
city.chaos -= 0.0001 * seconds;
|
||||||
city.chaos = Math.max(0, city.chaos);
|
city.chaos = Math.max(0, city.chaos);
|
||||||
}
|
}
|
||||||
@ -2042,7 +2021,7 @@ export class Bladeburner implements IBladeburner {
|
|||||||
this.randomEventCounter += getRandomInt(240, 600);
|
this.randomEventCounter += getRandomInt(240, 600);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.processAction(router, player, seconds);
|
this.processAction(seconds);
|
||||||
|
|
||||||
// Automation
|
// Automation
|
||||||
if (this.automateEnabled) {
|
if (this.automateEnabled) {
|
||||||
@ -2053,7 +2032,7 @@ export class Bladeburner implements IBladeburner {
|
|||||||
type: this.automateActionLow.type,
|
type: this.automateActionLow.type,
|
||||||
name: this.automateActionLow.name,
|
name: this.automateActionLow.name,
|
||||||
});
|
});
|
||||||
this.startAction(player, this.action);
|
this.startAction(this.action);
|
||||||
}
|
}
|
||||||
} else if (this.stamina >= this.automateThreshHigh) {
|
} else if (this.stamina >= this.automateThreshHigh) {
|
||||||
if (this.action.name !== this.automateActionHigh.name || this.action.type !== this.automateActionHigh.type) {
|
if (this.action.name !== this.automateActionHigh.name || this.action.type !== this.automateActionHigh.type) {
|
||||||
@ -2061,14 +2040,14 @@ export class Bladeburner implements IBladeburner {
|
|||||||
type: this.automateActionHigh.type,
|
type: this.automateActionHigh.type,
|
||||||
name: this.automateActionHigh.name,
|
name: this.automateActionHigh.name,
|
||||||
});
|
});
|
||||||
this.startAction(player, this.action);
|
this.startAction(this.action);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
getTypeAndNameFromActionId(actionId: IActionIdentifier): {
|
getTypeAndNameFromActionId(actionId: ActionIdentifier): {
|
||||||
type: string;
|
type: string;
|
||||||
name: string;
|
name: string;
|
||||||
} {
|
} {
|
||||||
@ -2121,7 +2100,7 @@ export class Bladeburner implements IBladeburner {
|
|||||||
return Object.keys(Skills);
|
return Object.keys(Skills);
|
||||||
}
|
}
|
||||||
|
|
||||||
startActionNetscriptFn(player: IPlayer, type: string, name: string, workerScript: WorkerScript): boolean {
|
startActionNetscriptFn(type: string, name: string, workerScript: WorkerScript): boolean {
|
||||||
const errorLogText = `Invalid action: type='${type}' name='${name}'`;
|
const errorLogText = `Invalid action: type='${type}' name='${name}'`;
|
||||||
const actionId = this.getActionIdFromTypeAndName(type, name);
|
const actionId = this.getActionIdFromTypeAndName(type, name);
|
||||||
if (actionId == null) {
|
if (actionId == null) {
|
||||||
@ -2139,7 +2118,7 @@ export class Bladeburner implements IBladeburner {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
this.startAction(player, actionId);
|
this.startAction(actionId);
|
||||||
workerScript.log(
|
workerScript.log(
|
||||||
"bladeburner.startAction",
|
"bladeburner.startAction",
|
||||||
() => `Starting bladeburner action with type '${type}' and name '${name}'`,
|
() => `Starting bladeburner action with type '${type}' and name '${name}'`,
|
||||||
@ -2153,7 +2132,7 @@ export class Bladeburner implements IBladeburner {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
getActionTimeNetscriptFn(person: IPerson, type: string, name: string): number | string {
|
getActionTimeNetscriptFn(person: Person, type: string, name: string): number | string {
|
||||||
const actionId = this.getActionIdFromTypeAndName(type, name);
|
const actionId = this.getActionIdFromTypeAndName(type, name);
|
||||||
if (actionId == null) {
|
if (actionId == null) {
|
||||||
return "bladeburner.getActionTime";
|
return "bladeburner.getActionTime";
|
||||||
@ -2184,7 +2163,7 @@ export class Bladeburner implements IBladeburner {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
getActionEstimatedSuccessChanceNetscriptFn(person: IPerson, type: string, name: string): [number, number] | string {
|
getActionEstimatedSuccessChanceNetscriptFn(person: Person, type: string, name: string): [number, number] | string {
|
||||||
const actionId = this.getActionIdFromTypeAndName(type, name);
|
const actionId = this.getActionIdFromTypeAndName(type, name);
|
||||||
if (actionId == null) {
|
if (actionId == null) {
|
||||||
return "bladeburner.getActionEstimatedSuccessChance";
|
return "bladeburner.getActionEstimatedSuccessChance";
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { IBladeburner } from "./IBladeburner";
|
import { Bladeburner } from "./Bladeburner";
|
||||||
import { Action, IActionParams } from "./Action";
|
import { Action, IActionParams } from "./Action";
|
||||||
import { Generic_fromJSON, Generic_toJSON, IReviverValue, Reviver } from "../utils/JSONReviver";
|
import { Generic_fromJSON, Generic_toJSON, IReviverValue, Reviver } from "../utils/JSONReviver";
|
||||||
|
|
||||||
@ -7,7 +7,7 @@ export class Contract extends Action {
|
|||||||
super(params);
|
super(params);
|
||||||
}
|
}
|
||||||
|
|
||||||
getActionTypeSkillSuccessBonus(inst: IBladeburner): number {
|
getActionTypeSkillSuccessBonus(inst: Bladeburner): number {
|
||||||
return inst.skillMultipliers.successChanceContract;
|
return inst.skillMultipliers.successChanceContract;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,72 +0,0 @@
|
|||||||
import { IReviverValue } from "../utils/JSONReviver";
|
|
||||||
import { IPerson } from "../PersonObjects/IPerson";
|
|
||||||
import { IBladeburner } from "./IBladeburner";
|
|
||||||
|
|
||||||
interface IStatsMultiplier {
|
|
||||||
[key: string]: number;
|
|
||||||
|
|
||||||
hack: number;
|
|
||||||
str: number;
|
|
||||||
def: number;
|
|
||||||
dex: number;
|
|
||||||
agi: number;
|
|
||||||
cha: number;
|
|
||||||
int: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface ISuccessChanceParams {
|
|
||||||
est: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface IAction {
|
|
||||||
name: string;
|
|
||||||
|
|
||||||
// Difficulty scales with level. See getDifficulty() method
|
|
||||||
level: number;
|
|
||||||
maxLevel: number;
|
|
||||||
autoLevel: boolean;
|
|
||||||
baseDifficulty: number;
|
|
||||||
difficultyFac: number;
|
|
||||||
|
|
||||||
// Rank increase/decrease is affected by this exponent
|
|
||||||
rewardFac: number;
|
|
||||||
|
|
||||||
successes: number;
|
|
||||||
failures: number;
|
|
||||||
|
|
||||||
// All of these scale with level/difficulty
|
|
||||||
rankGain: number;
|
|
||||||
rankLoss: number;
|
|
||||||
hpLoss: number;
|
|
||||||
hpLost: number;
|
|
||||||
|
|
||||||
// Action Category. Current categories are stealth and kill
|
|
||||||
isStealth: boolean;
|
|
||||||
isKill: boolean;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Number of this contract remaining, and its growth rate
|
|
||||||
* Growth rate is an integer and the count will increase by that integer every "cycle"
|
|
||||||
*/
|
|
||||||
count: number;
|
|
||||||
|
|
||||||
// Weighting of each stat in determining action success rate
|
|
||||||
weights: IStatsMultiplier;
|
|
||||||
// Diminishing returns of stats (stat ^ decay where 0 <= decay <= 1)
|
|
||||||
decays: IStatsMultiplier;
|
|
||||||
teamCount: number;
|
|
||||||
|
|
||||||
getDifficulty(): number;
|
|
||||||
attempt(inst: IBladeburner, person: IPerson): boolean;
|
|
||||||
getActionTimePenalty(): number;
|
|
||||||
getActionTime(inst: IBladeburner, person: IPerson): number;
|
|
||||||
getTeamSuccessBonus(inst: IBladeburner): number;
|
|
||||||
getActionTypeSkillSuccessBonus(inst: IBladeburner): number;
|
|
||||||
getChaosCompetencePenalty(inst: IBladeburner, params: ISuccessChanceParams): number;
|
|
||||||
getChaosDifficultyBonus(inst: IBladeburner): number;
|
|
||||||
getEstSuccessChance(inst: IBladeburner, person: IPerson): [number, number];
|
|
||||||
getSuccessChance(inst: IBladeburner, person: IPerson, params: ISuccessChanceParams): number;
|
|
||||||
getSuccessesNeededForNextLevel(baseSuccessesPerLevel: number): number;
|
|
||||||
setMaxLevel(baseSuccessesPerLevel: number): void;
|
|
||||||
toJSON(): IReviverValue;
|
|
||||||
}
|
|
@ -1,4 +0,0 @@
|
|||||||
export interface IActionIdentifier {
|
|
||||||
name: string;
|
|
||||||
type: number;
|
|
||||||
}
|
|
@ -1,121 +0,0 @@
|
|||||||
import { IActionIdentifier } from "./IActionIdentifier";
|
|
||||||
import { City } from "./City";
|
|
||||||
import { Skill } from "./Skill";
|
|
||||||
import { IAction } from "./IAction";
|
|
||||||
import { IPlayer } from "../PersonObjects/IPlayer";
|
|
||||||
import { IPerson } from "../PersonObjects/IPerson";
|
|
||||||
import { ITaskTracker } from "../PersonObjects/ITaskTracker";
|
|
||||||
import { IRouter } from "../ui/Router";
|
|
||||||
import { WorkerScript } from "../Netscript/WorkerScript";
|
|
||||||
import { Contract } from "./Contract";
|
|
||||||
import { Operation } from "./Operation";
|
|
||||||
|
|
||||||
export interface IBladeburner {
|
|
||||||
numHosp: number;
|
|
||||||
moneyLost: number;
|
|
||||||
rank: number;
|
|
||||||
maxRank: number;
|
|
||||||
|
|
||||||
skillPoints: number;
|
|
||||||
totalSkillPoints: number;
|
|
||||||
|
|
||||||
teamSize: number;
|
|
||||||
teamLost: number;
|
|
||||||
hpLost: number;
|
|
||||||
|
|
||||||
storedCycles: number;
|
|
||||||
|
|
||||||
randomEventCounter: number;
|
|
||||||
|
|
||||||
actionTimeToComplete: number;
|
|
||||||
actionTimeCurrent: number;
|
|
||||||
actionTimeOverflow: number;
|
|
||||||
|
|
||||||
action: IActionIdentifier;
|
|
||||||
|
|
||||||
cities: Record<string, City>;
|
|
||||||
city: string;
|
|
||||||
skills: Record<string, number>;
|
|
||||||
skillMultipliers: Record<string, number>;
|
|
||||||
staminaBonus: number;
|
|
||||||
maxStamina: number;
|
|
||||||
stamina: number;
|
|
||||||
contracts: Record<string, Contract>;
|
|
||||||
operations: Record<string, Operation>;
|
|
||||||
blackops: Record<string, boolean>;
|
|
||||||
logging: {
|
|
||||||
general: boolean;
|
|
||||||
contracts: boolean;
|
|
||||||
ops: boolean;
|
|
||||||
blackops: boolean;
|
|
||||||
events: boolean;
|
|
||||||
};
|
|
||||||
automateEnabled: boolean;
|
|
||||||
automateActionHigh: IActionIdentifier;
|
|
||||||
automateThreshHigh: number;
|
|
||||||
automateActionLow: IActionIdentifier;
|
|
||||||
automateThreshLow: number;
|
|
||||||
consoleHistory: string[];
|
|
||||||
consoleLogs: string[];
|
|
||||||
|
|
||||||
getCurrentCity(): City;
|
|
||||||
calculateStaminaPenalty(): number;
|
|
||||||
startAction(player: IPlayer, action: IActionIdentifier): void;
|
|
||||||
upgradeSkill(skill: Skill): void;
|
|
||||||
executeConsoleCommands(player: IPlayer, command: string): void;
|
|
||||||
postToConsole(input: string, saveToLogs?: boolean): void;
|
|
||||||
log(input: string): void;
|
|
||||||
resetAction(): void;
|
|
||||||
clearConsole(): void;
|
|
||||||
|
|
||||||
prestige(): void;
|
|
||||||
storeCycles(numCycles?: number): void;
|
|
||||||
getTypeAndNameFromActionId(actionId: IActionIdentifier): {
|
|
||||||
type: string;
|
|
||||||
name: string;
|
|
||||||
};
|
|
||||||
getContractNamesNetscriptFn(): string[];
|
|
||||||
getOperationNamesNetscriptFn(): string[];
|
|
||||||
getBlackOpNamesNetscriptFn(): string[];
|
|
||||||
getGeneralActionNamesNetscriptFn(): string[];
|
|
||||||
getSkillNamesNetscriptFn(): string[];
|
|
||||||
startActionNetscriptFn(player: IPlayer, type: string, name: string, workerScript: WorkerScript): boolean;
|
|
||||||
getActionTimeNetscriptFn(person: IPerson, type: string, name: string): number | string;
|
|
||||||
getActionEstimatedSuccessChanceNetscriptFn(person: IPerson, type: string, name: string): [number, number] | string;
|
|
||||||
getActionCountRemainingNetscriptFn(type: string, name: string, workerScript: WorkerScript): number;
|
|
||||||
getSkillLevelNetscriptFn(skillName: string, workerScript: WorkerScript): number;
|
|
||||||
getSkillUpgradeCostNetscriptFn(skillName: string, count: number, workerScript: WorkerScript): number;
|
|
||||||
upgradeSkillNetscriptFn(skillName: string, count: number, workerScript: WorkerScript): boolean;
|
|
||||||
getTeamSizeNetscriptFn(type: string, name: string, workerScript: WorkerScript): number;
|
|
||||||
setTeamSizeNetscriptFn(type: string, name: string, size: number, workerScript: WorkerScript): number;
|
|
||||||
joinBladeburnerFactionNetscriptFn(workerScript: WorkerScript): boolean;
|
|
||||||
getActionIdFromTypeAndName(type: string, name: string): IActionIdentifier | null;
|
|
||||||
executeStartConsoleCommand(player: IPlayer, args: string[]): void;
|
|
||||||
executeSkillConsoleCommand(args: string[]): void;
|
|
||||||
executeLogConsoleCommand(args: string[]): void;
|
|
||||||
executeHelpConsoleCommand(args: string[]): void;
|
|
||||||
executeAutomateConsoleCommand(args: string[]): void;
|
|
||||||
parseCommandArguments(command: string): string[];
|
|
||||||
executeConsoleCommand(player: IPlayer, command: string): void;
|
|
||||||
triggerMigration(sourceCityName: string): void;
|
|
||||||
triggerPotentialMigration(sourceCityName: string, chance: number): void;
|
|
||||||
randomEvent(): void;
|
|
||||||
getDiplomacyEffectiveness(player: IPlayer): number;
|
|
||||||
getRecruitmentSuccessChance(player: IPerson): number;
|
|
||||||
getRecruitmentTime(player: IPerson): number;
|
|
||||||
resetSkillMultipliers(): void;
|
|
||||||
updateSkillMultipliers(): void;
|
|
||||||
completeOperation(success: boolean, player: IPlayer): void;
|
|
||||||
getActionObject(actionId: IActionIdentifier): IAction | null;
|
|
||||||
completeContract(success: boolean, actionIdent: IActionIdentifier): void;
|
|
||||||
completeAction(player: IPlayer, person: IPerson, actionIdent: IActionIdentifier, isPlayer?: boolean): ITaskTracker;
|
|
||||||
infiltrateSynthoidCommunities(p: IPlayer): void;
|
|
||||||
changeRank(player: IPlayer, change: number): void;
|
|
||||||
processAction(router: IRouter, player: IPlayer, seconds: number): void;
|
|
||||||
calculateStaminaGainPerSecond(player: IPlayer): number;
|
|
||||||
calculateMaxStamina(player: IPlayer): void;
|
|
||||||
create(): void;
|
|
||||||
process(router: IRouter, player: IPlayer): void;
|
|
||||||
getActionStats(action: IAction, person: IPerson, success: boolean): ITaskTracker;
|
|
||||||
sleeveSupport(joining: boolean): void;
|
|
||||||
}
|
|
@ -1,4 +1,4 @@
|
|||||||
import { IBladeburner } from "./IBladeburner";
|
import { Bladeburner } from "./Bladeburner";
|
||||||
import { BladeburnerConstants } from "./data/Constants";
|
import { BladeburnerConstants } from "./data/Constants";
|
||||||
import { Action, IActionParams } from "./Action";
|
import { Action, IActionParams } from "./Action";
|
||||||
import { Generic_fromJSON, Generic_toJSON, IReviverValue, Reviver } from "../utils/JSONReviver";
|
import { Generic_fromJSON, Generic_toJSON, IReviverValue, Reviver } from "../utils/JSONReviver";
|
||||||
@ -19,7 +19,7 @@ export class Operation extends Action {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// For actions that have teams. To be implemented by subtypes.
|
// For actions that have teams. To be implemented by subtypes.
|
||||||
getTeamSuccessBonus(inst: IBladeburner): number {
|
getTeamSuccessBonus(inst: Bladeburner): number {
|
||||||
if (this.teamCount && this.teamCount > 0) {
|
if (this.teamCount && this.teamCount > 0) {
|
||||||
this.teamCount = Math.min(this.teamCount, inst.teamSize);
|
this.teamCount = Math.min(this.teamCount, inst.teamSize);
|
||||||
const teamMultiplier = Math.pow(this.teamCount, 0.05);
|
const teamMultiplier = Math.pow(this.teamCount, 0.05);
|
||||||
@ -29,11 +29,11 @@ export class Operation extends Action {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
getActionTypeSkillSuccessBonus(inst: IBladeburner): number {
|
getActionTypeSkillSuccessBonus(inst: Bladeburner): number {
|
||||||
return inst.skillMultipliers.successChanceOperation;
|
return inst.skillMultipliers.successChanceOperation;
|
||||||
}
|
}
|
||||||
|
|
||||||
getChaosDifficultyBonus(inst: IBladeburner /*, params: ISuccessChanceParams*/): number {
|
getChaosDifficultyBonus(inst: Bladeburner /*, params: ISuccessChanceParams*/): number {
|
||||||
const city = inst.getCurrentCity();
|
const city = inst.getCurrentCity();
|
||||||
if (city.chaos > BladeburnerConstants.ChaosThreshold) {
|
if (city.chaos > BladeburnerConstants.ChaosThreshold) {
|
||||||
const diff = 1 + (city.chaos - BladeburnerConstants.ChaosThreshold);
|
const diff = 1 + (city.chaos - BladeburnerConstants.ChaosThreshold);
|
||||||
|
@ -1,33 +1,5 @@
|
|||||||
import { CityName } from "./../../Locations/data/CityNames";
|
import { CityName } from "./../../Locations/data/CityNames";
|
||||||
export const BladeburnerConstants: {
|
export const BladeburnerConstants = {
|
||||||
CityNames: string[];
|
|
||||||
CyclesPerSecond: number;
|
|
||||||
StaminaGainPerSecond: number;
|
|
||||||
BaseStaminaLoss: number;
|
|
||||||
MaxStaminaToGainFactor: number;
|
|
||||||
DifficultyToTimeFactor: number;
|
|
||||||
DiffMultExponentialFactor: number;
|
|
||||||
DiffMultLinearFactor: number;
|
|
||||||
EffAgiLinearFactor: number;
|
|
||||||
EffDexLinearFactor: number;
|
|
||||||
EffAgiExponentialFactor: number;
|
|
||||||
EffDexExponentialFactor: number;
|
|
||||||
BaseRecruitmentTimeNeeded: number;
|
|
||||||
PopulationThreshold: number;
|
|
||||||
PopulationExponent: number;
|
|
||||||
ChaosThreshold: number;
|
|
||||||
BaseStatGain: number;
|
|
||||||
BaseIntGain: number;
|
|
||||||
ActionCountGrowthPeriod: number;
|
|
||||||
RankToFactionRepFactor: number;
|
|
||||||
RankNeededForFaction: number;
|
|
||||||
ContractSuccessesPerLevel: number;
|
|
||||||
OperationSuccessesPerLevel: number;
|
|
||||||
RanksPerSkillPoint: number;
|
|
||||||
ContractBaseMoneyGain: number;
|
|
||||||
HrcHpGain: number;
|
|
||||||
HrcStaminaGain: number;
|
|
||||||
} = {
|
|
||||||
CityNames: [
|
CityNames: [
|
||||||
CityName.Aevum,
|
CityName.Aevum,
|
||||||
CityName.Chongqing,
|
CityName.Chongqing,
|
||||||
|
@ -1,19 +1,4 @@
|
|||||||
export const SkillNames: {
|
export const SkillNames = {
|
||||||
BladesIntuition: string;
|
|
||||||
Cloak: string;
|
|
||||||
Marksman: string;
|
|
||||||
WeaponProficiency: string;
|
|
||||||
ShortCircuit: string;
|
|
||||||
DigitalObserver: string;
|
|
||||||
Tracer: string;
|
|
||||||
Overclock: string;
|
|
||||||
Reaper: string;
|
|
||||||
EvasiveSystem: string;
|
|
||||||
Datamancer: string;
|
|
||||||
CybersEdge: string;
|
|
||||||
HandsOfMidas: string;
|
|
||||||
Hyperdrive: string;
|
|
||||||
} = {
|
|
||||||
BladesIntuition: "Blade's Intuition",
|
BladesIntuition: "Blade's Intuition",
|
||||||
Cloak: "Cloak",
|
Cloak: "Cloak",
|
||||||
Marksman: "Marksman",
|
Marksman: "Marksman",
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import { IAction } from "../IAction";
|
import { Action } from "../Action";
|
||||||
import { IBladeburner } from "../IBladeburner";
|
import { Bladeburner } from "../Bladeburner";
|
||||||
import { BladeburnerConstants } from "../data/Constants";
|
import { BladeburnerConstants } from "../data/Constants";
|
||||||
import { use } from "../../ui/Context";
|
|
||||||
|
|
||||||
import Typography from "@mui/material/Typography";
|
import Typography from "@mui/material/Typography";
|
||||||
import Tooltip from "@mui/material/Tooltip";
|
import Tooltip from "@mui/material/Tooltip";
|
||||||
@ -12,29 +11,27 @@ import ArrowDropUpIcon from "@mui/icons-material/ArrowDropUp";
|
|||||||
import ArrowDropDownIcon from "@mui/icons-material/ArrowDropDown";
|
import ArrowDropDownIcon from "@mui/icons-material/ArrowDropDown";
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
action: IAction;
|
action: Action;
|
||||||
isActive: boolean;
|
isActive: boolean;
|
||||||
bladeburner: IBladeburner;
|
bladeburner: Bladeburner;
|
||||||
rerender: () => void;
|
rerender: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function ActionLevel({ action, isActive, bladeburner, rerender }: IProps): React.ReactElement {
|
export function ActionLevel({ action, isActive, bladeburner, rerender }: IProps): React.ReactElement {
|
||||||
const player = use.Player();
|
|
||||||
|
|
||||||
const canIncrease = action.level < action.maxLevel;
|
const canIncrease = action.level < action.maxLevel;
|
||||||
const canDecrease = action.level > 1;
|
const canDecrease = action.level > 1;
|
||||||
|
|
||||||
function increaseLevel(): void {
|
function increaseLevel(): void {
|
||||||
if (!canIncrease) return;
|
if (!canIncrease) return;
|
||||||
++action.level;
|
++action.level;
|
||||||
if (isActive) bladeburner.startAction(player, bladeburner.action);
|
if (isActive) bladeburner.startAction(bladeburner.action);
|
||||||
rerender();
|
rerender();
|
||||||
}
|
}
|
||||||
|
|
||||||
function decreaseLevel(): void {
|
function decreaseLevel(): void {
|
||||||
if (!canDecrease) return;
|
if (!canDecrease) return;
|
||||||
--action.level;
|
--action.level;
|
||||||
if (isActive) bladeburner.startAction(player, bladeburner.action);
|
if (isActive) bladeburner.startAction(bladeburner.action);
|
||||||
rerender();
|
rerender();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,16 +4,14 @@ import { ContractPage } from "./ContractPage";
|
|||||||
import { OperationPage } from "./OperationPage";
|
import { OperationPage } from "./OperationPage";
|
||||||
import { BlackOpPage } from "./BlackOpPage";
|
import { BlackOpPage } from "./BlackOpPage";
|
||||||
import { SkillPage } from "./SkillPage";
|
import { SkillPage } from "./SkillPage";
|
||||||
import { IBladeburner } from "../IBladeburner";
|
import { Bladeburner } from "../Bladeburner";
|
||||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
|
||||||
|
|
||||||
import Tabs from "@mui/material/Tabs";
|
import Tabs from "@mui/material/Tabs";
|
||||||
import Tab from "@mui/material/Tab";
|
import Tab from "@mui/material/Tab";
|
||||||
import Box from "@mui/material/Box";
|
import Box from "@mui/material/Box";
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
bladeburner: IBladeburner;
|
bladeburner: Bladeburner;
|
||||||
player: IPlayer;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function AllPages(props: IProps): React.ReactElement {
|
export function AllPages(props: IProps): React.ReactElement {
|
||||||
@ -33,10 +31,10 @@ export function AllPages(props: IProps): React.ReactElement {
|
|||||||
<Tab label="Skills" />
|
<Tab label="Skills" />
|
||||||
</Tabs>
|
</Tabs>
|
||||||
<Box sx={{ p: 1 }}>
|
<Box sx={{ p: 1 }}>
|
||||||
{value === 0 && <GeneralActionPage bladeburner={props.bladeburner} player={props.player} />}
|
{value === 0 && <GeneralActionPage bladeburner={props.bladeburner} />}
|
||||||
{value === 1 && <ContractPage bladeburner={props.bladeburner} player={props.player} />}
|
{value === 1 && <ContractPage bladeburner={props.bladeburner} />}
|
||||||
{value === 2 && <OperationPage bladeburner={props.bladeburner} player={props.player} />}
|
{value === 2 && <OperationPage bladeburner={props.bladeburner} />}
|
||||||
{value === 3 && <BlackOpPage bladeburner={props.bladeburner} player={props.player} />}
|
{value === 3 && <BlackOpPage bladeburner={props.bladeburner} />}
|
||||||
{value === 4 && <SkillPage bladeburner={props.bladeburner} />}
|
{value === 4 && <SkillPage bladeburner={props.bladeburner} />}
|
||||||
</Box>
|
</Box>
|
||||||
</>
|
</>
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import { IAction } from "../IAction";
|
import { Action } from "../Action";
|
||||||
import Typography from "@mui/material/Typography";
|
import Typography from "@mui/material/Typography";
|
||||||
import Tooltip from "@mui/material/Tooltip";
|
import Tooltip from "@mui/material/Tooltip";
|
||||||
import Box from "@mui/material/Box";
|
import Box from "@mui/material/Box";
|
||||||
import Switch from "@mui/material/Switch";
|
import Switch from "@mui/material/Switch";
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
action: IAction;
|
action: Action;
|
||||||
rerender: () => void;
|
rerender: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,10 +3,10 @@ import { formatNumber, convertTimeMsToTimeElapsedString } from "../../utils/Stri
|
|||||||
import { ActionTypes } from "../data/ActionTypes";
|
import { ActionTypes } from "../data/ActionTypes";
|
||||||
import { createProgressBarText } from "../../utils/helpers/createProgressBarText";
|
import { createProgressBarText } from "../../utils/helpers/createProgressBarText";
|
||||||
import { TeamSizeButton } from "./TeamSizeButton";
|
import { TeamSizeButton } from "./TeamSizeButton";
|
||||||
import { IBladeburner } from "../IBladeburner";
|
import { Bladeburner } from "../Bladeburner";
|
||||||
import { BlackOperation } from "../BlackOperation";
|
import { BlackOperation } from "../BlackOperation";
|
||||||
import { BlackOperations } from "../data/BlackOperations";
|
import { BlackOperations } from "../data/BlackOperations";
|
||||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
import { Player } from "../../Player";
|
||||||
import { CopyableText } from "../../ui/React/CopyableText";
|
import { CopyableText } from "../../ui/React/CopyableText";
|
||||||
import { SuccessChance } from "./SuccessChance";
|
import { SuccessChance } from "./SuccessChance";
|
||||||
import { StartButton } from "./StartButton";
|
import { StartButton } from "./StartButton";
|
||||||
@ -15,8 +15,7 @@ import Typography from "@mui/material/Typography";
|
|||||||
import Paper from "@mui/material/Paper";
|
import Paper from "@mui/material/Paper";
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
bladeburner: IBladeburner;
|
bladeburner: Bladeburner;
|
||||||
player: IPlayer;
|
|
||||||
action: BlackOperation;
|
action: BlackOperation;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -37,7 +36,7 @@ export function BlackOpElem(props: IProps): React.ReactElement {
|
|||||||
const isActive =
|
const isActive =
|
||||||
props.bladeburner.action.type === ActionTypes["BlackOperation"] &&
|
props.bladeburner.action.type === ActionTypes["BlackOperation"] &&
|
||||||
props.action.name === props.bladeburner.action.name;
|
props.action.name === props.bladeburner.action.name;
|
||||||
const actionTime = props.action.getActionTime(props.bladeburner, props.player);
|
const actionTime = props.action.getActionTime(props.bladeburner, Player);
|
||||||
const hasReqdRank = props.bladeburner.rank >= props.action.reqdRank;
|
const hasReqdRank = props.bladeburner.rank >= props.action.reqdRank;
|
||||||
const computedActionTimeCurrent = Math.min(
|
const computedActionTimeCurrent = Math.min(
|
||||||
props.bladeburner.actionTimeCurrent + props.bladeburner.actionTimeOverflow,
|
props.bladeburner.actionTimeCurrent + props.bladeburner.actionTimeOverflow,
|
||||||
|
@ -2,12 +2,10 @@ import React from "react";
|
|||||||
import { BlackOperations } from "../BlackOperations";
|
import { BlackOperations } from "../BlackOperations";
|
||||||
import { BlackOperation } from "../BlackOperation";
|
import { BlackOperation } from "../BlackOperation";
|
||||||
import { BlackOpElem } from "./BlackOpElem";
|
import { BlackOpElem } from "./BlackOpElem";
|
||||||
import { IBladeburner } from "../IBladeburner";
|
import { Bladeburner } from "../Bladeburner";
|
||||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
bladeburner: IBladeburner;
|
bladeburner: Bladeburner;
|
||||||
player: IPlayer;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function BlackOpList(props: IProps): React.ReactElement {
|
export function BlackOpList(props: IProps): React.ReactElement {
|
||||||
@ -35,7 +33,7 @@ export function BlackOpList(props: IProps): React.ReactElement {
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{blackops.map((blackop: BlackOperation) => (
|
{blackops.map((blackop: BlackOperation) => (
|
||||||
<BlackOpElem key={blackop.name} bladeburner={props.bladeburner} action={blackop} player={props.player} />
|
<BlackOpElem key={blackop.name} bladeburner={props.bladeburner} action={blackop} />
|
||||||
))}
|
))}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
@ -1,21 +1,18 @@
|
|||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import { BlackOpList } from "./BlackOpList";
|
import { BlackOpList } from "./BlackOpList";
|
||||||
import { IBladeburner } from "../IBladeburner";
|
import { Bladeburner } from "../Bladeburner";
|
||||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
|
||||||
import Typography from "@mui/material/Typography";
|
import Typography from "@mui/material/Typography";
|
||||||
import { FactionNames } from "../../Faction/data/FactionNames";
|
import { FactionNames } from "../../Faction/data/FactionNames";
|
||||||
import { use } from "../../ui/Context";
|
import { Router } from "../../ui/GameRoot";
|
||||||
import { BlackOperationNames } from "../data/BlackOperationNames";
|
import { BlackOperationNames } from "../data/BlackOperationNames";
|
||||||
import { Button } from "@mui/material";
|
import { Button } from "@mui/material";
|
||||||
import { CorruptableText } from "../../ui/React/CorruptableText";
|
import { CorruptableText } from "../../ui/React/CorruptableText";
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
bladeburner: IBladeburner;
|
bladeburner: Bladeburner;
|
||||||
player: IPlayer;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function BlackOpPage(props: IProps): React.ReactElement {
|
export function BlackOpPage(props: IProps): React.ReactElement {
|
||||||
const router = use.Router();
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Typography>
|
<Typography>
|
||||||
@ -33,11 +30,11 @@ export function BlackOpPage(props: IProps): React.ReactElement {
|
|||||||
losses.
|
losses.
|
||||||
</Typography>
|
</Typography>
|
||||||
{props.bladeburner.blackops[BlackOperationNames.OperationDaedalus] ? (
|
{props.bladeburner.blackops[BlackOperationNames.OperationDaedalus] ? (
|
||||||
<Button sx={{ my: 1, p: 1 }} onClick={() => router.toBitVerse(false, false)}>
|
<Button sx={{ my: 1, p: 1 }} onClick={() => Router.toBitVerse(false, false)}>
|
||||||
<CorruptableText content="Destroy w0rld_d34mon"></CorruptableText>
|
<CorruptableText content="Destroy w0rld_d34mon"></CorruptableText>
|
||||||
</Button>
|
</Button>
|
||||||
) : (
|
) : (
|
||||||
<BlackOpList bladeburner={props.bladeburner} player={props.player} />
|
<BlackOpList bladeburner={props.bladeburner} />
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
@ -1,11 +1,10 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import { FactionNames } from "../../Faction/data/FactionNames";
|
import { FactionNames } from "../../Faction/data/FactionNames";
|
||||||
import { use } from "../../ui/Context";
|
import { Router } from "../../ui/GameRoot";
|
||||||
import { CinematicText } from "../../ui/React/CinematicText";
|
import { CinematicText } from "../../ui/React/CinematicText";
|
||||||
import { dialogBoxCreate } from "../../ui/React/DialogBox";
|
import { dialogBoxCreate } from "../../ui/React/DialogBox";
|
||||||
|
|
||||||
export function BladeburnerCinematic(): React.ReactElement {
|
export function BladeburnerCinematic(): React.ReactElement {
|
||||||
const router = use.Router();
|
|
||||||
return (
|
return (
|
||||||
<CinematicText
|
<CinematicText
|
||||||
lines={[
|
lines={[
|
||||||
@ -32,7 +31,7 @@ export function BladeburnerCinematic(): React.ReactElement {
|
|||||||
"investigating and dealing with Synthoid threats.",
|
"investigating and dealing with Synthoid threats.",
|
||||||
]}
|
]}
|
||||||
onDone={() => {
|
onDone={() => {
|
||||||
router.toTerminal();
|
Router.toTerminal();
|
||||||
dialogBoxCreate(
|
dialogBoxCreate(
|
||||||
`Visit the National Security Agency (NSA) to apply for their ${FactionNames.Bladeburners} ` +
|
`Visit the National Security Agency (NSA) to apply for their ${FactionNames.Bladeburners} ` +
|
||||||
"division! You will need 100 of each combat stat before doing this.",
|
"division! You will need 100 of each combat stat before doing this.",
|
||||||
|
@ -3,12 +3,10 @@ import { Stats } from "./Stats";
|
|||||||
import { Console } from "./Console";
|
import { Console } from "./Console";
|
||||||
import { AllPages } from "./AllPages";
|
import { AllPages } from "./AllPages";
|
||||||
|
|
||||||
import { use } from "../../ui/Context";
|
import { Player } from "../../Player";
|
||||||
import Box from "@mui/material/Box";
|
import Box from "@mui/material/Box";
|
||||||
|
|
||||||
export function BladeburnerRoot(): React.ReactElement {
|
export function BladeburnerRoot(): React.ReactElement {
|
||||||
const player = use.Player();
|
|
||||||
const router = use.Router();
|
|
||||||
const setRerender = useState(false)[1];
|
const setRerender = useState(false)[1];
|
||||||
function rerender(): void {
|
function rerender(): void {
|
||||||
setRerender((old) => !old);
|
setRerender((old) => !old);
|
||||||
@ -19,16 +17,16 @@ export function BladeburnerRoot(): React.ReactElement {
|
|||||||
return () => clearInterval(id);
|
return () => clearInterval(id);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const bladeburner = player.bladeburner;
|
const bladeburner = Player.bladeburner;
|
||||||
if (bladeburner === null) return <></>;
|
if (!bladeburner) return <></>;
|
||||||
return (
|
return (
|
||||||
<Box display="flex" flexDirection="column">
|
<Box display="flex" flexDirection="column">
|
||||||
<Box sx={{ display: "grid", gridTemplateColumns: "4fr 8fr", p: 1 }}>
|
<Box sx={{ display: "grid", gridTemplateColumns: "4fr 8fr", p: 1 }}>
|
||||||
<Stats bladeburner={bladeburner} player={player} router={router} />
|
<Stats bladeburner={bladeburner} />
|
||||||
<Console bladeburner={bladeburner} player={player} />
|
<Console bladeburner={bladeburner} />
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
<AllPages bladeburner={bladeburner} player={player} />
|
<AllPages bladeburner={bladeburner} />
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
import React, { useState, useRef, useEffect } from "react";
|
import React, { useState, useRef, useEffect } from "react";
|
||||||
import { IBladeburner } from "../IBladeburner";
|
import { Bladeburner } from "../Bladeburner";
|
||||||
import { KEY } from "../../utils/helpers/keyCodes";
|
import { KEY } from "../../utils/helpers/keyCodes";
|
||||||
|
|
||||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
|
||||||
import Paper from "@mui/material/Paper";
|
import Paper from "@mui/material/Paper";
|
||||||
import List from "@mui/material/List";
|
import List from "@mui/material/List";
|
||||||
import ListItem from "@mui/material/ListItem";
|
import ListItem from "@mui/material/ListItem";
|
||||||
@ -49,8 +48,7 @@ function Line(props: ILineProps): React.ReactElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
bladeburner: IBladeburner;
|
bladeburner: Bladeburner;
|
||||||
player: IPlayer;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function Console(props: IProps): React.ReactElement {
|
export function Console(props: IProps): React.ReactElement {
|
||||||
@ -81,7 +79,7 @@ export function Console(props: IProps): React.ReactElement {
|
|||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
if (command.length > 0) {
|
if (command.length > 0) {
|
||||||
props.bladeburner.postToConsole("> " + command);
|
props.bladeburner.postToConsole("> " + command);
|
||||||
props.bladeburner.executeConsoleCommands(props.player, command);
|
props.bladeburner.executeConsoleCommands(command);
|
||||||
setConsoleHistoryIndex(props.bladeburner.consoleHistory.length);
|
setConsoleHistoryIndex(props.bladeburner.consoleHistory.length);
|
||||||
setCommand("");
|
setCommand("");
|
||||||
}
|
}
|
||||||
|
@ -3,9 +3,9 @@ import { ActionTypes } from "../data/ActionTypes";
|
|||||||
import { createProgressBarText } from "../../utils/helpers/createProgressBarText";
|
import { createProgressBarText } from "../../utils/helpers/createProgressBarText";
|
||||||
import { formatNumber, convertTimeMsToTimeElapsedString } from "../../utils/StringHelperFunctions";
|
import { formatNumber, convertTimeMsToTimeElapsedString } from "../../utils/StringHelperFunctions";
|
||||||
import { Contracts } from "../data/Contracts";
|
import { Contracts } from "../data/Contracts";
|
||||||
import { IBladeburner } from "../IBladeburner";
|
import { Bladeburner } from "../Bladeburner";
|
||||||
import { IAction } from "../IAction";
|
import { Action } from "../Action";
|
||||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
import { Player } from "../../Player";
|
||||||
import { SuccessChance } from "./SuccessChance";
|
import { SuccessChance } from "./SuccessChance";
|
||||||
import { CopyableText } from "../../ui/React/CopyableText";
|
import { CopyableText } from "../../ui/React/CopyableText";
|
||||||
import { ActionLevel } from "./ActionLevel";
|
import { ActionLevel } from "./ActionLevel";
|
||||||
@ -16,9 +16,8 @@ import Typography from "@mui/material/Typography";
|
|||||||
import Paper from "@mui/material/Paper";
|
import Paper from "@mui/material/Paper";
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
bladeburner: IBladeburner;
|
bladeburner: Bladeburner;
|
||||||
player: IPlayer;
|
action: Action;
|
||||||
action: IAction;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function ContractElem(props: IProps): React.ReactElement {
|
export function ContractElem(props: IProps): React.ReactElement {
|
||||||
@ -32,7 +31,7 @@ export function ContractElem(props: IProps): React.ReactElement {
|
|||||||
props.bladeburner.actionTimeCurrent + props.bladeburner.actionTimeOverflow,
|
props.bladeburner.actionTimeCurrent + props.bladeburner.actionTimeOverflow,
|
||||||
props.bladeburner.actionTimeToComplete,
|
props.bladeburner.actionTimeToComplete,
|
||||||
);
|
);
|
||||||
const actionTime = props.action.getActionTime(props.bladeburner, props.player);
|
const actionTime = props.action.getActionTime(props.bladeburner, Player);
|
||||||
|
|
||||||
const actionData = Contracts[props.action.name];
|
const actionData = Contracts[props.action.name];
|
||||||
if (actionData === undefined) {
|
if (actionData === undefined) {
|
||||||
|
@ -1,11 +1,9 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import { ContractElem } from "./ContractElem";
|
import { ContractElem } from "./ContractElem";
|
||||||
import { IBladeburner } from "../IBladeburner";
|
import { Bladeburner } from "../Bladeburner";
|
||||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
bladeburner: IBladeburner;
|
bladeburner: Bladeburner;
|
||||||
player: IPlayer;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function ContractList(props: IProps): React.ReactElement {
|
export function ContractList(props: IProps): React.ReactElement {
|
||||||
@ -14,7 +12,7 @@ export function ContractList(props: IProps): React.ReactElement {
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{names.map((name: string) => (
|
{names.map((name: string) => (
|
||||||
<ContractElem key={name} bladeburner={props.bladeburner} action={contracts[name]} player={props.player} />
|
<ContractElem key={name} bladeburner={props.bladeburner} action={contracts[name]} />
|
||||||
))}
|
))}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
@ -1,12 +1,10 @@
|
|||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import { ContractList } from "./ContractList";
|
import { ContractList } from "./ContractList";
|
||||||
import { IBladeburner } from "../IBladeburner";
|
import { Bladeburner } from "../Bladeburner";
|
||||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
|
||||||
import Typography from "@mui/material/Typography";
|
import Typography from "@mui/material/Typography";
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
bladeburner: IBladeburner;
|
bladeburner: Bladeburner;
|
||||||
player: IPlayer;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function ContractPage(props: IProps): React.ReactElement {
|
export function ContractPage(props: IProps): React.ReactElement {
|
||||||
@ -20,7 +18,7 @@ export function ContractPage(props: IProps): React.ReactElement {
|
|||||||
You can unlock higher-level contracts by successfully completing them. Higher-level contracts are more
|
You can unlock higher-level contracts by successfully completing them. Higher-level contracts are more
|
||||||
difficult, but grant more rank, experience, and money.
|
difficult, but grant more rank, experience, and money.
|
||||||
</Typography>
|
</Typography>
|
||||||
<ContractList bladeburner={props.bladeburner} player={props.player} />
|
<ContractList bladeburner={props.bladeburner} />
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -2,10 +2,10 @@ import React, { useState } from "react";
|
|||||||
import { ActionTypes } from "../data/ActionTypes";
|
import { ActionTypes } from "../data/ActionTypes";
|
||||||
import { createProgressBarText } from "../../utils/helpers/createProgressBarText";
|
import { createProgressBarText } from "../../utils/helpers/createProgressBarText";
|
||||||
import { formatNumber, convertTimeMsToTimeElapsedString } from "../../utils/StringHelperFunctions";
|
import { formatNumber, convertTimeMsToTimeElapsedString } from "../../utils/StringHelperFunctions";
|
||||||
import { IBladeburner } from "../IBladeburner";
|
import { Bladeburner } from "../Bladeburner";
|
||||||
import { IAction } from "../IAction";
|
import { Action } from "../Action";
|
||||||
import { GeneralActions } from "../data/GeneralActions";
|
import { GeneralActions } from "../data/GeneralActions";
|
||||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
import { Player } from "../../Player";
|
||||||
import { CopyableText } from "../../ui/React/CopyableText";
|
import { CopyableText } from "../../ui/React/CopyableText";
|
||||||
|
|
||||||
import { StartButton } from "./StartButton";
|
import { StartButton } from "./StartButton";
|
||||||
@ -15,9 +15,8 @@ import Box from "@mui/material/Box";
|
|||||||
import Paper from "@mui/material/Paper";
|
import Paper from "@mui/material/Paper";
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
bladeburner: IBladeburner;
|
bladeburner: Bladeburner;
|
||||||
player: IPlayer;
|
action: Action;
|
||||||
action: IAction;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function GeneralActionElem(props: IProps): React.ReactElement {
|
export function GeneralActionElem(props: IProps): React.ReactElement {
|
||||||
@ -40,13 +39,13 @@ export function GeneralActionElem(props: IProps): React.ReactElement {
|
|||||||
case "Incite Violence":
|
case "Incite Violence":
|
||||||
return 60;
|
return 60;
|
||||||
case "Recruitment":
|
case "Recruitment":
|
||||||
return props.bladeburner.getRecruitmentTime(props.player);
|
return props.bladeburner.getRecruitmentTime(Player);
|
||||||
}
|
}
|
||||||
return -1; // dead code
|
return -1; // dead code
|
||||||
})();
|
})();
|
||||||
const successChance =
|
const successChance =
|
||||||
props.action.name === "Recruitment"
|
props.action.name === "Recruitment"
|
||||||
? Math.max(0, Math.min(props.bladeburner.getRecruitmentSuccessChance(props.player), 1))
|
? Math.max(0, Math.min(props.bladeburner.getRecruitmentSuccessChance(Player), 1))
|
||||||
: -1;
|
: -1;
|
||||||
|
|
||||||
const actionData = GeneralActions[props.action.name];
|
const actionData = GeneralActions[props.action.name];
|
||||||
|
@ -2,12 +2,10 @@ import React from "react";
|
|||||||
import { GeneralActionElem } from "./GeneralActionElem";
|
import { GeneralActionElem } from "./GeneralActionElem";
|
||||||
import { Action } from "../Action";
|
import { Action } from "../Action";
|
||||||
import { GeneralActions } from "../GeneralActions";
|
import { GeneralActions } from "../GeneralActions";
|
||||||
import { IBladeburner } from "../IBladeburner";
|
import { Bladeburner } from "../Bladeburner";
|
||||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
bladeburner: IBladeburner;
|
bladeburner: Bladeburner;
|
||||||
player: IPlayer;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function GeneralActionList(props: IProps): React.ReactElement {
|
export function GeneralActionList(props: IProps): React.ReactElement {
|
||||||
@ -20,7 +18,7 @@ export function GeneralActionList(props: IProps): React.ReactElement {
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{actions.map((action: Action) => (
|
{actions.map((action: Action) => (
|
||||||
<GeneralActionElem key={action.name} bladeburner={props.bladeburner} action={action} player={props.player} />
|
<GeneralActionElem key={action.name} bladeburner={props.bladeburner} action={action} />
|
||||||
))}
|
))}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
@ -1,19 +1,17 @@
|
|||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import { GeneralActionList } from "./GeneralActionList";
|
import { GeneralActionList } from "./GeneralActionList";
|
||||||
import { IBladeburner } from "../IBladeburner";
|
import { Bladeburner } from "../Bladeburner";
|
||||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
|
||||||
import Typography from "@mui/material/Typography";
|
import Typography from "@mui/material/Typography";
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
bladeburner: IBladeburner;
|
bladeburner: Bladeburner;
|
||||||
player: IPlayer;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function GeneralActionPage(props: IProps): React.ReactElement {
|
export function GeneralActionPage(props: IProps): React.ReactElement {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Typography>These are generic actions that will assist you in your Bladeburner duties.</Typography>
|
<Typography>These are generic actions that will assist you in your Bladeburner duties.</Typography>
|
||||||
<GeneralActionList bladeburner={props.bladeburner} player={props.player} />
|
<GeneralActionList bladeburner={props.bladeburner} />
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -7,18 +7,17 @@ import { ActionLevel } from "./ActionLevel";
|
|||||||
import { Autolevel } from "./Autolevel";
|
import { Autolevel } from "./Autolevel";
|
||||||
import { StartButton } from "./StartButton";
|
import { StartButton } from "./StartButton";
|
||||||
import { TeamSizeButton } from "./TeamSizeButton";
|
import { TeamSizeButton } from "./TeamSizeButton";
|
||||||
import { IBladeburner } from "../IBladeburner";
|
import { Bladeburner } from "../Bladeburner";
|
||||||
import { Operation } from "../Operation";
|
import { Operation } from "../Operation";
|
||||||
import { Operations } from "../data/Operations";
|
import { Operations } from "../data/Operations";
|
||||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
import { Player } from "../../Player";
|
||||||
import { CopyableText } from "../../ui/React/CopyableText";
|
import { CopyableText } from "../../ui/React/CopyableText";
|
||||||
|
|
||||||
import Typography from "@mui/material/Typography";
|
import Typography from "@mui/material/Typography";
|
||||||
import Paper from "@mui/material/Paper";
|
import Paper from "@mui/material/Paper";
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
bladeburner: IBladeburner;
|
bladeburner: Bladeburner;
|
||||||
player: IPlayer;
|
|
||||||
action: Operation;
|
action: Operation;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -33,7 +32,7 @@ export function OperationElem(props: IProps): React.ReactElement {
|
|||||||
props.bladeburner.actionTimeCurrent + props.bladeburner.actionTimeOverflow,
|
props.bladeburner.actionTimeCurrent + props.bladeburner.actionTimeOverflow,
|
||||||
props.bladeburner.actionTimeToComplete,
|
props.bladeburner.actionTimeToComplete,
|
||||||
);
|
);
|
||||||
const actionTime = props.action.getActionTime(props.bladeburner, props.player);
|
const actionTime = props.action.getActionTime(props.bladeburner, Player);
|
||||||
|
|
||||||
const actionData = Operations[props.action.name];
|
const actionData = Operations[props.action.name];
|
||||||
if (actionData === undefined) {
|
if (actionData === undefined) {
|
||||||
|
@ -1,11 +1,9 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import { OperationElem } from "./OperationElem";
|
import { OperationElem } from "./OperationElem";
|
||||||
import { IBladeburner } from "../IBladeburner";
|
import { Bladeburner } from "../Bladeburner";
|
||||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
bladeburner: IBladeburner;
|
bladeburner: Bladeburner;
|
||||||
player: IPlayer;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function OperationList(props: IProps): React.ReactElement {
|
export function OperationList(props: IProps): React.ReactElement {
|
||||||
@ -14,7 +12,7 @@ export function OperationList(props: IProps): React.ReactElement {
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{names.map((name: string) => (
|
{names.map((name: string) => (
|
||||||
<OperationElem key={name} bladeburner={props.bladeburner} action={operations[name]} player={props.player} />
|
<OperationElem key={name} bladeburner={props.bladeburner} action={operations[name]} />
|
||||||
))}
|
))}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
@ -1,12 +1,10 @@
|
|||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import { OperationList } from "./OperationList";
|
import { OperationList } from "./OperationList";
|
||||||
import { IBladeburner } from "../IBladeburner";
|
import { Bladeburner } from "../Bladeburner";
|
||||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
|
||||||
import Typography from "@mui/material/Typography";
|
import Typography from "@mui/material/Typography";
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
bladeburner: IBladeburner;
|
bladeburner: Bladeburner;
|
||||||
player: IPlayer;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function OperationPage(props: IProps): React.ReactElement {
|
export function OperationPage(props: IProps): React.ReactElement {
|
||||||
@ -29,7 +27,7 @@ export function OperationPage(props: IProps): React.ReactElement {
|
|||||||
You can unlock higher-level operations by successfully completing them. Higher-level operations are more
|
You can unlock higher-level operations by successfully completing them. Higher-level operations are more
|
||||||
difficult, but grant more rank and experience.
|
difficult, but grant more rank and experience.
|
||||||
</Typography>
|
</Typography>
|
||||||
<OperationList bladeburner={props.bladeburner} player={props.player} />
|
<OperationList bladeburner={props.bladeburner} />
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import { CopyableText } from "../../ui/React/CopyableText";
|
import { CopyableText } from "../../ui/React/CopyableText";
|
||||||
import { formatNumber } from "../../utils/StringHelperFunctions";
|
import { formatNumber } from "../../utils/StringHelperFunctions";
|
||||||
import { IBladeburner } from "../IBladeburner";
|
import { Bladeburner } from "../Bladeburner";
|
||||||
|
|
||||||
import Typography from "@mui/material/Typography";
|
import Typography from "@mui/material/Typography";
|
||||||
import IconButton from "@mui/material/IconButton";
|
import IconButton from "@mui/material/IconButton";
|
||||||
@ -13,7 +13,7 @@ import { Skill } from "../Skill";
|
|||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
skill: Skill;
|
skill: Skill;
|
||||||
bladeburner: IBladeburner;
|
bladeburner: Bladeburner;
|
||||||
onUpgrade: () => void;
|
onUpgrade: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import { SkillElem } from "./SkillElem";
|
import { SkillElem } from "./SkillElem";
|
||||||
import { Skills } from "../Skills";
|
import { Skills } from "../Skills";
|
||||||
import { IBladeburner } from "../IBladeburner";
|
import { Bladeburner } from "../Bladeburner";
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
bladeburner: IBladeburner;
|
bladeburner: Bladeburner;
|
||||||
onUpgrade: () => void;
|
onUpgrade: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,10 +2,10 @@ import React, { useState } from "react";
|
|||||||
import { SkillList } from "./SkillList";
|
import { SkillList } from "./SkillList";
|
||||||
import { BladeburnerConstants } from "../data/Constants";
|
import { BladeburnerConstants } from "../data/Constants";
|
||||||
import { formatNumber } from "../../utils/StringHelperFunctions";
|
import { formatNumber } from "../../utils/StringHelperFunctions";
|
||||||
import { IBladeburner } from "../IBladeburner";
|
import { Bladeburner } from "../Bladeburner";
|
||||||
import Typography from "@mui/material/Typography";
|
import Typography from "@mui/material/Typography";
|
||||||
interface IProps {
|
interface IProps {
|
||||||
bladeburner: IBladeburner;
|
bladeburner: Bladeburner;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function SkillPage(props: IProps): React.ReactElement {
|
export function SkillPage(props: IProps): React.ReactElement {
|
||||||
|
@ -1,20 +1,20 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
|
|
||||||
import { IBladeburner } from "../IBladeburner";
|
import { Bladeburner } from "../Bladeburner";
|
||||||
import { BlackOperation } from "../BlackOperation";
|
import { BlackOperation } from "../BlackOperation";
|
||||||
import { use } from "../../ui/Context";
|
import { Player } from "../../Player";
|
||||||
import Button from "@mui/material/Button";
|
import Button from "@mui/material/Button";
|
||||||
import { AugmentationNames } from "../../Augmentation/data/AugmentationNames";
|
import { AugmentationNames } from "../../Augmentation/data/AugmentationNames";
|
||||||
|
import { ActionIdentifier } from "../ActionIdentifier";
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
bladeburner: IBladeburner;
|
bladeburner: Bladeburner;
|
||||||
type: number;
|
type: number;
|
||||||
name: string;
|
name: string;
|
||||||
rerender: () => void;
|
rerender: () => void;
|
||||||
}
|
}
|
||||||
export function StartButton(props: IProps): React.ReactElement {
|
export function StartButton(props: IProps): React.ReactElement {
|
||||||
const player = use.Player();
|
const action = props.bladeburner.getActionObject(new ActionIdentifier({ name: props.name, type: props.type }));
|
||||||
const action = props.bladeburner.getActionObject({ name: props.name, type: props.type });
|
|
||||||
if (action == null) {
|
if (action == null) {
|
||||||
throw new Error("Failed to get Operation Object for: " + props.name);
|
throw new Error("Failed to get Operation Object for: " + props.name);
|
||||||
}
|
}
|
||||||
@ -33,8 +33,8 @@ export function StartButton(props: IProps): React.ReactElement {
|
|||||||
if (disabled) return;
|
if (disabled) return;
|
||||||
props.bladeburner.action.type = props.type;
|
props.bladeburner.action.type = props.type;
|
||||||
props.bladeburner.action.name = props.name;
|
props.bladeburner.action.name = props.name;
|
||||||
if (!player.hasAugmentation(AugmentationNames.BladesSimulacrum, true)) player.finishWork(true);
|
if (!Player.hasAugmentation(AugmentationNames.BladesSimulacrum, true)) Player.finishWork(true);
|
||||||
props.bladeburner.startAction(player, props.bladeburner.action);
|
props.bladeburner.startAction(props.bladeburner.action);
|
||||||
props.rerender();
|
props.rerender();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
import React, { useState, useEffect } from "react";
|
import React, { useState, useEffect } from "react";
|
||||||
import { formatNumber, convertTimeMsToTimeElapsedString } from "../../utils/StringHelperFunctions";
|
import { formatNumber, convertTimeMsToTimeElapsedString } from "../../utils/StringHelperFunctions";
|
||||||
import { BladeburnerConstants } from "../data/Constants";
|
import { BladeburnerConstants } from "../data/Constants";
|
||||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
import { Player } from "../../Player";
|
||||||
import { Money } from "../../ui/React/Money";
|
import { Money } from "../../ui/React/Money";
|
||||||
import { numeralWrapper } from "../../ui/numeralFormat";
|
import { numeralWrapper } from "../../ui/numeralFormat";
|
||||||
import { Factions } from "../../Faction/Factions";
|
import { Factions } from "../../Faction/Factions";
|
||||||
import { IRouter } from "../../ui/Router";
|
import { Router } from "../../ui/GameRoot";
|
||||||
import { joinFaction } from "../../Faction/FactionHelpers";
|
import { joinFaction } from "../../Faction/FactionHelpers";
|
||||||
import { IBladeburner } from "../IBladeburner";
|
import { Bladeburner } from "../Bladeburner";
|
||||||
|
|
||||||
import { TravelModal } from "./TravelModal";
|
import { TravelModal } from "./TravelModal";
|
||||||
import Typography from "@mui/material/Typography";
|
import Typography from "@mui/material/Typography";
|
||||||
@ -18,9 +18,7 @@ import Paper from "@mui/material/Paper";
|
|||||||
import { FactionNames } from "../../Faction/data/FactionNames";
|
import { FactionNames } from "../../Faction/data/FactionNames";
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
bladeburner: IBladeburner;
|
bladeburner: Bladeburner;
|
||||||
router: IRouter;
|
|
||||||
player: IPlayer;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function Stats(props: IProps): React.ReactElement {
|
export function Stats(props: IProps): React.ReactElement {
|
||||||
@ -40,7 +38,7 @@ export function Stats(props: IProps): React.ReactElement {
|
|||||||
joinFaction(faction);
|
joinFaction(faction);
|
||||||
}
|
}
|
||||||
|
|
||||||
props.router.toFaction(faction);
|
Router.toFaction(faction);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -170,13 +168,13 @@ export function Stats(props: IProps): React.ReactElement {
|
|||||||
<Typography>Skill Points: {formatNumber(props.bladeburner.skillPoints, 0)}</Typography>
|
<Typography>Skill Points: {formatNumber(props.bladeburner.skillPoints, 0)}</Typography>
|
||||||
<br />
|
<br />
|
||||||
<Typography>
|
<Typography>
|
||||||
Aug. Success Chance mult: {formatNumber(props.player.mults.bladeburner_success_chance * 100, 1)}%
|
Aug. Success Chance mult: {formatNumber(Player.mults.bladeburner_success_chance * 100, 1)}%
|
||||||
<br />
|
<br />
|
||||||
Aug. Max Stamina mult: {formatNumber(props.player.mults.bladeburner_max_stamina * 100, 1)}%
|
Aug. Max Stamina mult: {formatNumber(Player.mults.bladeburner_max_stamina * 100, 1)}%
|
||||||
<br />
|
<br />
|
||||||
Aug. Stamina Gain mult: {formatNumber(props.player.mults.bladeburner_stamina_gain * 100, 1)}%
|
Aug. Stamina Gain mult: {formatNumber(Player.mults.bladeburner_stamina_gain * 100, 1)}%
|
||||||
<br />
|
<br />
|
||||||
Aug. Field Analysis mult: {formatNumber(props.player.mults.bladeburner_analysis * 100, 1)}%
|
Aug. Field Analysis mult: {formatNumber(Player.mults.bladeburner_analysis * 100, 1)}%
|
||||||
</Typography>
|
</Typography>
|
||||||
</Box>
|
</Box>
|
||||||
</Paper>
|
</Paper>
|
||||||
|
@ -2,13 +2,13 @@ import React from "react";
|
|||||||
import { formatNumber } from "../../utils/StringHelperFunctions";
|
import { formatNumber } from "../../utils/StringHelperFunctions";
|
||||||
import { StealthIcon } from "./StealthIcon";
|
import { StealthIcon } from "./StealthIcon";
|
||||||
import { KillIcon } from "./KillIcon";
|
import { KillIcon } from "./KillIcon";
|
||||||
import { IAction } from "../IAction";
|
import { Action } from "../Action";
|
||||||
import { IBladeburner } from "../IBladeburner";
|
import { Bladeburner } from "../Bladeburner";
|
||||||
import { Player } from "../../Player";
|
import { Player } from "../../Player";
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
bladeburner: IBladeburner;
|
bladeburner: Bladeburner;
|
||||||
action: IAction;
|
action: Action;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function SuccessChance(props: IProps): React.ReactElement {
|
export function SuccessChance(props: IProps): React.ReactElement {
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
import React, { useState } from "react";
|
import React, { useState } from "react";
|
||||||
import { Operation } from "../Operation";
|
import { Operation } from "../Operation";
|
||||||
import { IBladeburner } from "../IBladeburner";
|
import { Bladeburner } from "../Bladeburner";
|
||||||
import { TeamSizeModal } from "./TeamSizeModal";
|
import { TeamSizeModal } from "./TeamSizeModal";
|
||||||
import { formatNumber } from "../../utils/StringHelperFunctions";
|
import { formatNumber } from "../../utils/StringHelperFunctions";
|
||||||
import Button from "@mui/material/Button";
|
import Button from "@mui/material/Button";
|
||||||
interface IProps {
|
interface IProps {
|
||||||
action: Operation;
|
action: Operation;
|
||||||
bladeburner: IBladeburner;
|
bladeburner: Bladeburner;
|
||||||
}
|
}
|
||||||
export function TeamSizeButton(props: IProps): React.ReactElement {
|
export function TeamSizeButton(props: IProps): React.ReactElement {
|
||||||
const [open, setOpen] = useState(false);
|
const [open, setOpen] = useState(false);
|
||||||
|
@ -2,13 +2,13 @@ import React, { useState } from "react";
|
|||||||
import { dialogBoxCreate } from "../../ui/React/DialogBox";
|
import { dialogBoxCreate } from "../../ui/React/DialogBox";
|
||||||
import { Modal } from "../../ui/React/Modal";
|
import { Modal } from "../../ui/React/Modal";
|
||||||
import { Action } from "../Action";
|
import { Action } from "../Action";
|
||||||
import { IBladeburner } from "../IBladeburner";
|
import { Bladeburner } from "../Bladeburner";
|
||||||
import Typography from "@mui/material/Typography";
|
import Typography from "@mui/material/Typography";
|
||||||
import Button from "@mui/material/Button";
|
import Button from "@mui/material/Button";
|
||||||
import TextField from "@mui/material/TextField";
|
import TextField from "@mui/material/TextField";
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
bladeburner: IBladeburner;
|
bladeburner: Bladeburner;
|
||||||
action: Action;
|
action: Action;
|
||||||
open: boolean;
|
open: boolean;
|
||||||
onClose: () => void;
|
onClose: () => void;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import { IBladeburner } from "../IBladeburner";
|
import { Bladeburner } from "../Bladeburner";
|
||||||
import { WorldMap } from "../../ui/React/WorldMap";
|
import { WorldMap } from "../../ui/React/WorldMap";
|
||||||
import { Modal } from "../../ui/React/Modal";
|
import { Modal } from "../../ui/React/Modal";
|
||||||
import { CityName } from "../../Locations/data/CityNames";
|
import { CityName } from "../../Locations/data/CityNames";
|
||||||
@ -8,7 +8,7 @@ import Typography from "@mui/material/Typography";
|
|||||||
import Button from "@mui/material/Button";
|
import Button from "@mui/material/Button";
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
bladeburner: IBladeburner;
|
bladeburner: Bladeburner;
|
||||||
open: boolean;
|
open: boolean;
|
||||||
onClose: () => void;
|
onClose: () => void;
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
|
|
||||||
import { IPlayer } from "../PersonObjects/IPlayer";
|
import { Player } from "../Player";
|
||||||
import { Money } from "../ui/React/Money";
|
import { Money } from "../ui/React/Money";
|
||||||
import { Game, reachedLimit } from "./Game";
|
import { win, reachedLimit } from "./Game";
|
||||||
import { Deck } from "./CardDeck/Deck";
|
import { Deck } from "./CardDeck/Deck";
|
||||||
import { Hand } from "./CardDeck/Hand";
|
import { Hand } from "./CardDeck/Hand";
|
||||||
import { InputAdornment } from "@mui/material";
|
import { InputAdornment } from "@mui/material";
|
||||||
@ -24,10 +24,6 @@ enum Result {
|
|||||||
Tie = "Push! (Tie)",
|
Tie = "Push! (Tie)",
|
||||||
}
|
}
|
||||||
|
|
||||||
type Props = {
|
|
||||||
p: IPlayer;
|
|
||||||
};
|
|
||||||
|
|
||||||
type State = {
|
type State = {
|
||||||
playerHand: Hand;
|
playerHand: Hand;
|
||||||
dealerHand: Hand;
|
dealerHand: Hand;
|
||||||
@ -40,11 +36,11 @@ type State = {
|
|||||||
wagerInvalidHelperText: string;
|
wagerInvalidHelperText: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export class Blackjack extends Game<Props, State> {
|
export class Blackjack extends React.Component<Record<string, never>, State> {
|
||||||
deck: Deck;
|
deck: Deck;
|
||||||
|
|
||||||
constructor(props: Props) {
|
constructor() {
|
||||||
super(props);
|
super({});
|
||||||
|
|
||||||
this.deck = new Deck(DECK_COUNT);
|
this.deck = new Deck(DECK_COUNT);
|
||||||
|
|
||||||
@ -64,20 +60,19 @@ export class Blackjack extends Game<Props, State> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
canStartGame = (): boolean => {
|
canStartGame = (): boolean => {
|
||||||
const { p } = this.props;
|
|
||||||
const { bet } = this.state;
|
const { bet } = this.state;
|
||||||
|
|
||||||
return p.canAfford(bet);
|
return Player.canAfford(bet);
|
||||||
};
|
};
|
||||||
|
|
||||||
startGame = (): void => {
|
startGame = (): void => {
|
||||||
if (!this.canStartGame() || reachedLimit(this.props.p)) {
|
if (!this.canStartGame() || reachedLimit()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Take money from player right away so that player's dont just "leave" to avoid the loss (I mean they could
|
// Take money from player right away so that player's dont just "leave" to avoid the loss (I mean they could
|
||||||
// always reload without saving but w.e) TODO: Save/Restore the RNG state to limit the value of save-scumming.
|
// always reload without saving but w.e) TODO: Save/Restore the RNG state to limit the value of save-scumming.
|
||||||
this.props.p.loseMoney(this.state.bet, "casino");
|
win(-this.state.bet);
|
||||||
|
|
||||||
const playerHand = new Hand([this.deck.safeDrawCard(), this.deck.safeDrawCard()]);
|
const playerHand = new Hand([this.deck.safeDrawCard(), this.deck.safeDrawCard()]);
|
||||||
const dealerHand = new Hand([this.deck.safeDrawCard(), this.deck.safeDrawCard()]);
|
const dealerHand = new Hand([this.deck.safeDrawCard(), this.deck.safeDrawCard()]);
|
||||||
@ -230,7 +225,7 @@ export class Blackjack extends Game<Props, State> {
|
|||||||
: (() => {
|
: (() => {
|
||||||
throw new Error(`Unexpected result: ${result}`);
|
throw new Error(`Unexpected result: ${result}`);
|
||||||
})(); // This can't happen, right?
|
})(); // This can't happen, right?
|
||||||
this.win(this.props.p, gains);
|
win(gains);
|
||||||
this.setState({
|
this.setState({
|
||||||
gameInProgress: false,
|
gameInProgress: false,
|
||||||
result,
|
result,
|
||||||
@ -239,7 +234,6 @@ export class Blackjack extends Game<Props, State> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
wagerOnChange = (event: React.ChangeEvent<HTMLInputElement>): void => {
|
wagerOnChange = (event: React.ChangeEvent<HTMLInputElement>): void => {
|
||||||
const { p } = this.props;
|
|
||||||
const betInput = event.target.value;
|
const betInput = event.target.value;
|
||||||
const wager = Math.round(parseFloat(betInput));
|
const wager = Math.round(parseFloat(betInput));
|
||||||
if (isNaN(wager)) {
|
if (isNaN(wager)) {
|
||||||
@ -263,7 +257,7 @@ export class Blackjack extends Game<Props, State> {
|
|||||||
wagerInvalid: true,
|
wagerInvalid: true,
|
||||||
wagerInvalidHelperText: "Exceeds max bet",
|
wagerInvalidHelperText: "Exceeds max bet",
|
||||||
});
|
});
|
||||||
} else if (!p.canAfford(wager)) {
|
} else if (!Player.canAfford(wager)) {
|
||||||
this.setState({
|
this.setState({
|
||||||
bet: 0,
|
bet: 0,
|
||||||
betInput,
|
betInput,
|
||||||
|
@ -5,7 +5,6 @@
|
|||||||
*/
|
*/
|
||||||
import React, { useState } from "react";
|
import React, { useState } from "react";
|
||||||
|
|
||||||
import { IPlayer } from "../PersonObjects/IPlayer";
|
|
||||||
import { BadRNG } from "./RNG";
|
import { BadRNG } from "./RNG";
|
||||||
import { win, reachedLimit } from "./Game";
|
import { win, reachedLimit } from "./Game";
|
||||||
import { trusted } from "./utils";
|
import { trusted } from "./utils";
|
||||||
@ -15,14 +14,10 @@ import TextField from "@mui/material/TextField";
|
|||||||
import Button from "@mui/material/Button";
|
import Button from "@mui/material/Button";
|
||||||
import Box from "@mui/material/Box";
|
import Box from "@mui/material/Box";
|
||||||
|
|
||||||
type IProps = {
|
|
||||||
p: IPlayer;
|
|
||||||
};
|
|
||||||
|
|
||||||
const minPlay = 0;
|
const minPlay = 0;
|
||||||
const maxPlay = 10e3;
|
const maxPlay = 10e3;
|
||||||
|
|
||||||
export function CoinFlip(props: IProps): React.ReactElement {
|
export function CoinFlip(): React.ReactElement {
|
||||||
const [investment, setInvestment] = useState(1000);
|
const [investment, setInvestment] = useState(1000);
|
||||||
const [result, setResult] = useState(<span> </span>);
|
const [result, setResult] = useState(<span> </span>);
|
||||||
const [status, setStatus] = useState("");
|
const [status, setStatus] = useState("");
|
||||||
@ -43,7 +38,7 @@ export function CoinFlip(props: IProps): React.ReactElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function play(guess: string): void {
|
function play(guess: string): void {
|
||||||
if (reachedLimit(props.p)) return;
|
if (reachedLimit()) return;
|
||||||
const v = BadRNG.random();
|
const v = BadRNG.random();
|
||||||
let letter: string;
|
let letter: string;
|
||||||
if (v < 0.5) {
|
if (v < 0.5) {
|
||||||
@ -65,11 +60,11 @@ export function CoinFlip(props: IProps): React.ReactElement {
|
|||||||
|
|
||||||
setTimeout(() => setPlayLock(false), 250);
|
setTimeout(() => setPlayLock(false), 250);
|
||||||
if (correct) {
|
if (correct) {
|
||||||
win(props.p, investment);
|
win(investment);
|
||||||
} else {
|
} else {
|
||||||
win(props.p, -investment);
|
win(-investment);
|
||||||
}
|
}
|
||||||
if (reachedLimit(props.p)) return;
|
if (reachedLimit()) return;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
16
src/Casino/Game.ts
Normal file
16
src/Casino/Game.ts
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
import { Player } from "../Player";
|
||||||
|
import { dialogBoxCreate } from "../ui/React/DialogBox";
|
||||||
|
|
||||||
|
const gainLimit = 10e9;
|
||||||
|
|
||||||
|
export function win(n: number): void {
|
||||||
|
Player.gainMoney(n, "casino");
|
||||||
|
}
|
||||||
|
|
||||||
|
export function reachedLimit(): boolean {
|
||||||
|
const reached = Player.getCasinoWinnings() > gainLimit;
|
||||||
|
if (reached) {
|
||||||
|
dialogBoxCreate("Alright cheater get out of here. You're not allowed here anymore.");
|
||||||
|
}
|
||||||
|
return reached;
|
||||||
|
}
|
@ -1,31 +0,0 @@
|
|||||||
import * as React from "react";
|
|
||||||
import { IPlayer } from "../PersonObjects/IPlayer";
|
|
||||||
import { dialogBoxCreate } from "../ui/React/DialogBox";
|
|
||||||
|
|
||||||
const gainLimit = 10e9;
|
|
||||||
|
|
||||||
export function win(p: IPlayer, n: number): void {
|
|
||||||
p.gainMoney(n, "casino");
|
|
||||||
}
|
|
||||||
|
|
||||||
export function reachedLimit(p: IPlayer): boolean {
|
|
||||||
const reached = p.getCasinoWinnings() > gainLimit;
|
|
||||||
if (reached) {
|
|
||||||
dialogBoxCreate(<>Alright cheater get out of here. You're not allowed here anymore.</>);
|
|
||||||
}
|
|
||||||
return reached;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class Game<T, U> extends React.Component<T, U> {
|
|
||||||
win(p: IPlayer, n: number): void {
|
|
||||||
p.gainMoney(n, "casino");
|
|
||||||
}
|
|
||||||
|
|
||||||
reachedLimit(p: IPlayer): boolean {
|
|
||||||
const reached = p.getCasinoWinnings() > gainLimit;
|
|
||||||
if (reached) {
|
|
||||||
dialogBoxCreate(<>Alright cheater get out of here. You're not allowed here anymore.</>);
|
|
||||||
}
|
|
||||||
return reached;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,6 +1,5 @@
|
|||||||
import React, { useState, useEffect } from "react";
|
import React, { useState, useEffect } from "react";
|
||||||
|
|
||||||
import { IPlayer } from "../PersonObjects/IPlayer";
|
|
||||||
import { Money } from "../ui/React/Money";
|
import { Money } from "../ui/React/Money";
|
||||||
import { win, reachedLimit } from "./Game";
|
import { win, reachedLimit } from "./Game";
|
||||||
import { WHRNG } from "./RNG";
|
import { WHRNG } from "./RNG";
|
||||||
@ -9,10 +8,6 @@ import Typography from "@mui/material/Typography";
|
|||||||
import Button from "@mui/material/Button";
|
import Button from "@mui/material/Button";
|
||||||
import TextField from "@mui/material/TextField";
|
import TextField from "@mui/material/TextField";
|
||||||
|
|
||||||
type IProps = {
|
|
||||||
p: IPlayer;
|
|
||||||
};
|
|
||||||
|
|
||||||
const minPlay = 0;
|
const minPlay = 0;
|
||||||
const maxPlay = 1e7;
|
const maxPlay = 1e7;
|
||||||
|
|
||||||
@ -111,7 +106,7 @@ function Single(s: number): Strategy {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function Roulette(props: IProps): React.ReactElement {
|
export function Roulette(): React.ReactElement {
|
||||||
const [rng] = useState(new WHRNG(new Date().getTime()));
|
const [rng] = useState(new WHRNG(new Date().getTime()));
|
||||||
const [investment, setInvestment] = useState(1000);
|
const [investment, setInvestment] = useState(1000);
|
||||||
const [canPlay, setCanPlay] = useState(true);
|
const [canPlay, setCanPlay] = useState(true);
|
||||||
@ -151,7 +146,7 @@ export function Roulette(props: IProps): React.ReactElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function play(strategy: Strategy): void {
|
function play(strategy: Strategy): void {
|
||||||
if (reachedLimit(props.p)) return;
|
if (reachedLimit()) return;
|
||||||
|
|
||||||
setCanPlay(false);
|
setCanPlay(false);
|
||||||
setLock(false);
|
setLock(false);
|
||||||
@ -184,14 +179,14 @@ export function Roulette(props: IProps): React.ReactElement {
|
|||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
win(props.p, gain);
|
win(gain);
|
||||||
|
|
||||||
setCanPlay(true);
|
setCanPlay(true);
|
||||||
setLock(true);
|
setLock(true);
|
||||||
setStatus(status);
|
setStatus(status);
|
||||||
setN(n);
|
setN(n);
|
||||||
|
|
||||||
reachedLimit(props.p);
|
reachedLimit();
|
||||||
}, 1600);
|
}, 1600);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import React, { useState, useEffect } from "react";
|
import React, { useState, useEffect } from "react";
|
||||||
|
|
||||||
import { IPlayer } from "../PersonObjects/IPlayer";
|
import { Player } from "../Player";
|
||||||
import { Money } from "../ui/React/Money";
|
import { Money } from "../ui/React/Money";
|
||||||
import { WHRNG } from "./RNG";
|
import { WHRNG } from "./RNG";
|
||||||
import { win, reachedLimit } from "./Game";
|
import { win, reachedLimit } from "./Game";
|
||||||
@ -9,10 +9,6 @@ import Typography from "@mui/material/Typography";
|
|||||||
import TextField from "@mui/material/TextField";
|
import TextField from "@mui/material/TextField";
|
||||||
import Button from "@mui/material/Button";
|
import Button from "@mui/material/Button";
|
||||||
|
|
||||||
type IProps = {
|
|
||||||
p: IPlayer;
|
|
||||||
};
|
|
||||||
|
|
||||||
// statically shuffled array of symbols.
|
// statically shuffled array of symbols.
|
||||||
const symbols = [
|
const symbols = [
|
||||||
"D",
|
"D",
|
||||||
@ -141,8 +137,8 @@ const payLines = [
|
|||||||
const minPlay = 0;
|
const minPlay = 0;
|
||||||
const maxPlay = 1e6;
|
const maxPlay = 1e6;
|
||||||
|
|
||||||
export function SlotMachine(props: IProps): React.ReactElement {
|
export function SlotMachine(): React.ReactElement {
|
||||||
const [rng] = useState(new WHRNG(props.p.totalPlaytime));
|
const [rng] = useState(new WHRNG(Player.totalPlaytime));
|
||||||
const [index, setIndex] = useState<number[]>([0, 0, 0, 0, 0]);
|
const [index, setIndex] = useState<number[]>([0, 0, 0, 0, 0]);
|
||||||
const [locks, setLocks] = useState<number[]>([0, 0, 0, 0, 0]);
|
const [locks, setLocks] = useState<number[]>([0, 0, 0, 0, 0]);
|
||||||
const [investment, setInvestment] = useState(1000);
|
const [investment, setInvestment] = useState(1000);
|
||||||
@ -191,9 +187,9 @@ export function SlotMachine(props: IProps): React.ReactElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function play(): void {
|
function play(): void {
|
||||||
if (reachedLimit(props.p)) return;
|
if (reachedLimit()) return;
|
||||||
setStatus("playing");
|
setStatus("playing");
|
||||||
win(props.p, -investment);
|
win(-investment);
|
||||||
if (!canPlay) return;
|
if (!canPlay) return;
|
||||||
unlock();
|
unlock();
|
||||||
setTimeout(lock, rng.random() * 2000 + 1000);
|
setTimeout(lock, rng.random() * 2000 + 1000);
|
||||||
@ -235,7 +231,7 @@ export function SlotMachine(props: IProps): React.ReactElement {
|
|||||||
if (count < 3) continue;
|
if (count < 3) continue;
|
||||||
const payout = getPayout(data[0], count - 3);
|
const payout = getPayout(data[0], count - 3);
|
||||||
gains += investment * payout;
|
gains += investment * payout;
|
||||||
win(props.p, investment * payout);
|
win(investment * payout);
|
||||||
}
|
}
|
||||||
|
|
||||||
setStatus(
|
setStatus(
|
||||||
@ -244,7 +240,7 @@ export function SlotMachine(props: IProps): React.ReactElement {
|
|||||||
</>,
|
</>,
|
||||||
);
|
);
|
||||||
setCanPlay(true);
|
setCanPlay(true);
|
||||||
if (reachedLimit(props.p)) return;
|
if (reachedLimit()) return;
|
||||||
}
|
}
|
||||||
|
|
||||||
function unlock(): void {
|
function unlock(): void {
|
||||||
|
@ -191,7 +191,8 @@ function getRandomFilename(server: BaseServer, reward: ICodingContractReward): s
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (reward.name) {
|
if (reward.name) {
|
||||||
contractFn += `-${reward.name.replace(/\s/g, "")}`;
|
// Only alphanumeric characters in the reward name.
|
||||||
|
contractFn += `-${reward.name.replace(/[^a-zA-Z0-9]/g, "")}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
return contractFn;
|
return contractFn;
|
||||||
|
@ -29,7 +29,7 @@ export function initCompanies(): void {
|
|||||||
for (const companyName of Object.keys(Companies)) {
|
for (const companyName of Object.keys(Companies)) {
|
||||||
const company = Companies[companyName];
|
const company = Companies[companyName];
|
||||||
const oldCompany = oldCompanies[companyName];
|
const oldCompany = oldCompanies[companyName];
|
||||||
if (!(oldCompany instanceof Company)) {
|
if (!oldCompany) {
|
||||||
// New game, so no OldCompanies data
|
// New game, so no OldCompanies data
|
||||||
company.favor = 0;
|
company.favor = 0;
|
||||||
} else {
|
} else {
|
||||||
|
@ -88,11 +88,7 @@ export class Company {
|
|||||||
}
|
}
|
||||||
|
|
||||||
hasPosition(pos: CompanyPosition | string): boolean {
|
hasPosition(pos: CompanyPosition | string): boolean {
|
||||||
if (pos instanceof CompanyPosition) {
|
return this.companyPositions[typeof pos === "string" ? pos : pos.name] != null;
|
||||||
return this.companyPositions[pos.name] != null;
|
|
||||||
} else {
|
|
||||||
return this.companyPositions[pos] != null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
hasAgentPositions(): boolean {
|
hasAgentPositions(): boolean {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import { Company } from "../Company";
|
import { Company } from "../Company";
|
||||||
import { use } from "../../ui/Context";
|
import { Player } from "../../Player";
|
||||||
import { Modal } from "../../ui/React/Modal";
|
import { Modal } from "../../ui/React/Modal";
|
||||||
import Typography from "@mui/material/Typography";
|
import Typography from "@mui/material/Typography";
|
||||||
import Button from "@mui/material/Button";
|
import Button from "@mui/material/Button";
|
||||||
@ -14,9 +14,8 @@ interface IProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function QuitJobModal(props: IProps): React.ReactElement {
|
export function QuitJobModal(props: IProps): React.ReactElement {
|
||||||
const player = use.Player();
|
|
||||||
function quit(): void {
|
function quit(): void {
|
||||||
player.quitJob(props.locName);
|
Player.quitJob(props.locName);
|
||||||
props.onQuit();
|
props.onQuit();
|
||||||
props.onClose();
|
props.onClose();
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,6 @@
|
|||||||
import { Player } from "../Player";
|
import { Player } from "../Player";
|
||||||
import { IPlayer } from "src/PersonObjects/IPlayer";
|
|
||||||
import { MaterialSizes } from "./MaterialSizes";
|
import { MaterialSizes } from "./MaterialSizes";
|
||||||
import { ICorporation } from "./ICorporation";
|
|
||||||
import { Corporation } from "./Corporation";
|
import { Corporation } from "./Corporation";
|
||||||
import { IIndustry } from "./IIndustry";
|
|
||||||
import { IndustryStartingCosts, IndustryResearchTrees } from "./IndustryData";
|
import { IndustryStartingCosts, IndustryResearchTrees } from "./IndustryData";
|
||||||
import { Industry } from "./Industry";
|
import { Industry } from "./Industry";
|
||||||
import { CorporationConstants } from "./data/Constants";
|
import { CorporationConstants } from "./data/Constants";
|
||||||
@ -18,7 +15,7 @@ import { EmployeePositions } from "./EmployeePositions";
|
|||||||
import { ResearchMap } from "./ResearchMap";
|
import { ResearchMap } from "./ResearchMap";
|
||||||
import { isRelevantMaterial } from "./ui/Helpers";
|
import { isRelevantMaterial } from "./ui/Helpers";
|
||||||
|
|
||||||
export function NewIndustry(corporation: ICorporation, industry: string, name: string): void {
|
export function NewIndustry(corporation: Corporation, industry: string, name: string): void {
|
||||||
if (corporation.divisions.find(({ type }) => industry == type))
|
if (corporation.divisions.find(({ type }) => industry == type))
|
||||||
throw new Error(`You have already expanded into the ${industry} industry!`);
|
throw new Error(`You have already expanded into the ${industry} industry!`);
|
||||||
|
|
||||||
@ -48,7 +45,7 @@ export function NewIndustry(corporation: ICorporation, industry: string, name: s
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function NewCity(corporation: ICorporation, division: IIndustry, city: string): void {
|
export function NewCity(corporation: Corporation, division: Industry, city: string): void {
|
||||||
if (corporation.funds < CorporationConstants.OfficeInitialCost) {
|
if (corporation.funds < CorporationConstants.OfficeInitialCost) {
|
||||||
throw new Error("You don't have enough company funds to open a new office!");
|
throw new Error("You don't have enough company funds to open a new office!");
|
||||||
}
|
}
|
||||||
@ -62,7 +59,7 @@ export function NewCity(corporation: ICorporation, division: IIndustry, city: st
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function UnlockUpgrade(corporation: ICorporation, upgrade: CorporationUnlockUpgrade): void {
|
export function UnlockUpgrade(corporation: Corporation, upgrade: CorporationUnlockUpgrade): void {
|
||||||
if (corporation.funds < upgrade.price) {
|
if (corporation.funds < upgrade.price) {
|
||||||
throw new Error("Insufficient funds");
|
throw new Error("Insufficient funds");
|
||||||
}
|
}
|
||||||
@ -72,7 +69,7 @@ export function UnlockUpgrade(corporation: ICorporation, upgrade: CorporationUnl
|
|||||||
corporation.unlock(upgrade);
|
corporation.unlock(upgrade);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function LevelUpgrade(corporation: ICorporation, upgrade: CorporationUpgrade): void {
|
export function LevelUpgrade(corporation: Corporation, upgrade: CorporationUpgrade): void {
|
||||||
const baseCost = upgrade.basePrice;
|
const baseCost = upgrade.basePrice;
|
||||||
const priceMult = upgrade.priceMult;
|
const priceMult = upgrade.priceMult;
|
||||||
const level = corporation.upgrades[upgrade.index];
|
const level = corporation.upgrades[upgrade.index];
|
||||||
@ -84,7 +81,7 @@ export function LevelUpgrade(corporation: ICorporation, upgrade: CorporationUpgr
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function IssueDividends(corporation: ICorporation, rate: number): void {
|
export function IssueDividends(corporation: Corporation, rate: number): void {
|
||||||
if (isNaN(rate) || rate < 0 || rate > CorporationConstants.DividendMaxRate) {
|
if (isNaN(rate) || rate < 0 || rate > CorporationConstants.DividendMaxRate) {
|
||||||
throw new Error(`Invalid value. Must be an number between 0 and ${CorporationConstants.DividendMaxRate}`);
|
throw new Error(`Invalid value. Must be an number between 0 and ${CorporationConstants.DividendMaxRate}`);
|
||||||
}
|
}
|
||||||
@ -253,7 +250,7 @@ export function BuyMaterial(material: Material, amt: number): void {
|
|||||||
material.buy = amt;
|
material.buy = amt;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function BulkPurchase(corp: ICorporation, warehouse: Warehouse, material: Material, amt: number): void {
|
export function BulkPurchase(corp: Corporation, warehouse: Warehouse, material: Material, amt: number): void {
|
||||||
const matSize = MaterialSizes[material.name];
|
const matSize = MaterialSizes[material.name];
|
||||||
const maxAmount = (warehouse.size - warehouse.sizeUsed) / matSize;
|
const maxAmount = (warehouse.size - warehouse.sizeUsed) / matSize;
|
||||||
if (isNaN(amt) || amt < 0) {
|
if (isNaN(amt) || amt < 0) {
|
||||||
@ -271,7 +268,7 @@ export function BulkPurchase(corp: ICorporation, warehouse: Warehouse, material:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function SellShares(corporation: ICorporation, player: IPlayer, numShares: number): number {
|
export function SellShares(corporation: Corporation, numShares: number): number {
|
||||||
if (isNaN(numShares)) throw new Error("Invalid value for number of shares");
|
if (isNaN(numShares)) throw new Error("Invalid value for number of shares");
|
||||||
if (numShares < 0) throw new Error("Invalid value for number of shares");
|
if (numShares < 0) throw new Error("Invalid value for number of shares");
|
||||||
if (numShares > corporation.numShares) throw new Error("You don't have that many shares to sell!");
|
if (numShares > corporation.numShares) throw new Error("You don't have that many shares to sell!");
|
||||||
@ -287,20 +284,20 @@ export function SellShares(corporation: ICorporation, player: IPlayer, numShares
|
|||||||
corporation.sharePrice = newSharePrice;
|
corporation.sharePrice = newSharePrice;
|
||||||
corporation.shareSalesUntilPriceUpdate = newSharesUntilUpdate;
|
corporation.shareSalesUntilPriceUpdate = newSharesUntilUpdate;
|
||||||
corporation.shareSaleCooldown = CorporationConstants.SellSharesCooldown;
|
corporation.shareSaleCooldown = CorporationConstants.SellSharesCooldown;
|
||||||
player.gainMoney(profit, "corporation");
|
Player.gainMoney(profit, "corporation");
|
||||||
return profit;
|
return profit;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function BuyBackShares(corporation: ICorporation, player: IPlayer, numShares: number): boolean {
|
export function BuyBackShares(corporation: Corporation, numShares: number): boolean {
|
||||||
if (isNaN(numShares)) throw new Error("Invalid value for number of shares");
|
if (isNaN(numShares)) throw new Error("Invalid value for number of shares");
|
||||||
if (numShares < 0) throw new Error("Invalid value for number of shares");
|
if (numShares < 0) throw new Error("Invalid value for number of shares");
|
||||||
if (numShares > corporation.issuedShares) throw new Error("You don't have that many shares to buy!");
|
if (numShares > corporation.issuedShares) throw new Error("You don't have that many shares to buy!");
|
||||||
if (!corporation.public) throw new Error("You haven't gone public!");
|
if (!corporation.public) throw new Error("You haven't gone public!");
|
||||||
const buybackPrice = corporation.sharePrice * 1.1;
|
const buybackPrice = corporation.sharePrice * 1.1;
|
||||||
if (player.money < numShares * buybackPrice) throw new Error("You cant afford that many shares!");
|
if (Player.money < numShares * buybackPrice) throw new Error("You cant afford that many shares!");
|
||||||
corporation.numShares += numShares;
|
corporation.numShares += numShares;
|
||||||
corporation.issuedShares -= numShares;
|
corporation.issuedShares -= numShares;
|
||||||
player.loseMoney(numShares * buybackPrice, "corporation");
|
Player.loseMoney(numShares * buybackPrice, "corporation");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -319,7 +316,7 @@ export function AutoAssignJob(office: OfficeSpace, job: string, count: number):
|
|||||||
return office.autoAssignJob(job, count);
|
return office.autoAssignJob(job, count);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function UpgradeOfficeSize(corp: ICorporation, office: OfficeSpace, size: number): void {
|
export function UpgradeOfficeSize(corp: Corporation, office: OfficeSpace, size: number): void {
|
||||||
const initialPriceMult = Math.round(office.size / CorporationConstants.OfficeInitialSize);
|
const initialPriceMult = Math.round(office.size / CorporationConstants.OfficeInitialSize);
|
||||||
const costMultiplier = 1.09;
|
const costMultiplier = 1.09;
|
||||||
// Calculate cost to upgrade size by 15 employees
|
// Calculate cost to upgrade size by 15 employees
|
||||||
@ -333,7 +330,7 @@ export function UpgradeOfficeSize(corp: ICorporation, office: OfficeSpace, size:
|
|||||||
corp.funds = corp.funds - cost;
|
corp.funds = corp.funds - cost;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function BuyCoffee(corp: ICorporation, office: OfficeSpace): boolean {
|
export function BuyCoffee(corp: Corporation, office: OfficeSpace): boolean {
|
||||||
const cost = office.getCoffeeCost();
|
const cost = office.getCoffeeCost();
|
||||||
if (corp.funds < cost) {
|
if (corp.funds < cost) {
|
||||||
return false;
|
return false;
|
||||||
@ -347,7 +344,7 @@ export function BuyCoffee(corp: ICorporation, office: OfficeSpace): boolean {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function ThrowParty(corp: ICorporation, office: OfficeSpace, costPerEmployee: number): number {
|
export function ThrowParty(corp: Corporation, office: OfficeSpace, costPerEmployee: number): number {
|
||||||
const mult = 1 + costPerEmployee / 10e6;
|
const mult = 1 + costPerEmployee / 10e6;
|
||||||
const cost = costPerEmployee * office.employees.length;
|
const cost = costPerEmployee * office.employees.length;
|
||||||
if (corp.funds < cost) {
|
if (corp.funds < cost) {
|
||||||
@ -362,9 +359,9 @@ export function ThrowParty(corp: ICorporation, office: OfficeSpace, costPerEmplo
|
|||||||
return mult;
|
return mult;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function PurchaseWarehouse(corp: ICorporation, division: IIndustry, city: string): void {
|
export function PurchaseWarehouse(corp: Corporation, division: Industry, city: string): void {
|
||||||
if (corp.funds < CorporationConstants.WarehouseInitialCost) return;
|
if (corp.funds < CorporationConstants.WarehouseInitialCost) return;
|
||||||
if (division.warehouses[city] instanceof Warehouse) return;
|
if (division.warehouses[city]) return;
|
||||||
division.warehouses[city] = new Warehouse({
|
division.warehouses[city] = new Warehouse({
|
||||||
corp: corp,
|
corp: corp,
|
||||||
industry: division,
|
industry: division,
|
||||||
@ -381,7 +378,7 @@ export function UpgradeWarehouseCost(warehouse: Warehouse, amt: number): number
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function UpgradeWarehouse(corp: ICorporation, division: IIndustry, warehouse: Warehouse, amt = 1): void {
|
export function UpgradeWarehouse(corp: Corporation, division: Industry, warehouse: Warehouse, amt = 1): void {
|
||||||
const sizeUpgradeCost = UpgradeWarehouseCost(warehouse, amt);
|
const sizeUpgradeCost = UpgradeWarehouseCost(warehouse, amt);
|
||||||
if (corp.funds < sizeUpgradeCost) return;
|
if (corp.funds < sizeUpgradeCost) return;
|
||||||
warehouse.level += amt;
|
warehouse.level += amt;
|
||||||
@ -389,7 +386,7 @@ export function UpgradeWarehouse(corp: ICorporation, division: IIndustry, wareho
|
|||||||
corp.funds = corp.funds - sizeUpgradeCost;
|
corp.funds = corp.funds - sizeUpgradeCost;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function HireAdVert(corp: ICorporation, division: IIndustry): void {
|
export function HireAdVert(corp: Corporation, division: Industry): void {
|
||||||
const cost = division.getAdVertCost();
|
const cost = division.getAdVertCost();
|
||||||
if (corp.funds < cost) return;
|
if (corp.funds < cost) return;
|
||||||
corp.funds = corp.funds - cost;
|
corp.funds = corp.funds - cost;
|
||||||
@ -397,8 +394,8 @@ export function HireAdVert(corp: ICorporation, division: IIndustry): void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function MakeProduct(
|
export function MakeProduct(
|
||||||
corp: ICorporation,
|
corp: Corporation,
|
||||||
division: IIndustry,
|
division: Industry,
|
||||||
city: string,
|
city: string,
|
||||||
productName: string,
|
productName: string,
|
||||||
designInvest: number,
|
designInvest: number,
|
||||||
@ -442,7 +439,7 @@ export function MakeProduct(
|
|||||||
designCost: designInvest,
|
designCost: designInvest,
|
||||||
advCost: marketingInvest,
|
advCost: marketingInvest,
|
||||||
});
|
});
|
||||||
if (products[product.name] instanceof Product) {
|
if (products[product.name]) {
|
||||||
throw new Error(`You already have a product with this name!`);
|
throw new Error(`You already have a product with this name!`);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -450,7 +447,7 @@ export function MakeProduct(
|
|||||||
products[product.name] = product;
|
products[product.name] = product;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function Research(division: IIndustry, researchName: string): void {
|
export function Research(division: Industry, researchName: string): void {
|
||||||
const researchTree = IndustryResearchTrees[division.type];
|
const researchTree = IndustryResearchTrees[division.type];
|
||||||
if (researchTree === undefined) throw new Error(`No research tree for industry '${division.type}'`);
|
if (researchTree === undefined) throw new Error(`No research tree for industry '${division.type}'`);
|
||||||
const allResearch = researchTree.getAllNodes();
|
const allResearch = researchTree.getAllNodes();
|
||||||
@ -473,10 +470,10 @@ export function Research(division: IIndustry, researchName: string): void {
|
|||||||
for (let i = 0; i < CorporationConstants.Cities.length; ++i) {
|
for (let i = 0; i < CorporationConstants.Cities.length; ++i) {
|
||||||
const city = CorporationConstants.Cities[i];
|
const city = CorporationConstants.Cities[i];
|
||||||
const warehouse = division.warehouses[city];
|
const warehouse = division.warehouses[city];
|
||||||
if (!(warehouse instanceof Warehouse)) {
|
if (!warehouse) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (Player.corporation instanceof Corporation) {
|
if (Player.corporation) {
|
||||||
// Stores cycles in a "buffer". Processed separately using Engine Counters
|
// Stores cycles in a "buffer". Processed separately using Engine Counters
|
||||||
warehouse.updateSize(Player.corporation, division);
|
warehouse.updateSize(Player.corporation, division);
|
||||||
}
|
}
|
||||||
|
@ -1,14 +1,13 @@
|
|||||||
import { CorporationState } from "./CorporationState";
|
import { CorporationState } from "./CorporationState";
|
||||||
import { CorporationUnlockUpgrade, CorporationUnlockUpgrades } from "./data/CorporationUnlockUpgrades";
|
import { CorporationUnlockUpgrade, CorporationUnlockUpgrades } from "./data/CorporationUnlockUpgrades";
|
||||||
import { CorporationUpgrade, CorporationUpgrades } from "./data/CorporationUpgrades";
|
import { CorporationUpgrade, CorporationUpgrades } from "./data/CorporationUpgrades";
|
||||||
import { Warehouse } from "./Warehouse";
|
|
||||||
import { CorporationConstants } from "./data/Constants";
|
import { CorporationConstants } from "./data/Constants";
|
||||||
import { Industry } from "./Industry";
|
import { Industry } from "./Industry";
|
||||||
|
|
||||||
import { BitNodeMultipliers } from "../BitNode/BitNodeMultipliers";
|
import { BitNodeMultipliers } from "../BitNode/BitNodeMultipliers";
|
||||||
import { showLiterature } from "../Literature/LiteratureHelpers";
|
import { showLiterature } from "../Literature/LiteratureHelpers";
|
||||||
import { LiteratureNames } from "../Literature/data/LiteratureNames";
|
import { LiteratureNames } from "../Literature/data/LiteratureNames";
|
||||||
import { IPlayer } from "../PersonObjects/IPlayer";
|
import { Player } from "../Player";
|
||||||
|
|
||||||
import { dialogBoxCreate } from "../ui/React/DialogBox";
|
import { dialogBoxCreate } from "../ui/React/DialogBox";
|
||||||
import { Reviver, Generic_toJSON, Generic_fromJSON, IReviverValue } from "../utils/JSONReviver";
|
import { Reviver, Generic_toJSON, Generic_fromJSON, IReviverValue } from "../utils/JSONReviver";
|
||||||
@ -76,7 +75,7 @@ export class Corporation {
|
|||||||
this.storedCycles += numCycles;
|
this.storedCycles += numCycles;
|
||||||
}
|
}
|
||||||
|
|
||||||
process(player: IPlayer): void {
|
process(): void {
|
||||||
if (this.storedCycles >= CorporationConstants.CyclesPerIndustryStateCycle) {
|
if (this.storedCycles >= CorporationConstants.CyclesPerIndustryStateCycle) {
|
||||||
const state = this.getState();
|
const state = this.getState();
|
||||||
const marketCycles = 1;
|
const marketCycles = 1;
|
||||||
@ -120,7 +119,7 @@ export class Corporation {
|
|||||||
if (isNaN(this.funds) || this.funds === Infinity || this.funds === -Infinity) {
|
if (isNaN(this.funds) || this.funds === Infinity || this.funds === -Infinity) {
|
||||||
dialogBoxCreate(
|
dialogBoxCreate(
|
||||||
"There was an error calculating your Corporations funds and they got reset to 0. " +
|
"There was an error calculating your Corporations funds and they got reset to 0. " +
|
||||||
"This is a bug. Please report to game developer.<br><br>" +
|
"This is a bug. Please report to game developer.\n\n" +
|
||||||
"(Your funds have been set to $150b for the inconvenience)",
|
"(Your funds have been set to $150b for the inconvenience)",
|
||||||
);
|
);
|
||||||
this.funds = 150e9;
|
this.funds = 150e9;
|
||||||
@ -139,7 +138,7 @@ export class Corporation {
|
|||||||
} else {
|
} else {
|
||||||
const totalDividends = this.dividendRate * cycleProfit;
|
const totalDividends = this.dividendRate * cycleProfit;
|
||||||
const retainedEarnings = cycleProfit - totalDividends;
|
const retainedEarnings = cycleProfit - totalDividends;
|
||||||
player.gainMoney(this.getCycleDividends(), "corporation");
|
Player.gainMoney(this.getCycleDividends(), "corporation");
|
||||||
this.addFunds(retainedEarnings);
|
this.addFunds(retainedEarnings);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -331,7 +330,7 @@ export class Corporation {
|
|||||||
for (const city of Object.keys(industry.warehouses)) {
|
for (const city of Object.keys(industry.warehouses)) {
|
||||||
const warehouse = industry.warehouses[city];
|
const warehouse = industry.warehouses[city];
|
||||||
if (warehouse === 0) continue;
|
if (warehouse === 0) continue;
|
||||||
if (industry.warehouses.hasOwnProperty(city) && warehouse instanceof Warehouse) {
|
if (industry.warehouses.hasOwnProperty(city) && warehouse) {
|
||||||
warehouse.updateSize(this, industry);
|
warehouse.updateSize(this, industry);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -428,9 +427,9 @@ export class Corporation {
|
|||||||
// Adds the Corporation Handbook (Starter Guide) to the player's home computer.
|
// Adds the Corporation Handbook (Starter Guide) to the player's home computer.
|
||||||
// This is a lit file that gives introductory info to the player
|
// This is a lit file that gives introductory info to the player
|
||||||
// This occurs when the player clicks the "Getting Started Guide" button on the overview panel
|
// This occurs when the player clicks the "Getting Started Guide" button on the overview panel
|
||||||
getStarterGuide(player: IPlayer): void {
|
getStarterGuide(): void {
|
||||||
// Check if player already has Corporation Handbook
|
// Check if player already has Corporation Handbook
|
||||||
const homeComp = player.getHomeComputer();
|
const homeComp = Player.getHomeComputer();
|
||||||
let hasHandbook = false;
|
let hasHandbook = false;
|
||||||
const handbookFn = LiteratureNames.CorporationManagementHandbook;
|
const handbookFn = LiteratureNames.CorporationManagementHandbook;
|
||||||
for (let i = 0; i < homeComp.messages.length; ++i) {
|
for (let i = 0; i < homeComp.messages.length; ++i) {
|
||||||
|
@ -2,8 +2,8 @@ import { CorporationConstants } from "./data/Constants";
|
|||||||
import { getRandomInt } from "../utils/helpers/getRandomInt";
|
import { getRandomInt } from "../utils/helpers/getRandomInt";
|
||||||
import { Generic_fromJSON, Generic_toJSON, IReviverValue, Reviver } from "../utils/JSONReviver";
|
import { Generic_fromJSON, Generic_toJSON, IReviverValue, Reviver } from "../utils/JSONReviver";
|
||||||
import { EmployeePositions } from "./EmployeePositions";
|
import { EmployeePositions } from "./EmployeePositions";
|
||||||
import { ICorporation } from "./ICorporation";
|
import { Corporation } from "./Corporation";
|
||||||
import { IIndustry } from "./IIndustry";
|
import { Industry } from "./Industry";
|
||||||
|
|
||||||
interface IParams {
|
interface IParams {
|
||||||
name?: string;
|
name?: string;
|
||||||
@ -77,7 +77,7 @@ export class Employee {
|
|||||||
return salary;
|
return salary;
|
||||||
}
|
}
|
||||||
|
|
||||||
calculateProductivity(corporation: ICorporation, industry: IIndustry): number {
|
calculateProductivity(corporation: Corporation, industry: Industry): number {
|
||||||
const effCre = this.cre * corporation.getEmployeeCreMultiplier() * industry.getEmployeeCreMultiplier(),
|
const effCre = this.cre * corporation.getEmployeeCreMultiplier() * industry.getEmployeeCreMultiplier(),
|
||||||
effCha = this.cha * corporation.getEmployeeChaMultiplier() * industry.getEmployeeChaMultiplier(),
|
effCha = this.cha * corporation.getEmployeeChaMultiplier() * industry.getEmployeeChaMultiplier(),
|
||||||
effInt = this.int * corporation.getEmployeeIntMultiplier() * industry.getEmployeeIntMultiplier(),
|
effInt = this.int * corporation.getEmployeeIntMultiplier() * industry.getEmployeeIntMultiplier(),
|
||||||
|
@ -1,63 +0,0 @@
|
|||||||
import { Industry } from "./Industry";
|
|
||||||
import { IPlayer } from "../PersonObjects/IPlayer";
|
|
||||||
import { CorporationUnlockUpgrade } from "./data/CorporationUnlockUpgrades";
|
|
||||||
import { CorporationUpgrade } from "./data/CorporationUpgrades";
|
|
||||||
import { CorporationState } from "./CorporationState";
|
|
||||||
import { IReviverValue } from "../utils/JSONReviver";
|
|
||||||
|
|
||||||
export interface ICorporation {
|
|
||||||
name: string;
|
|
||||||
|
|
||||||
divisions: Industry[];
|
|
||||||
|
|
||||||
funds: number;
|
|
||||||
revenue: number;
|
|
||||||
expenses: number;
|
|
||||||
fundingRound: number;
|
|
||||||
public: boolean;
|
|
||||||
totalShares: number;
|
|
||||||
numShares: number;
|
|
||||||
shareSalesUntilPriceUpdate: number;
|
|
||||||
shareSaleCooldown: number;
|
|
||||||
issueNewSharesCooldown: number;
|
|
||||||
dividendRate: number;
|
|
||||||
dividendTax: number;
|
|
||||||
issuedShares: number;
|
|
||||||
sharePrice: number;
|
|
||||||
storedCycles: number;
|
|
||||||
valuation: number;
|
|
||||||
|
|
||||||
unlockUpgrades: number[];
|
|
||||||
upgrades: number[];
|
|
||||||
upgradeMultipliers: number[];
|
|
||||||
|
|
||||||
state: CorporationState;
|
|
||||||
|
|
||||||
addFunds(amt: number): void;
|
|
||||||
getState(): string;
|
|
||||||
storeCycles(numCycles: number): void;
|
|
||||||
process(player: IPlayer): void;
|
|
||||||
determineValuation(): void;
|
|
||||||
determineCycleValuation(): number;
|
|
||||||
getTargetSharePrice(): number;
|
|
||||||
updateSharePrice(): void;
|
|
||||||
immediatelyUpdateSharePrice(): void;
|
|
||||||
calculateShareSale(numShares: number): [number, number, number];
|
|
||||||
convertCooldownToString(cd: number): string;
|
|
||||||
unlock(upgrade: CorporationUnlockUpgrade): void;
|
|
||||||
upgrade(upgrade: CorporationUpgrade): void;
|
|
||||||
getProductionMultiplier(): number;
|
|
||||||
getStorageMultiplier(): number;
|
|
||||||
getDreamSenseGain(): number;
|
|
||||||
getAdvertisingMultiplier(): number;
|
|
||||||
getEmployeeCreMultiplier(): number;
|
|
||||||
getEmployeeChaMultiplier(): number;
|
|
||||||
getEmployeeIntMultiplier(): number;
|
|
||||||
getEmployeeEffMultiplier(): number;
|
|
||||||
getSalesMultiplier(): number;
|
|
||||||
getScientificResearchMultiplier(): number;
|
|
||||||
getStarterGuide(player: IPlayer): void;
|
|
||||||
updateDividendTax(): void;
|
|
||||||
getCycleDividends(): number;
|
|
||||||
toJSON(): IReviverValue;
|
|
||||||
}
|
|
@ -1,78 +0,0 @@
|
|||||||
import { Material } from "./Material";
|
|
||||||
import { Warehouse } from "./Warehouse";
|
|
||||||
import { ICorporation } from "./ICorporation";
|
|
||||||
import { OfficeSpace } from "./OfficeSpace";
|
|
||||||
import { Product } from "./Product";
|
|
||||||
import { IReviverValue } from "../utils/JSONReviver";
|
|
||||||
|
|
||||||
export interface IIndustry {
|
|
||||||
name: string;
|
|
||||||
type: string;
|
|
||||||
sciResearch: Material;
|
|
||||||
researched: { [key: string]: boolean | undefined };
|
|
||||||
reqMats: { [key: string]: number | undefined };
|
|
||||||
|
|
||||||
prodMats: string[];
|
|
||||||
|
|
||||||
products: { [key: string]: Product | undefined };
|
|
||||||
makesProducts: boolean;
|
|
||||||
|
|
||||||
awareness: number;
|
|
||||||
popularity: number;
|
|
||||||
startingCost: number;
|
|
||||||
|
|
||||||
reFac: number;
|
|
||||||
sciFac: number;
|
|
||||||
hwFac: number;
|
|
||||||
robFac: number;
|
|
||||||
aiFac: number;
|
|
||||||
advFac: number;
|
|
||||||
|
|
||||||
prodMult: number;
|
|
||||||
|
|
||||||
// Decimal
|
|
||||||
lastCycleRevenue: number;
|
|
||||||
lastCycleExpenses: number;
|
|
||||||
thisCycleRevenue: number;
|
|
||||||
thisCycleExpenses: number;
|
|
||||||
|
|
||||||
state: string;
|
|
||||||
newInd: boolean;
|
|
||||||
warehouses: { [key: string]: Warehouse | 0 };
|
|
||||||
offices: { [key: string]: OfficeSpace | 0 };
|
|
||||||
numAdVerts: number;
|
|
||||||
|
|
||||||
init(): void;
|
|
||||||
getProductDescriptionText(): string;
|
|
||||||
getMaximumNumberProducts(): number;
|
|
||||||
hasMaximumNumberProducts(): boolean;
|
|
||||||
calculateProductionFactors(): void;
|
|
||||||
updateWarehouseSizeUsed(warehouse: Warehouse): void;
|
|
||||||
process(marketCycles: number, state: string, corporation: ICorporation): void;
|
|
||||||
processMaterialMarket(): void;
|
|
||||||
processProductMarket(marketCycles: number): void;
|
|
||||||
processMaterials(marketCycles: number, corporation: ICorporation): [number, number];
|
|
||||||
processProducts(marketCycles: number, corporation: ICorporation): [number, number];
|
|
||||||
processProduct(marketCycles: number, product: Product, corporation: ICorporation): number;
|
|
||||||
resetImports(state: string): void;
|
|
||||||
discontinueProduct(product: Product): void;
|
|
||||||
getAdVertCost(): number;
|
|
||||||
applyAdVert(corporation: ICorporation): void;
|
|
||||||
getOfficeProductivity(office: OfficeSpace, params?: { forProduct?: boolean }): number;
|
|
||||||
getBusinessFactor(office: OfficeSpace): number;
|
|
||||||
getAdvertisingFactors(): [number, number, number, number];
|
|
||||||
getMarketFactor(mat: { dmd: number; cmp: number }): number;
|
|
||||||
hasResearch(name: string): boolean;
|
|
||||||
updateResearchTree(): void;
|
|
||||||
getAdvertisingMultiplier(): number;
|
|
||||||
getEmployeeChaMultiplier(): number;
|
|
||||||
getEmployeeCreMultiplier(): number;
|
|
||||||
getEmployeeEffMultiplier(): number;
|
|
||||||
getEmployeeIntMultiplier(): number;
|
|
||||||
getProductionMultiplier(): number;
|
|
||||||
getProductProductionMultiplier(): number;
|
|
||||||
getSalesMultiplier(): number;
|
|
||||||
getScientificResearchMultiplier(): number;
|
|
||||||
getStorageMultiplier(): number;
|
|
||||||
toJSON(): IReviverValue;
|
|
||||||
}
|
|
@ -12,16 +12,15 @@ import { dialogBoxCreate } from "../ui/React/DialogBox";
|
|||||||
import { isString } from "../utils/helpers/isString";
|
import { isString } from "../utils/helpers/isString";
|
||||||
import { MaterialSizes } from "./MaterialSizes";
|
import { MaterialSizes } from "./MaterialSizes";
|
||||||
import { Warehouse } from "./Warehouse";
|
import { Warehouse } from "./Warehouse";
|
||||||
import { ICorporation } from "./ICorporation";
|
import { Corporation } from "./Corporation";
|
||||||
import { IIndustry } from "./IIndustry";
|
|
||||||
|
|
||||||
interface IParams {
|
interface IParams {
|
||||||
name?: string;
|
name?: string;
|
||||||
corp?: ICorporation;
|
corp?: Corporation;
|
||||||
type?: string;
|
type?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Industry implements IIndustry {
|
export class Industry {
|
||||||
name = "";
|
name = "";
|
||||||
type = Industries.Agriculture;
|
type = Industries.Agriculture;
|
||||||
sciResearch = new Material({ name: "Scientific Research" });
|
sciResearch = new Material({ name: "Scientific Research" });
|
||||||
@ -356,9 +355,7 @@ export class Industry implements IIndustry {
|
|||||||
for (let i = 0; i < CorporationConstants.Cities.length; ++i) {
|
for (let i = 0; i < CorporationConstants.Cities.length; ++i) {
|
||||||
const city = CorporationConstants.Cities[i];
|
const city = CorporationConstants.Cities[i];
|
||||||
const warehouse = this.warehouses[city];
|
const warehouse = this.warehouses[city];
|
||||||
if (!(warehouse instanceof Warehouse)) {
|
if (!warehouse) continue;
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
const materials = warehouse.materials;
|
const materials = warehouse.materials;
|
||||||
|
|
||||||
@ -385,7 +382,7 @@ export class Industry implements IIndustry {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
process(marketCycles = 1, state: string, corporation: ICorporation): void {
|
process(marketCycles = 1, state: string, corporation: Corporation): void {
|
||||||
this.state = state;
|
this.state = state;
|
||||||
|
|
||||||
//At the start of a cycle, store and reset revenue/expenses
|
//At the start of a cycle, store and reset revenue/expenses
|
||||||
@ -414,10 +411,7 @@ export class Industry implements IIndustry {
|
|||||||
let employeeSalary = 0;
|
let employeeSalary = 0;
|
||||||
for (const officeLoc of Object.keys(this.offices)) {
|
for (const officeLoc of Object.keys(this.offices)) {
|
||||||
const office = this.offices[officeLoc];
|
const office = this.offices[officeLoc];
|
||||||
if (office === 0) continue;
|
if (office) employeeSalary += office.process(marketCycles, corporation, this);
|
||||||
if (office instanceof OfficeSpace) {
|
|
||||||
employeeSalary += office.process(marketCycles, corporation, this);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
this.thisCycleExpenses = this.thisCycleExpenses + employeeSalary;
|
this.thisCycleExpenses = this.thisCycleExpenses + employeeSalary;
|
||||||
|
|
||||||
@ -468,7 +462,7 @@ export class Industry implements IIndustry {
|
|||||||
for (let i = 0; i < CorporationConstants.Cities.length; ++i) {
|
for (let i = 0; i < CorporationConstants.Cities.length; ++i) {
|
||||||
//If this industry has a warehouse in this city, process the market
|
//If this industry has a warehouse in this city, process the market
|
||||||
//for every material this industry requires or produces
|
//for every material this industry requires or produces
|
||||||
if (this.warehouses[CorporationConstants.Cities[i]] instanceof Warehouse) {
|
if (this.warehouses[CorporationConstants.Cities[i]]) {
|
||||||
const wh = this.warehouses[CorporationConstants.Cities[i]];
|
const wh = this.warehouses[CorporationConstants.Cities[i]];
|
||||||
if (wh === 0) continue;
|
if (wh === 0) continue;
|
||||||
for (const name of Object.keys(reqMats)) {
|
for (const name of Object.keys(reqMats)) {
|
||||||
@ -518,7 +512,7 @@ export class Industry implements IIndustry {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Process production, purchase, and import/export of materials
|
//Process production, purchase, and import/export of materials
|
||||||
processMaterials(marketCycles = 1, corporation: ICorporation): [number, number] {
|
processMaterials(marketCycles = 1, corporation: Corporation): [number, number] {
|
||||||
let revenue = 0,
|
let revenue = 0,
|
||||||
expenses = 0;
|
expenses = 0;
|
||||||
this.calculateProductionFactors();
|
this.calculateProductionFactors();
|
||||||
@ -528,7 +522,7 @@ export class Industry implements IIndustry {
|
|||||||
const office = this.offices[city];
|
const office = this.offices[city];
|
||||||
if (office === 0) continue;
|
if (office === 0) continue;
|
||||||
|
|
||||||
if (this.warehouses[city] instanceof Warehouse) {
|
if (this.warehouses[city]) {
|
||||||
const warehouse = this.warehouses[city];
|
const warehouse = this.warehouses[city];
|
||||||
if (warehouse === 0) continue;
|
if (warehouse === 0) continue;
|
||||||
|
|
||||||
@ -825,14 +819,7 @@ export class Industry implements IIndustry {
|
|||||||
sellAmt = eval(tmp);
|
sellAmt = eval(tmp);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
dialogBoxCreate(
|
dialogBoxCreate(
|
||||||
"Error evaluating your sell amount for material " +
|
`Error evaluating your sell amount for material ${mat.name} in ${this.name}'s ${city} office. The sell amount is being set to zero`,
|
||||||
mat.name +
|
|
||||||
" in " +
|
|
||||||
this.name +
|
|
||||||
"'s " +
|
|
||||||
city +
|
|
||||||
" office. The sell amount " +
|
|
||||||
"is being set to zero",
|
|
||||||
);
|
);
|
||||||
sellAmt = 0;
|
sellAmt = 0;
|
||||||
}
|
}
|
||||||
@ -879,27 +866,13 @@ export class Industry implements IIndustry {
|
|||||||
amt = eval(amtStr);
|
amt = eval(amtStr);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
dialogBoxCreate(
|
dialogBoxCreate(
|
||||||
"Calculating export for " +
|
`Calculating export for ${mat.name} in ${this.name}'s ${city} division failed with error: ${e}`,
|
||||||
mat.name +
|
|
||||||
" in " +
|
|
||||||
this.name +
|
|
||||||
"'s " +
|
|
||||||
city +
|
|
||||||
" division failed with " +
|
|
||||||
"error: " +
|
|
||||||
e,
|
|
||||||
);
|
);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (isNaN(amt)) {
|
if (isNaN(amt)) {
|
||||||
dialogBoxCreate(
|
dialogBoxCreate(
|
||||||
"Error calculating export amount for " +
|
`Error calculating export amount for ${mat.name} in ${this.name}'s ${city} division.`,
|
||||||
mat.name +
|
|
||||||
" in " +
|
|
||||||
this.name +
|
|
||||||
"'s " +
|
|
||||||
city +
|
|
||||||
" division.",
|
|
||||||
);
|
);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -915,7 +888,7 @@ export class Industry implements IIndustry {
|
|||||||
if (corporation.divisions[foo].name === exp.ind) {
|
if (corporation.divisions[foo].name === exp.ind) {
|
||||||
const expIndustry = corporation.divisions[foo];
|
const expIndustry = corporation.divisions[foo];
|
||||||
const expWarehouse = expIndustry.warehouses[exp.city];
|
const expWarehouse = expIndustry.warehouses[exp.city];
|
||||||
if (!(expWarehouse instanceof Warehouse)) {
|
if (!expWarehouse) {
|
||||||
console.error(`Invalid export! ${expIndustry.name} ${exp.city}`);
|
console.error(`Invalid export! ${expIndustry.name} ${exp.city}`);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -958,7 +931,7 @@ export class Industry implements IIndustry {
|
|||||||
|
|
||||||
//Produce Scientific Research based on R&D employees
|
//Produce Scientific Research based on R&D employees
|
||||||
//Scientific Research can be produced without a warehouse
|
//Scientific Research can be produced without a warehouse
|
||||||
if (office instanceof OfficeSpace) {
|
if (office) {
|
||||||
this.sciResearch.qty +=
|
this.sciResearch.qty +=
|
||||||
0.004 *
|
0.004 *
|
||||||
Math.pow(office.employeeProd[EmployeePositions.RandD], 0.5) *
|
Math.pow(office.employeeProd[EmployeePositions.RandD], 0.5) *
|
||||||
@ -970,7 +943,7 @@ export class Industry implements IIndustry {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Process production & sale of this industry's FINISHED products (including all of their stats)
|
//Process production & sale of this industry's FINISHED products (including all of their stats)
|
||||||
processProducts(marketCycles = 1, corporation: ICorporation): [number, number] {
|
processProducts(marketCycles = 1, corporation: Corporation): [number, number] {
|
||||||
let revenue = 0;
|
let revenue = 0;
|
||||||
const expenses = 0;
|
const expenses = 0;
|
||||||
|
|
||||||
@ -997,7 +970,7 @@ export class Industry implements IIndustry {
|
|||||||
for (const prodName of Object.keys(this.products)) {
|
for (const prodName of Object.keys(this.products)) {
|
||||||
if (this.products.hasOwnProperty(prodName)) {
|
if (this.products.hasOwnProperty(prodName)) {
|
||||||
const prod = this.products[prodName];
|
const prod = this.products[prodName];
|
||||||
if (prod instanceof Product && prod.fin) {
|
if (prod && prod.fin) {
|
||||||
revenue += this.processProduct(marketCycles, prod, corporation);
|
revenue += this.processProduct(marketCycles, prod, corporation);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1006,14 +979,14 @@ export class Industry implements IIndustry {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Processes FINISHED products
|
//Processes FINISHED products
|
||||||
processProduct(marketCycles = 1, product: Product, corporation: ICorporation): number {
|
processProduct(marketCycles = 1, product: Product, corporation: Corporation): number {
|
||||||
let totalProfit = 0;
|
let totalProfit = 0;
|
||||||
for (let i = 0; i < CorporationConstants.Cities.length; ++i) {
|
for (let i = 0; i < CorporationConstants.Cities.length; ++i) {
|
||||||
const city = CorporationConstants.Cities[i];
|
const city = CorporationConstants.Cities[i];
|
||||||
const office = this.offices[city];
|
const office = this.offices[city];
|
||||||
if (office === 0) continue;
|
if (office === 0) continue;
|
||||||
const warehouse = this.warehouses[city];
|
const warehouse = this.warehouses[city];
|
||||||
if (warehouse instanceof Warehouse) {
|
if (warehouse) {
|
||||||
switch (this.state) {
|
switch (this.state) {
|
||||||
case "PRODUCTION": {
|
case "PRODUCTION": {
|
||||||
//Calculate the maximum production of this material based
|
//Calculate the maximum production of this material based
|
||||||
@ -1172,13 +1145,7 @@ export class Industry implements IIndustry {
|
|||||||
tmp = eval(tmp);
|
tmp = eval(tmp);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
dialogBoxCreate(
|
dialogBoxCreate(
|
||||||
"Error evaluating your sell price expression for " +
|
`Error evaluating your sell price expression for ${product.name} in ${this.name}'s ${city} office. Sell price is being set to MAX`,
|
||||||
product.name +
|
|
||||||
" in " +
|
|
||||||
this.name +
|
|
||||||
"'s " +
|
|
||||||
city +
|
|
||||||
" office. Sell price is being set to MAX",
|
|
||||||
);
|
);
|
||||||
tmp = product.maxsll;
|
tmp = product.maxsll;
|
||||||
}
|
}
|
||||||
@ -1223,7 +1190,7 @@ export class Industry implements IIndustry {
|
|||||||
if (state === "EXPORT") {
|
if (state === "EXPORT") {
|
||||||
for (let i = 0; i < CorporationConstants.Cities.length; ++i) {
|
for (let i = 0; i < CorporationConstants.Cities.length; ++i) {
|
||||||
const city = CorporationConstants.Cities[i];
|
const city = CorporationConstants.Cities[i];
|
||||||
if (!(this.warehouses[city] instanceof Warehouse)) {
|
if (!this.warehouses[city]) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
const warehouse = this.warehouses[city];
|
const warehouse = this.warehouses[city];
|
||||||
@ -1252,7 +1219,7 @@ export class Industry implements IIndustry {
|
|||||||
return 1e9 * Math.pow(1.06, this.numAdVerts);
|
return 1e9 * Math.pow(1.06, this.numAdVerts);
|
||||||
}
|
}
|
||||||
|
|
||||||
applyAdVert(corporation: ICorporation): void {
|
applyAdVert(corporation: Corporation): void {
|
||||||
const advMult = corporation.getAdvertisingMultiplier() * this.getAdvertisingMultiplier();
|
const advMult = corporation.getAdvertisingMultiplier() * this.getAdvertisingMultiplier();
|
||||||
const awareness = (this.awareness + 3 * advMult) * (1.01 * advMult);
|
const awareness = (this.awareness + 3 * advMult) * (1.01 * advMult);
|
||||||
this.awareness = Math.min(awareness, Number.MAX_VALUE);
|
this.awareness = Math.min(awareness, Number.MAX_VALUE);
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import { ResearchTree } from "./ResearchTree";
|
import { ResearchTree } from "./ResearchTree";
|
||||||
import { ICorporation } from "./ICorporation";
|
import { Corporation } from "./Corporation";
|
||||||
import { getBaseResearchTreeCopy, getProductIndustryResearchTreeCopy } from "./data/BaseResearchTree";
|
import { getBaseResearchTreeCopy, getProductIndustryResearchTreeCopy } from "./data/BaseResearchTree";
|
||||||
import { MoneyCost } from "./ui/MoneyCost";
|
import { MoneyCost } from "./ui/MoneyCost";
|
||||||
|
|
||||||
@ -59,8 +59,8 @@ export const IndustryStartingCosts: IIndustryMap<number> = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Map of description for each industry
|
// Map of description for each industry
|
||||||
export const IndustryDescriptions: IIndustryMap<(corp: ICorporation) => React.ReactElement> = {
|
export const IndustryDescriptions: IIndustryMap<(corp: Corporation) => React.ReactElement> = {
|
||||||
Energy: (corp: ICorporation) => (
|
Energy: (corp: Corporation) => (
|
||||||
<>
|
<>
|
||||||
Engage in the production and distribution of energy.
|
Engage in the production and distribution of energy.
|
||||||
<br />
|
<br />
|
||||||
@ -70,7 +70,7 @@ export const IndustryDescriptions: IIndustryMap<(corp: ICorporation) => React.Re
|
|||||||
Recommended starting Industry: NO
|
Recommended starting Industry: NO
|
||||||
</>
|
</>
|
||||||
),
|
),
|
||||||
Utilities: (corp: ICorporation) => (
|
Utilities: (corp: Corporation) => (
|
||||||
<>
|
<>
|
||||||
Distribute water and provide wastewater services.
|
Distribute water and provide wastewater services.
|
||||||
<br />
|
<br />
|
||||||
@ -80,7 +80,7 @@ export const IndustryDescriptions: IIndustryMap<(corp: ICorporation) => React.Re
|
|||||||
Recommended starting Industry: NO
|
Recommended starting Industry: NO
|
||||||
</>
|
</>
|
||||||
),
|
),
|
||||||
Agriculture: (corp: ICorporation) => (
|
Agriculture: (corp: Corporation) => (
|
||||||
<>
|
<>
|
||||||
Cultivate crops and breed livestock to produce food.
|
Cultivate crops and breed livestock to produce food.
|
||||||
<br />
|
<br />
|
||||||
@ -90,7 +90,7 @@ export const IndustryDescriptions: IIndustryMap<(corp: ICorporation) => React.Re
|
|||||||
Recommended starting Industry: YES
|
Recommended starting Industry: YES
|
||||||
</>
|
</>
|
||||||
),
|
),
|
||||||
Fishing: (corp: ICorporation) => (
|
Fishing: (corp: Corporation) => (
|
||||||
<>
|
<>
|
||||||
Produce food through the breeding and processing of fish and fish products.
|
Produce food through the breeding and processing of fish and fish products.
|
||||||
<br />
|
<br />
|
||||||
@ -100,7 +100,7 @@ export const IndustryDescriptions: IIndustryMap<(corp: ICorporation) => React.Re
|
|||||||
Recommended starting Industry: NO
|
Recommended starting Industry: NO
|
||||||
</>
|
</>
|
||||||
),
|
),
|
||||||
Mining: (corp: ICorporation) => (
|
Mining: (corp: Corporation) => (
|
||||||
<>
|
<>
|
||||||
Extract and process metals from the earth.
|
Extract and process metals from the earth.
|
||||||
<br />
|
<br />
|
||||||
@ -110,7 +110,7 @@ export const IndustryDescriptions: IIndustryMap<(corp: ICorporation) => React.Re
|
|||||||
Recommended starting Industry: NO
|
Recommended starting Industry: NO
|
||||||
</>
|
</>
|
||||||
),
|
),
|
||||||
Food: (corp: ICorporation) => (
|
Food: (corp: Corporation) => (
|
||||||
<>
|
<>
|
||||||
Create your own restaurants all around the world.
|
Create your own restaurants all around the world.
|
||||||
<br />
|
<br />
|
||||||
@ -120,7 +120,7 @@ export const IndustryDescriptions: IIndustryMap<(corp: ICorporation) => React.Re
|
|||||||
Recommended starting Industry: YES
|
Recommended starting Industry: YES
|
||||||
</>
|
</>
|
||||||
),
|
),
|
||||||
Tobacco: (corp: ICorporation) => (
|
Tobacco: (corp: Corporation) => (
|
||||||
<>
|
<>
|
||||||
Create and distribute tobacco and tobacco-related products.
|
Create and distribute tobacco and tobacco-related products.
|
||||||
<br />
|
<br />
|
||||||
@ -130,7 +130,7 @@ export const IndustryDescriptions: IIndustryMap<(corp: ICorporation) => React.Re
|
|||||||
Recommended starting Industry: YES
|
Recommended starting Industry: YES
|
||||||
</>
|
</>
|
||||||
),
|
),
|
||||||
Chemical: (corp: ICorporation) => (
|
Chemical: (corp: Corporation) => (
|
||||||
<>
|
<>
|
||||||
Produce industrial chemicals.
|
Produce industrial chemicals.
|
||||||
<br />
|
<br />
|
||||||
@ -140,7 +140,7 @@ export const IndustryDescriptions: IIndustryMap<(corp: ICorporation) => React.Re
|
|||||||
Recommended starting Industry: NO
|
Recommended starting Industry: NO
|
||||||
</>
|
</>
|
||||||
),
|
),
|
||||||
Pharmaceutical: (corp: ICorporation) => (
|
Pharmaceutical: (corp: Corporation) => (
|
||||||
<>
|
<>
|
||||||
Discover, develop, and create new pharmaceutical drugs.
|
Discover, develop, and create new pharmaceutical drugs.
|
||||||
<br />
|
<br />
|
||||||
@ -150,7 +150,7 @@ export const IndustryDescriptions: IIndustryMap<(corp: ICorporation) => React.Re
|
|||||||
Recommended starting Industry: NO
|
Recommended starting Industry: NO
|
||||||
</>
|
</>
|
||||||
),
|
),
|
||||||
Computer: (corp: ICorporation) => (
|
Computer: (corp: Corporation) => (
|
||||||
<>
|
<>
|
||||||
Develop and manufacture new computer hardware and networking infrastructures.
|
Develop and manufacture new computer hardware and networking infrastructures.
|
||||||
<br />
|
<br />
|
||||||
@ -160,7 +160,7 @@ export const IndustryDescriptions: IIndustryMap<(corp: ICorporation) => React.Re
|
|||||||
Recommended starting Industry: NO
|
Recommended starting Industry: NO
|
||||||
</>
|
</>
|
||||||
),
|
),
|
||||||
Robotics: (corp: ICorporation) => (
|
Robotics: (corp: Corporation) => (
|
||||||
<>
|
<>
|
||||||
Develop and create robots.
|
Develop and create robots.
|
||||||
<br />
|
<br />
|
||||||
@ -170,7 +170,7 @@ export const IndustryDescriptions: IIndustryMap<(corp: ICorporation) => React.Re
|
|||||||
Recommended starting Industry: NO
|
Recommended starting Industry: NO
|
||||||
</>
|
</>
|
||||||
),
|
),
|
||||||
Software: (corp: ICorporation) => (
|
Software: (corp: Corporation) => (
|
||||||
<>
|
<>
|
||||||
Develop computer software and create AI Cores.
|
Develop computer software and create AI Cores.
|
||||||
<br />
|
<br />
|
||||||
@ -180,7 +180,7 @@ export const IndustryDescriptions: IIndustryMap<(corp: ICorporation) => React.Re
|
|||||||
Recommended starting Industry: YES
|
Recommended starting Industry: YES
|
||||||
</>
|
</>
|
||||||
),
|
),
|
||||||
Healthcare: (corp: ICorporation) => (
|
Healthcare: (corp: Corporation) => (
|
||||||
<>
|
<>
|
||||||
Create and manage hospitals.
|
Create and manage hospitals.
|
||||||
<br />
|
<br />
|
||||||
@ -190,7 +190,7 @@ export const IndustryDescriptions: IIndustryMap<(corp: ICorporation) => React.Re
|
|||||||
Recommended starting Industry: NO
|
Recommended starting Industry: NO
|
||||||
</>
|
</>
|
||||||
),
|
),
|
||||||
RealEstate: (corp: ICorporation) => (
|
RealEstate: (corp: Corporation) => (
|
||||||
<>
|
<>
|
||||||
Develop and manage real estate properties.
|
Develop and manage real estate properties.
|
||||||
<br />
|
<br />
|
||||||
|
@ -4,8 +4,8 @@ import { getRandomInt } from "../utils/helpers/getRandomInt";
|
|||||||
import { generateRandomString } from "../utils/StringHelperFunctions";
|
import { generateRandomString } from "../utils/StringHelperFunctions";
|
||||||
import { Generic_fromJSON, Generic_toJSON, IReviverValue, Reviver } from "../utils/JSONReviver";
|
import { Generic_fromJSON, Generic_toJSON, IReviverValue, Reviver } from "../utils/JSONReviver";
|
||||||
import { Employee } from "./Employee";
|
import { Employee } from "./Employee";
|
||||||
import { IIndustry } from "./IIndustry";
|
import { Industry } from "./Industry";
|
||||||
import { ICorporation } from "./ICorporation";
|
import { Corporation } from "./Corporation";
|
||||||
|
|
||||||
interface IParams {
|
interface IParams {
|
||||||
loc?: string;
|
loc?: string;
|
||||||
@ -68,7 +68,7 @@ export class OfficeSpace {
|
|||||||
return this.employees.length >= this.size;
|
return this.employees.length >= this.size;
|
||||||
}
|
}
|
||||||
|
|
||||||
process(marketCycles = 1, corporation: ICorporation, industry: IIndustry): number {
|
process(marketCycles = 1, corporation: Corporation, industry: Industry): number {
|
||||||
// HRBuddy AutoRecruitment and training
|
// HRBuddy AutoRecruitment and training
|
||||||
if (industry.hasResearch("HRBuddy-Recruitment") && !this.atCapacity()) {
|
if (industry.hasResearch("HRBuddy-Recruitment") && !this.atCapacity()) {
|
||||||
const emp = this.hireRandomEmployee();
|
const emp = this.hireRandomEmployee();
|
||||||
@ -177,7 +177,7 @@ export class OfficeSpace {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
calculateEmployeeProductivity(corporation: ICorporation, industry: IIndustry): void {
|
calculateEmployeeProductivity(corporation: Corporation, industry: Industry): void {
|
||||||
//Reset
|
//Reset
|
||||||
for (const name of Object.keys(this.employeeProd)) {
|
for (const name of Object.keys(this.employeeProd)) {
|
||||||
this.employeeProd[name] = 0;
|
this.employeeProd[name] = 0;
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { EmployeePositions } from "./EmployeePositions";
|
import { EmployeePositions } from "./EmployeePositions";
|
||||||
import { MaterialSizes } from "./MaterialSizes";
|
import { MaterialSizes } from "./MaterialSizes";
|
||||||
import { IIndustry } from "./IIndustry";
|
import { Industry } from "./Industry";
|
||||||
import { ProductRatingWeights, IProductRatingWeight } from "./ProductRatingWeights";
|
import { ProductRatingWeights, IProductRatingWeight } from "./ProductRatingWeights";
|
||||||
|
|
||||||
import { createCityMap } from "../Locations/createCityMap";
|
import { createCityMap } from "../Locations/createCityMap";
|
||||||
@ -157,7 +157,7 @@ export class Product {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// @param industry - Industry object. Reference to industry that makes this Product
|
// @param industry - Industry object. Reference to industry that makes this Product
|
||||||
finishProduct(industry: IIndustry): void {
|
finishProduct(industry: Industry): void {
|
||||||
this.fin = true;
|
this.fin = true;
|
||||||
|
|
||||||
// Calculate properties
|
// Calculate properties
|
||||||
@ -248,7 +248,7 @@ export class Product {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
calculateRating(industry: IIndustry): void {
|
calculateRating(industry: Industry): void {
|
||||||
const weights: IProductRatingWeight = ProductRatingWeights[industry.type];
|
const weights: IProductRatingWeight = ProductRatingWeights[industry.type];
|
||||||
if (weights == null) {
|
if (weights == null) {
|
||||||
console.error(`Could not find product rating weights for: ${industry}`);
|
console.error(`Could not find product rating weights for: ${industry}`);
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
import { Material } from "./Material";
|
import { Material } from "./Material";
|
||||||
import { ICorporation } from "./ICorporation";
|
import { Corporation } from "./Corporation";
|
||||||
import { IIndustry } from "./IIndustry";
|
import { Industry } from "./Industry";
|
||||||
import { MaterialSizes } from "./MaterialSizes";
|
import { MaterialSizes } from "./MaterialSizes";
|
||||||
import { IMap } from "../types";
|
import { IMap } from "../types";
|
||||||
import { Generic_fromJSON, Generic_toJSON, IReviverValue, Reviver } from "../utils/JSONReviver";
|
import { Generic_fromJSON, Generic_toJSON, IReviverValue, Reviver } from "../utils/JSONReviver";
|
||||||
import { exceptionAlert } from "../utils/helpers/exceptionAlert";
|
import { exceptionAlert } from "../utils/helpers/exceptionAlert";
|
||||||
|
|
||||||
interface IConstructorParams {
|
interface IConstructorParams {
|
||||||
corp?: ICorporation;
|
corp?: Corporation;
|
||||||
industry?: IIndustry;
|
industry?: Industry;
|
||||||
loc?: string;
|
loc?: string;
|
||||||
size?: number;
|
size?: number;
|
||||||
}
|
}
|
||||||
@ -96,7 +96,7 @@ export class Warehouse {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
updateSize(corporation: ICorporation, industry: IIndustry): void {
|
updateSize(corporation: Corporation, industry: Industry): void {
|
||||||
try {
|
try {
|
||||||
this.size = this.level * 100 * corporation.getStorageMultiplier() * industry.getStorageMultiplier();
|
this.size = this.level * 100 * corporation.getStorageMultiplier() * industry.getStorageMultiplier();
|
||||||
} catch (e: unknown) {
|
} catch (e: unknown) {
|
||||||
|
@ -1,39 +1,7 @@
|
|||||||
import { CityName } from "./../../Locations/data/CityNames";
|
import { CityName } from "./../../Locations/data/CityNames";
|
||||||
const CyclesPerMarketCycle = 50;
|
const CyclesPerMarketCycle = 50;
|
||||||
const AllCorporationStates = ["START", "PURCHASE", "PRODUCTION", "SALE", "EXPORT"];
|
const AllCorporationStates = ["START", "PURCHASE", "PRODUCTION", "SALE", "EXPORT"];
|
||||||
export const CorporationConstants: {
|
export const CorporationConstants = {
|
||||||
INITIALSHARES: number;
|
|
||||||
SHARESPERPRICEUPDATE: number;
|
|
||||||
IssueNewSharesCooldown: number;
|
|
||||||
SellSharesCooldown: number;
|
|
||||||
CyclesPerMarketCycle: number;
|
|
||||||
CyclesPerIndustryStateCycle: number;
|
|
||||||
SecsPerMarketCycle: number;
|
|
||||||
Cities: string[];
|
|
||||||
WarehouseInitialCost: number;
|
|
||||||
WarehouseInitialSize: number;
|
|
||||||
WarehouseUpgradeBaseCost: number;
|
|
||||||
OfficeInitialCost: number;
|
|
||||||
OfficeInitialSize: number;
|
|
||||||
OfficeUpgradeBaseCost: number;
|
|
||||||
BribeThreshold: number;
|
|
||||||
BribeToRepRatio: number;
|
|
||||||
ProductProductionCostRatio: number;
|
|
||||||
DividendMaxRate: number;
|
|
||||||
EmployeeSalaryMultiplier: number;
|
|
||||||
CyclesPerEmployeeRaise: number;
|
|
||||||
EmployeeRaiseAmount: number;
|
|
||||||
BaseMaxProducts: number;
|
|
||||||
AllCorporationStates: string[];
|
|
||||||
AllMaterials: string[];
|
|
||||||
AllIndustryTypes: string[];
|
|
||||||
AllUnlocks: string[];
|
|
||||||
AllUpgrades: string[];
|
|
||||||
AllResearch: string[];
|
|
||||||
FundingRoundShares: number[];
|
|
||||||
FundingRoundMultiplier: number[];
|
|
||||||
ValuationLength: number;
|
|
||||||
} = {
|
|
||||||
INITIALSHARES: 1e9, //Total number of shares you have at your company
|
INITIALSHARES: 1e9, //Total number of shares you have at your company
|
||||||
SHARESPERPRICEUPDATE: 1e6, //When selling large number of shares, price is dynamically updated for every batch of this amount
|
SHARESPERPRICEUPDATE: 1e6, //When selling large number of shares, price is dynamically updated for every batch of this amount
|
||||||
IssueNewSharesCooldown: 216e3, // 12 Hour in terms of game cycles
|
IssueNewSharesCooldown: 216e3, // 12 Hour in terms of game cycles
|
||||||
@ -96,7 +64,7 @@ export const CorporationConstants: {
|
|||||||
"Tobacco",
|
"Tobacco",
|
||||||
"Chemical",
|
"Chemical",
|
||||||
"Pharmaceutical",
|
"Pharmaceutical",
|
||||||
"Hardware",
|
"Computers",
|
||||||
"Robotics",
|
"Robotics",
|
||||||
"Software",
|
"Software",
|
||||||
"Healthcare",
|
"Healthcare",
|
||||||
|
@ -1,14 +1,11 @@
|
|||||||
import React, { useContext } from "react";
|
import React, { useContext } from "react";
|
||||||
import { ICorporation } from "../ICorporation";
|
import { Corporation } from "../Corporation";
|
||||||
import { IIndustry } from "../IIndustry";
|
import { Industry } from "../Industry";
|
||||||
|
|
||||||
export const Context: {
|
export const Context = {
|
||||||
Corporation: React.Context<ICorporation>;
|
Corporation: React.createContext<Corporation>({} as Corporation),
|
||||||
Division: React.Context<IIndustry>;
|
Division: React.createContext<Industry>({} as Industry),
|
||||||
} = {
|
|
||||||
Corporation: React.createContext<ICorporation>({} as ICorporation),
|
|
||||||
Division: React.createContext<IIndustry>({} as IIndustry),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export const useCorporation = (): ICorporation => useContext(Context.Corporation);
|
export const useCorporation = (): Corporation => useContext(Context.Corporation);
|
||||||
export const useDivision = (): IIndustry => useContext(Context.Division);
|
export const useDivision = (): Industry => useContext(Context.Division);
|
||||||
|
@ -2,11 +2,11 @@
|
|||||||
// These are the tabs at the top of the UI that let you switch to different
|
// These are the tabs at the top of the UI that let you switch to different
|
||||||
// divisions, see an overview of your corporation, or create a new industry
|
// divisions, see an overview of your corporation, or create a new industry
|
||||||
import React, { useState, useEffect } from "react";
|
import React, { useState, useEffect } from "react";
|
||||||
import { IIndustry } from "../IIndustry";
|
import { Industry } from "../Industry";
|
||||||
import { MainPanel } from "./MainPanel";
|
import { MainPanel } from "./MainPanel";
|
||||||
import { Industries } from "../IndustryData";
|
import { Industries } from "../IndustryData";
|
||||||
import { ExpandIndustryTab } from "./ExpandIndustryTab";
|
import { ExpandIndustryTab } from "./ExpandIndustryTab";
|
||||||
import { use } from "../../ui/Context";
|
import { Player } from "../../Player";
|
||||||
import { Context } from "./Context";
|
import { Context } from "./Context";
|
||||||
import { Overview } from "./Overview";
|
import { Overview } from "./Overview";
|
||||||
|
|
||||||
@ -14,8 +14,7 @@ import Tabs from "@mui/material/Tabs";
|
|||||||
import Tab from "@mui/material/Tab";
|
import Tab from "@mui/material/Tab";
|
||||||
|
|
||||||
export function CorporationRoot(): React.ReactElement {
|
export function CorporationRoot(): React.ReactElement {
|
||||||
const player = use.Player();
|
const corporation = Player.corporation;
|
||||||
const corporation = player.corporation;
|
|
||||||
if (corporation === null) return <></>;
|
if (corporation === null) return <></>;
|
||||||
const setRerender = useState(false)[1];
|
const setRerender = useState(false)[1];
|
||||||
function rerender(): void {
|
function rerender(): void {
|
||||||
@ -33,7 +32,7 @@ export function CorporationRoot(): React.ReactElement {
|
|||||||
const canExpand =
|
const canExpand =
|
||||||
Object.keys(Industries).filter(
|
Object.keys(Industries).filter(
|
||||||
(industryType: string) =>
|
(industryType: string) =>
|
||||||
corporation.divisions.find((division: IIndustry) => division.type === industryType) === undefined,
|
corporation.divisions.find((division: Industry) => division.type === industryType) === undefined,
|
||||||
).length > 0;
|
).length > 0;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -2,7 +2,7 @@ import React, { useState } from "react";
|
|||||||
import { dialogBoxCreate } from "../../ui/React/DialogBox";
|
import { dialogBoxCreate } from "../../ui/React/DialogBox";
|
||||||
import { IndustryStartingCosts, Industries, IndustryDescriptions } from "../IndustryData";
|
import { IndustryStartingCosts, Industries, IndustryDescriptions } from "../IndustryData";
|
||||||
import { useCorporation } from "./Context";
|
import { useCorporation } from "./Context";
|
||||||
import { IIndustry } from "../IIndustry";
|
import { Industry } from "../Industry";
|
||||||
import { NewIndustry } from "../Actions";
|
import { NewIndustry } from "../Actions";
|
||||||
|
|
||||||
import Typography from "@mui/material/Typography";
|
import Typography from "@mui/material/Typography";
|
||||||
@ -23,7 +23,7 @@ export function ExpandIndustryTab(props: IProps): React.ReactElement {
|
|||||||
const possibleIndustries = allIndustries
|
const possibleIndustries = allIndustries
|
||||||
.filter(
|
.filter(
|
||||||
(industryType: string) =>
|
(industryType: string) =>
|
||||||
corp.divisions.find((division: IIndustry) => division.type === industryType) === undefined,
|
corp.divisions.find((division: Industry) => division.type === industryType) === undefined,
|
||||||
)
|
)
|
||||||
.sort();
|
.sort();
|
||||||
const [industry, setIndustry] = useState(possibleIndustries.length > 0 ? possibleIndustries[0] : "");
|
const [industry, setIndustry] = useState(possibleIndustries.length > 0 ? possibleIndustries[0] : "");
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import { IIndustry } from "../IIndustry";
|
import { Industry } from "../Industry";
|
||||||
|
|
||||||
// Returns a boolean indicating whether the given material is relevant for the
|
// Returns a boolean indicating whether the given material is relevant for the
|
||||||
// current industry.
|
// current industry.
|
||||||
export function isRelevantMaterial(matName: string, division: IIndustry): boolean {
|
export function isRelevantMaterial(matName: string, division: Industry): boolean {
|
||||||
// Materials that affect Production multiplier
|
// Materials that affect Production multiplier
|
||||||
const prodMultiplierMats = ["Hardware", "Robots", "AICores", "RealEstate", "AI Cores", "Real Estate"];
|
const prodMultiplierMats = ["Hardware", "Robots", "AICores", "RealEstate", "AI Cores", "Real Estate"];
|
||||||
|
|
||||||
|
@ -7,7 +7,6 @@ import { IndustryOverview } from "./IndustryOverview";
|
|||||||
import { IndustryWarehouse } from "./IndustryWarehouse";
|
import { IndustryWarehouse } from "./IndustryWarehouse";
|
||||||
import { Warehouse } from "../Warehouse";
|
import { Warehouse } from "../Warehouse";
|
||||||
import { OfficeSpace } from "../OfficeSpace";
|
import { OfficeSpace } from "../OfficeSpace";
|
||||||
import { use } from "../../ui/Context";
|
|
||||||
import { useCorporation, useDivision } from "./Context";
|
import { useCorporation, useDivision } from "./Context";
|
||||||
import Box from "@mui/material/Box";
|
import Box from "@mui/material/Box";
|
||||||
|
|
||||||
@ -19,7 +18,6 @@ interface IProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function Industry(props: IProps): React.ReactElement {
|
export function Industry(props: IProps): React.ReactElement {
|
||||||
const player = use.Player();
|
|
||||||
const corp = useCorporation();
|
const corp = useCorporation();
|
||||||
const division = useDivision();
|
const division = useDivision();
|
||||||
return (
|
return (
|
||||||
@ -31,7 +29,6 @@ export function Industry(props: IProps): React.ReactElement {
|
|||||||
<Box sx={{ width: "50%" }}>
|
<Box sx={{ width: "50%" }}>
|
||||||
<IndustryWarehouse
|
<IndustryWarehouse
|
||||||
rerender={props.rerender}
|
rerender={props.rerender}
|
||||||
player={player}
|
|
||||||
corp={corp}
|
corp={corp}
|
||||||
currentCity={props.city}
|
currentCity={props.city}
|
||||||
division={division}
|
division={division}
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import { IIndustry } from "../IIndustry";
|
import { Industry } from "../Industry";
|
||||||
import { MathJaxWrapper } from "../../MathJaxWrapper";
|
import { MathJaxWrapper } from "../../MathJaxWrapper";
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
division: IIndustry;
|
division: Industry;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function IndustryProductEquation(props: IProps): React.ReactElement {
|
export function IndustryProductEquation(props: IProps): React.ReactElement {
|
||||||
|
@ -3,8 +3,6 @@
|
|||||||
import React, { useState } from "react";
|
import React, { useState } from "react";
|
||||||
|
|
||||||
import { CorporationConstants } from "../data/Constants";
|
import { CorporationConstants } from "../data/Constants";
|
||||||
import { Material } from "../Material";
|
|
||||||
import { Product } from "../Product";
|
|
||||||
import { Warehouse } from "../Warehouse";
|
import { Warehouse } from "../Warehouse";
|
||||||
import { SmartSupplyModal } from "./modals/SmartSupplyModal";
|
import { SmartSupplyModal } from "./modals/SmartSupplyModal";
|
||||||
import { ProductElem } from "./ProductElem";
|
import { ProductElem } from "./ProductElem";
|
||||||
@ -13,9 +11,8 @@ import { MaterialSizes } from "../MaterialSizes";
|
|||||||
|
|
||||||
import { numeralWrapper } from "../../ui/numeralFormat";
|
import { numeralWrapper } from "../../ui/numeralFormat";
|
||||||
|
|
||||||
import { ICorporation } from "../ICorporation";
|
import { Corporation } from "../Corporation";
|
||||||
import { IIndustry } from "../IIndustry";
|
import { Industry } from "../Industry";
|
||||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
|
||||||
import { MoneyCost } from "./MoneyCost";
|
import { MoneyCost } from "./MoneyCost";
|
||||||
import { isRelevantMaterial } from "./Helpers";
|
import { isRelevantMaterial } from "./Helpers";
|
||||||
import { IndustryProductEquation } from "./IndustryProductEquation";
|
import { IndustryProductEquation } from "./IndustryProductEquation";
|
||||||
@ -31,11 +28,10 @@ import makeStyles from "@mui/styles/makeStyles";
|
|||||||
import createStyles from "@mui/styles/createStyles";
|
import createStyles from "@mui/styles/createStyles";
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
corp: ICorporation;
|
corp: Corporation;
|
||||||
division: IIndustry;
|
division: Industry;
|
||||||
warehouse: Warehouse | 0;
|
warehouse: Warehouse | 0;
|
||||||
currentCity: string;
|
currentCity: string;
|
||||||
player: IPlayer;
|
|
||||||
rerender: () => void;
|
rerender: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -94,7 +90,7 @@ function WarehouseRoot(props: IProps): React.ReactElement {
|
|||||||
// Create React components for materials
|
// Create React components for materials
|
||||||
const mats = [];
|
const mats = [];
|
||||||
for (const matName of Object.keys(props.warehouse.materials)) {
|
for (const matName of Object.keys(props.warehouse.materials)) {
|
||||||
if (!(props.warehouse.materials[matName] instanceof Material)) continue;
|
if (!props.warehouse.materials[matName]) continue;
|
||||||
// Only create UI for materials that are relevant for the industry or in stock
|
// Only create UI for materials that are relevant for the industry or in stock
|
||||||
const isInStock = props.warehouse.materials[matName].qty > 0;
|
const isInStock = props.warehouse.materials[matName].qty > 0;
|
||||||
const isRelevant = isRelevantMaterial(matName, division);
|
const isRelevant = isRelevantMaterial(matName, division);
|
||||||
@ -115,7 +111,7 @@ function WarehouseRoot(props: IProps): React.ReactElement {
|
|||||||
if (division.makesProducts && Object.keys(division.products).length > 0) {
|
if (division.makesProducts && Object.keys(division.products).length > 0) {
|
||||||
for (const productName of Object.keys(division.products)) {
|
for (const productName of Object.keys(division.products)) {
|
||||||
const product = division.products[productName];
|
const product = division.products[productName];
|
||||||
if (!(product instanceof Product)) continue;
|
if (!product) continue;
|
||||||
products.push(
|
products.push(
|
||||||
<ProductElem rerender={props.rerender} city={props.currentCity} key={productName} product={product} />,
|
<ProductElem rerender={props.rerender} city={props.currentCity} key={productName} product={product} />,
|
||||||
);
|
);
|
||||||
@ -219,7 +215,7 @@ function WarehouseRoot(props: IProps): React.ReactElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function IndustryWarehouse(props: IProps): React.ReactElement {
|
export function IndustryWarehouse(props: IProps): React.ReactElement {
|
||||||
if (props.warehouse instanceof Warehouse) {
|
if (props.warehouse) {
|
||||||
return <WarehouseRoot {...props} />;
|
return <WarehouseRoot {...props} />;
|
||||||
} else {
|
} else {
|
||||||
return <EmptyWarehouse rerender={props.rerender} city={props.currentCity} />;
|
return <EmptyWarehouse rerender={props.rerender} city={props.currentCity} />;
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
|
|
||||||
import { CityTabs } from "./CityTabs";
|
import { CityTabs } from "./CityTabs";
|
||||||
import { IIndustry } from "../IIndustry";
|
import { Industry } from "../Industry";
|
||||||
import { Context, useCorporation } from "./Context";
|
import { Context, useCorporation } from "./Context";
|
||||||
|
|
||||||
import { CityName } from "../../Locations/data/CityNames";
|
import { CityName } from "../../Locations/data/CityNames";
|
||||||
@ -18,7 +18,7 @@ export function MainPanel(props: IProps): React.ReactElement {
|
|||||||
const corp = useCorporation();
|
const corp = useCorporation();
|
||||||
const division =
|
const division =
|
||||||
props.divisionName !== "Overview"
|
props.divisionName !== "Overview"
|
||||||
? corp.divisions.find((division: IIndustry) => division.name === props.divisionName)
|
? corp.divisions.find((division: Industry) => division.name === props.divisionName)
|
||||||
: undefined; // use undefined because find returns undefined
|
: undefined; // use undefined because find returns undefined
|
||||||
|
|
||||||
if (division === undefined) throw new Error("Cannot find division");
|
if (division === undefined) throw new Error("Cannot find division");
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
// (right-side panel in the Industry UI)
|
// (right-side panel in the Industry UI)
|
||||||
import React, { useState } from "react";
|
import React, { useState } from "react";
|
||||||
|
|
||||||
import { OfficeSpace } from "../OfficeSpace";
|
|
||||||
import { Material } from "../Material";
|
import { Material } from "../Material";
|
||||||
import { Warehouse } from "../Warehouse";
|
import { Warehouse } from "../Warehouse";
|
||||||
import { ExportModal } from "./modals/ExportModal";
|
import { ExportModal } from "./modals/ExportModal";
|
||||||
@ -45,7 +44,7 @@ export function MaterialElem(props: IMaterialProps): React.ReactElement {
|
|||||||
const mat = props.mat;
|
const mat = props.mat;
|
||||||
const markupLimit = mat.getMarkupLimit();
|
const markupLimit = mat.getMarkupLimit();
|
||||||
const office = division.offices[city];
|
const office = division.offices[city];
|
||||||
if (!(office instanceof OfficeSpace)) {
|
if (!office) {
|
||||||
throw new Error(`Could not get OfficeSpace object for this city (${city})`);
|
throw new Error(`Could not get OfficeSpace object for this city (${city})`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import { numeralWrapper } from "../../ui/numeralFormat";
|
import { numeralWrapper } from "../../ui/numeralFormat";
|
||||||
import { ICorporation } from "../ICorporation";
|
import { Corporation } from "../Corporation";
|
||||||
import { Theme } from "@mui/material/styles";
|
import { Theme } from "@mui/material/styles";
|
||||||
import makeStyles from "@mui/styles/makeStyles";
|
import makeStyles from "@mui/styles/makeStyles";
|
||||||
import createStyles from "@mui/styles/createStyles";
|
import createStyles from "@mui/styles/createStyles";
|
||||||
@ -18,7 +18,7 @@ const useStyles = makeStyles((theme: Theme) =>
|
|||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
money: number;
|
money: number;
|
||||||
corp: ICorporation;
|
corp: Corporation;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function MoneyCost(props: IProps): React.ReactElement {
|
export function MoneyCost(props: IProps): React.ReactElement {
|
||||||
|
@ -21,7 +21,7 @@ import { convertTimeMsToTimeElapsedString } from "../../utils/StringHelperFuncti
|
|||||||
import { Money } from "../../ui/React/Money";
|
import { Money } from "../../ui/React/Money";
|
||||||
import { MoneyRate } from "../../ui/React/MoneyRate";
|
import { MoneyRate } from "../../ui/React/MoneyRate";
|
||||||
import { StatsTable } from "../../ui/React/StatsTable";
|
import { StatsTable } from "../../ui/React/StatsTable";
|
||||||
import { use } from "../../ui/Context";
|
import { Player } from "../../Player";
|
||||||
import { useCorporation } from "./Context";
|
import { useCorporation } from "./Context";
|
||||||
import Typography from "@mui/material/Typography";
|
import Typography from "@mui/material/Typography";
|
||||||
import Tooltip from "@mui/material/Tooltip";
|
import Tooltip from "@mui/material/Tooltip";
|
||||||
@ -34,7 +34,6 @@ interface IProps {
|
|||||||
rerender: () => void;
|
rerender: () => void;
|
||||||
}
|
}
|
||||||
export function Overview({ rerender }: IProps): React.ReactElement {
|
export function Overview({ rerender }: IProps): React.ReactElement {
|
||||||
const player = use.Player();
|
|
||||||
const corp = useCorporation();
|
const corp = useCorporation();
|
||||||
const profit: number = corp.revenue - corp.expenses;
|
const profit: number = corp.revenue - corp.expenses;
|
||||||
|
|
||||||
@ -100,7 +99,7 @@ export function Overview({ rerender }: IProps): React.ReactElement {
|
|||||||
</Typography>
|
</Typography>
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<Button onClick={() => corp.getStarterGuide(player)}>Getting Started Guide</Button>
|
<Button onClick={() => corp.getStarterGuide()}>Getting Started Guide</Button>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
{corp.public ? <PublicButtons rerender={rerender} /> : <PrivateButtons rerender={rerender} />}
|
{corp.public ? <PublicButtons rerender={rerender} /> : <PrivateButtons rerender={rerender} />}
|
||||||
<BribeButton />
|
<BribeButton />
|
||||||
@ -240,12 +239,11 @@ function PublicButtons({ rerender }: IPublicButtonsProps): React.ReactElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function BribeButton(): React.ReactElement {
|
function BribeButton(): React.ReactElement {
|
||||||
const player = use.Player();
|
|
||||||
const corp = useCorporation();
|
const corp = useCorporation();
|
||||||
const [open, setOpen] = useState(false);
|
const [open, setOpen] = useState(false);
|
||||||
const canBribe =
|
const canBribe =
|
||||||
corp.valuation >= CorporationConstants.BribeThreshold &&
|
corp.valuation >= CorporationConstants.BribeThreshold &&
|
||||||
player.factions.filter((f) => Factions[f].getInfo().offersWork()).length > 0;
|
Player.factions.filter((f) => Factions[f].getInfo().offersWork()).length > 0;
|
||||||
|
|
||||||
function openBribe(): void {
|
function openBribe(): void {
|
||||||
if (!canBribe) return;
|
if (!canBribe) return;
|
||||||
|
@ -4,7 +4,7 @@ import { CorporationConstants } from "../../data/Constants";
|
|||||||
import { numeralWrapper } from "../../../ui/numeralFormat";
|
import { numeralWrapper } from "../../../ui/numeralFormat";
|
||||||
import { dialogBoxCreate } from "../../../ui/React/DialogBox";
|
import { dialogBoxCreate } from "../../../ui/React/DialogBox";
|
||||||
import { Modal } from "../../../ui/React/Modal";
|
import { Modal } from "../../../ui/React/Modal";
|
||||||
import { use } from "../../../ui/Context";
|
import { Player } from "../../../Player";
|
||||||
import { useCorporation } from "../Context";
|
import { useCorporation } from "../Context";
|
||||||
import Typography from "@mui/material/Typography";
|
import Typography from "@mui/material/Typography";
|
||||||
import Button from "@mui/material/Button";
|
import Button from "@mui/material/Button";
|
||||||
@ -19,11 +19,10 @@ interface IProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function BribeFactionModal(props: IProps): React.ReactElement {
|
export function BribeFactionModal(props: IProps): React.ReactElement {
|
||||||
const player = use.Player();
|
const factions = Player.factions.filter((name: string) => {
|
||||||
const factions = player.factions.filter((name: string) => {
|
|
||||||
const info = Factions[name].getInfo();
|
const info = Factions[name].getInfo();
|
||||||
if (!info.offersWork()) return false;
|
if (!info.offersWork()) return false;
|
||||||
if (player.hasGangWith(name)) return false;
|
if (Player.hasGangWith(name)) return false;
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
const corp = useCorporation();
|
const corp = useCorporation();
|
||||||
@ -60,9 +59,7 @@ export function BribeFactionModal(props: IProps): React.ReactElement {
|
|||||||
const fac = Factions[selectedFaction];
|
const fac = Factions[selectedFaction];
|
||||||
if (disabled) return;
|
if (disabled) return;
|
||||||
const rep = repGain(money);
|
const rep = repGain(money);
|
||||||
dialogBoxCreate(
|
dialogBoxCreate(`You gained ${numeralWrapper.formatReputation(rep)} reputation with ${fac.name} by bribing them.`);
|
||||||
"You gained " + numeralWrapper.formatReputation(rep) + " reputation with " + fac.name + " by bribing them.",
|
|
||||||
);
|
|
||||||
fac.playerReputation += rep;
|
fac.playerReputation += rep;
|
||||||
corp.funds = corp.funds - money;
|
corp.funds = corp.funds - money;
|
||||||
props.onClose();
|
props.onClose();
|
||||||
@ -79,7 +76,7 @@ export function BribeFactionModal(props: IProps): React.ReactElement {
|
|||||||
{factions.map((name: string) => {
|
{factions.map((name: string) => {
|
||||||
const info = Factions[name].getInfo();
|
const info = Factions[name].getInfo();
|
||||||
if (!info.offersWork()) return;
|
if (!info.offersWork()) return;
|
||||||
if (player.hasGangWith(name)) return;
|
if (Player.hasGangWith(name)) return;
|
||||||
return (
|
return (
|
||||||
<MenuItem key={name} value={name}>
|
<MenuItem key={name} value={name}>
|
||||||
{name}
|
{name}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import React, { useState } from "react";
|
import React, { useState } from "react";
|
||||||
import { Modal } from "../../../ui/React/Modal";
|
import { Modal } from "../../../ui/React/Modal";
|
||||||
import { numeralWrapper } from "../../../ui/numeralFormat";
|
import { numeralWrapper } from "../../../ui/numeralFormat";
|
||||||
import { use } from "../../../ui/Context";
|
import { Player } from "../../../Player";
|
||||||
import { useCorporation } from "../Context";
|
import { useCorporation } from "../Context";
|
||||||
import Typography from "@mui/material/Typography";
|
import Typography from "@mui/material/Typography";
|
||||||
import Button from "@mui/material/Button";
|
import Button from "@mui/material/Button";
|
||||||
@ -19,7 +19,6 @@ interface IProps {
|
|||||||
// Create a popup that lets the player buyback shares
|
// Create a popup that lets the player buyback shares
|
||||||
// This is created when the player clicks the "Buyback Shares" button in the overview panel
|
// This is created when the player clicks the "Buyback Shares" button in the overview panel
|
||||||
export function BuybackSharesModal(props: IProps): React.ReactElement {
|
export function BuybackSharesModal(props: IProps): React.ReactElement {
|
||||||
const player = use.Player();
|
|
||||||
const corp = useCorporation();
|
const corp = useCorporation();
|
||||||
const [shares, setShares] = useState<number>(NaN);
|
const [shares, setShares] = useState<number>(NaN);
|
||||||
|
|
||||||
@ -30,12 +29,12 @@ export function BuybackSharesModal(props: IProps): React.ReactElement {
|
|||||||
isNaN(shares) ||
|
isNaN(shares) ||
|
||||||
shares <= 0 ||
|
shares <= 0 ||
|
||||||
shares > corp.issuedShares ||
|
shares > corp.issuedShares ||
|
||||||
shares * buybackPrice > player.money;
|
shares * buybackPrice > Player.money;
|
||||||
|
|
||||||
function buy(): void {
|
function buy(): void {
|
||||||
if (disabled) return;
|
if (disabled) return;
|
||||||
try {
|
try {
|
||||||
BuyBackShares(corp, player, shares);
|
BuyBackShares(corp, shares);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
dialogBoxCreate(err + "");
|
dialogBoxCreate(err + "");
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,8 @@ import React, { useState } from "react";
|
|||||||
|
|
||||||
import { Money } from "../../../ui/React/Money";
|
import { Money } from "../../../ui/React/Money";
|
||||||
import { Modal } from "../../../ui/React/Modal";
|
import { Modal } from "../../../ui/React/Modal";
|
||||||
import { use } from "../../../ui/Context";
|
import { Router } from "../../../ui/GameRoot";
|
||||||
|
import { Player } from "../../../Player";
|
||||||
import Typography from "@mui/material/Typography";
|
import Typography from "@mui/material/Typography";
|
||||||
import Button from "@mui/material/Button";
|
import Button from "@mui/material/Button";
|
||||||
import TextField from "@mui/material/TextField";
|
import TextField from "@mui/material/TextField";
|
||||||
@ -13,10 +14,8 @@ interface IProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function CreateCorporationModal(props: IProps): React.ReactElement {
|
export function CreateCorporationModal(props: IProps): React.ReactElement {
|
||||||
const player = use.Player();
|
const canSelfFund = Player.canAfford(150e9);
|
||||||
const router = use.Router();
|
if (!Player.canAccessCorporation() || Player.hasCorporation()) {
|
||||||
const canSelfFund = player.canAfford(150e9);
|
|
||||||
if (!player.canAccessCorporation() || player.hasCorporation()) {
|
|
||||||
props.onClose();
|
props.onClose();
|
||||||
return <></>;
|
return <></>;
|
||||||
}
|
}
|
||||||
@ -35,11 +34,11 @@ export function CreateCorporationModal(props: IProps): React.ReactElement {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
player.startCorporation(name);
|
Player.startCorporation(name);
|
||||||
player.loseMoney(150e9, "corporation");
|
Player.loseMoney(150e9, "corporation");
|
||||||
|
|
||||||
props.onClose();
|
props.onClose();
|
||||||
router.toCorporation();
|
Router.toCorporation();
|
||||||
}
|
}
|
||||||
|
|
||||||
function seed(): void {
|
function seed(): void {
|
||||||
@ -47,17 +46,17 @@ export function CreateCorporationModal(props: IProps): React.ReactElement {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
player.startCorporation(name, 500e6);
|
Player.startCorporation(name, 500e6);
|
||||||
|
|
||||||
props.onClose();
|
props.onClose();
|
||||||
router.toCorporation();
|
Router.toCorporation();
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Modal open={props.open} onClose={props.onClose}>
|
<Modal open={props.open} onClose={props.onClose}>
|
||||||
<Typography>
|
<Typography>
|
||||||
Would you like to start a corporation? This will require $150b for registration and initial funding.{" "}
|
Would you like to start a corporation? This will require $150b for registration and initial funding.{" "}
|
||||||
{player.bitNodeN === 3 &&
|
{Player.bitNodeN === 3 &&
|
||||||
`This $150b
|
`This $150b
|
||||||
can either be self-funded, or you can obtain the seed money from the government in exchange for 500 million
|
can either be self-funded, or you can obtain the seed money from the government in exchange for 500 million
|
||||||
shares`}
|
shares`}
|
||||||
@ -66,13 +65,13 @@ export function CreateCorporationModal(props: IProps): React.ReactElement {
|
|||||||
If you would like to start one, please enter a name for your corporation below:
|
If you would like to start one, please enter a name for your corporation below:
|
||||||
</Typography>
|
</Typography>
|
||||||
<TextField autoFocus={true} placeholder="Corporation Name" onChange={onChange} value={name} />
|
<TextField autoFocus={true} placeholder="Corporation Name" onChange={onChange} value={name} />
|
||||||
{player.bitNodeN === 3 && (
|
{Player.bitNodeN === 3 && (
|
||||||
<Button onClick={seed} disabled={name == ""}>
|
<Button onClick={seed} disabled={name == ""}>
|
||||||
Use seed money
|
Use seed money
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
<Button onClick={selfFund} disabled={name == "" || !canSelfFund}>
|
<Button onClick={selfFund} disabled={name == "" || !canSelfFund}>
|
||||||
Self-Fund (<Money money={150e9} player={player} />)
|
Self-Fund (<Money money={150e9} forPurchase={true} />)
|
||||||
</Button>
|
</Button>
|
||||||
</Modal>
|
</Modal>
|
||||||
);
|
);
|
||||||
|
@ -2,7 +2,7 @@ import React, { useState } from "react";
|
|||||||
import { dialogBoxCreate } from "../../../ui/React/DialogBox";
|
import { dialogBoxCreate } from "../../../ui/React/DialogBox";
|
||||||
import { Material } from "../../Material";
|
import { Material } from "../../Material";
|
||||||
import { Export } from "../../Export";
|
import { Export } from "../../Export";
|
||||||
import { IIndustry } from "../../IIndustry";
|
import { Industry } from "../../Industry";
|
||||||
import { ExportMaterial } from "../../Actions";
|
import { ExportMaterial } from "../../Actions";
|
||||||
import { Modal } from "../../../ui/React/Modal";
|
import { Modal } from "../../../ui/React/Modal";
|
||||||
import { useCorporation } from "../Context";
|
import { useCorporation } from "../Context";
|
||||||
@ -23,9 +23,7 @@ interface IProps {
|
|||||||
// Create a popup that lets the player manage exports
|
// Create a popup that lets the player manage exports
|
||||||
export function ExportModal(props: IProps): React.ReactElement {
|
export function ExportModal(props: IProps): React.ReactElement {
|
||||||
const corp = useCorporation();
|
const corp = useCorporation();
|
||||||
const possibleDivisions = corp.divisions.filter((division: IIndustry) =>
|
const possibleDivisions = corp.divisions.filter((division: Industry) => isRelevantMaterial(props.mat.name, division));
|
||||||
isRelevantMaterial(props.mat.name, division),
|
|
||||||
);
|
|
||||||
if (possibleDivisions.length === 0) throw new Error("Export popup created with no divisions.");
|
if (possibleDivisions.length === 0) throw new Error("Export popup created with no divisions.");
|
||||||
const defaultDivision = possibleDivisions[0];
|
const defaultDivision = possibleDivisions[0];
|
||||||
if (Object.keys(defaultDivision.warehouses).length === 0)
|
if (Object.keys(defaultDivision.warehouses).length === 0)
|
||||||
@ -72,7 +70,7 @@ export function ExportModal(props: IProps): React.ReactElement {
|
|||||||
rerender();
|
rerender();
|
||||||
}
|
}
|
||||||
|
|
||||||
const currentDivision = corp.divisions.find((division: IIndustry) => division.name === industry);
|
const currentDivision = corp.divisions.find((division: Industry) => division.name === industry);
|
||||||
if (currentDivision === undefined)
|
if (currentDivision === undefined)
|
||||||
throw new Error(`Export popup somehow ended up with undefined division '${currentDivision}'`);
|
throw new Error(`Export popup somehow ended up with undefined division '${currentDivision}'`);
|
||||||
const possibleCities = Object.keys(currentDivision.warehouses).filter(
|
const possibleCities = Object.keys(currentDivision.warehouses).filter(
|
||||||
@ -90,8 +88,8 @@ export function ExportModal(props: IProps): React.ReactElement {
|
|||||||
</Typography>
|
</Typography>
|
||||||
<Select onChange={onIndustryChange} value={industry}>
|
<Select onChange={onIndustryChange} value={industry}>
|
||||||
{corp.divisions
|
{corp.divisions
|
||||||
.filter((division: IIndustry) => isRelevantMaterial(props.mat.name, division))
|
.filter((division: Industry) => isRelevantMaterial(props.mat.name, division))
|
||||||
.map((division: IIndustry) => (
|
.map((division: Industry) => (
|
||||||
<MenuItem key={division.name} value={division.name}>
|
<MenuItem key={division.name} value={division.name}>
|
||||||
{division.name}
|
{division.name}
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
|
@ -89,14 +89,11 @@ export function IssueNewSharesModal(props: IProps): React.ReactElement {
|
|||||||
|
|
||||||
let dialogContents =
|
let dialogContents =
|
||||||
`Issued ${numeralWrapper.format(newShares, "0.000a")} new shares` +
|
`Issued ${numeralWrapper.format(newShares, "0.000a")} new shares` +
|
||||||
` and raised ${numeralWrapper.formatMoney(profit)}.`;
|
` and raised ${numeralWrapper.formatMoney(profit)}.` +
|
||||||
if (privateShares > 0) {
|
(privateShares > 0)
|
||||||
dialogContents += `<br>${numeralWrapper.format(
|
? "\n" + numeralWrapper.format(privateShares, "0.000a") + "of these shares were bought by private investors."
|
||||||
privateShares,
|
: "";
|
||||||
"0.000a",
|
dialogContents += `\n\nStock price decreased to ${numeralWrapper.formatMoney(corp.sharePrice)}`;
|
||||||
)} of these shares were bought by private investors.`;
|
|
||||||
}
|
|
||||||
dialogContents += `<br><br>Stock price decreased to ${numeralWrapper.formatMoney(corp.sharePrice)}`;
|
|
||||||
dialogBoxCreate(dialogContents);
|
dialogBoxCreate(dialogContents);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@ import React, { useState } from "react";
|
|||||||
import { Modal } from "../../../ui/React/Modal";
|
import { Modal } from "../../../ui/React/Modal";
|
||||||
import { IndustryResearchTrees } from "../../IndustryData";
|
import { IndustryResearchTrees } from "../../IndustryData";
|
||||||
import { CorporationConstants } from "../../data/Constants";
|
import { CorporationConstants } from "../../data/Constants";
|
||||||
import { IIndustry } from "../../IIndustry";
|
import { Industry } from "../../Industry";
|
||||||
import { Research } from "../../Actions";
|
import { Research } from "../../Actions";
|
||||||
import { Node } from "../../ResearchTree";
|
import { Node } from "../../ResearchTree";
|
||||||
import { ResearchMap } from "../../ResearchMap";
|
import { ResearchMap } from "../../ResearchMap";
|
||||||
@ -20,7 +20,7 @@ import CheckIcon from "@mui/icons-material/Check";
|
|||||||
|
|
||||||
interface INodeProps {
|
interface INodeProps {
|
||||||
n: Node | null;
|
n: Node | null;
|
||||||
division: IIndustry;
|
division: Industry;
|
||||||
}
|
}
|
||||||
function Upgrade({ n, division }: INodeProps): React.ReactElement {
|
function Upgrade({ n, division }: INodeProps): React.ReactElement {
|
||||||
const [open, setOpen] = useState(false);
|
const [open, setOpen] = useState(false);
|
||||||
@ -42,9 +42,7 @@ function Upgrade({ n, division }: INodeProps): React.ReactElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dialogBoxCreate(
|
dialogBoxCreate(
|
||||||
`Researched ${n.text}. It may take a market cycle ` +
|
`Researched ${n.text}. It may take a market cycle (~${CorporationConstants.SecsPerMarketCycle} seconds) before the effects of the Research apply.`,
|
||||||
`(~${CorporationConstants.SecsPerMarketCycle} seconds) before the effects of ` +
|
|
||||||
`the Research apply.`,
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -131,7 +129,7 @@ function Upgrade({ n, division }: INodeProps): React.ReactElement {
|
|||||||
interface IProps {
|
interface IProps {
|
||||||
open: boolean;
|
open: boolean;
|
||||||
onClose: () => void;
|
onClose: () => void;
|
||||||
industry: IIndustry;
|
industry: Industry;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create the Research Tree UI for this Industry
|
// Create the Research Tree UI for this Industry
|
||||||
|
@ -2,9 +2,8 @@ import React, { useState } from "react";
|
|||||||
import { numeralWrapper } from "../../../ui/numeralFormat";
|
import { numeralWrapper } from "../../../ui/numeralFormat";
|
||||||
import { dialogBoxCreate } from "../../../ui/React/DialogBox";
|
import { dialogBoxCreate } from "../../../ui/React/DialogBox";
|
||||||
import { Modal } from "../../../ui/React/Modal";
|
import { Modal } from "../../../ui/React/Modal";
|
||||||
import { use } from "../../../ui/Context";
|
|
||||||
import { useCorporation } from "../Context";
|
import { useCorporation } from "../Context";
|
||||||
import { ICorporation } from "../../ICorporation";
|
import { Corporation } from "../../Corporation";
|
||||||
import Typography from "@mui/material/Typography";
|
import Typography from "@mui/material/Typography";
|
||||||
import Button from "@mui/material/Button";
|
import Button from "@mui/material/Button";
|
||||||
import { Money } from "../../../ui/React/Money";
|
import { Money } from "../../../ui/React/Money";
|
||||||
@ -20,13 +19,12 @@ interface IProps {
|
|||||||
// Create a popup that lets the player sell Corporation shares
|
// Create a popup that lets the player sell Corporation shares
|
||||||
// This is created when the player clicks the "Sell Shares" button in the overview panel
|
// This is created when the player clicks the "Sell Shares" button in the overview panel
|
||||||
export function SellSharesModal(props: IProps): React.ReactElement {
|
export function SellSharesModal(props: IProps): React.ReactElement {
|
||||||
const player = use.Player();
|
|
||||||
const corp = useCorporation();
|
const corp = useCorporation();
|
||||||
const [shares, setShares] = useState<number>(NaN);
|
const [shares, setShares] = useState<number>(NaN);
|
||||||
|
|
||||||
const disabled = isNaN(shares) || shares <= 0 || shares > corp.numShares;
|
const disabled = isNaN(shares) || shares <= 0 || shares > corp.numShares;
|
||||||
|
|
||||||
function ProfitIndicator(props: { shares: number | null; corp: ICorporation }): React.ReactElement {
|
function ProfitIndicator(props: { shares: number | null; corp: Corporation }): React.ReactElement {
|
||||||
if (props.shares === null) return <></>;
|
if (props.shares === null) return <></>;
|
||||||
let text = "";
|
let text = "";
|
||||||
if (isNaN(props.shares) || props.shares <= 0) {
|
if (isNaN(props.shares) || props.shares <= 0) {
|
||||||
@ -49,7 +47,7 @@ export function SellSharesModal(props: IProps): React.ReactElement {
|
|||||||
function sell(): void {
|
function sell(): void {
|
||||||
if (disabled) return;
|
if (disabled) return;
|
||||||
try {
|
try {
|
||||||
const profit = SellShares(corp, player, shares);
|
const profit = SellShares(corp, shares);
|
||||||
props.onClose();
|
props.onClose();
|
||||||
dialogBoxCreate(
|
dialogBoxCreate(
|
||||||
<>
|
<>
|
||||||
|
@ -2,7 +2,6 @@ import React, { useState } from "react";
|
|||||||
|
|
||||||
import { Warehouse } from "../../Warehouse";
|
import { Warehouse } from "../../Warehouse";
|
||||||
import { SetSmartSupply, SetSmartSupplyUseLeftovers } from "../../Actions";
|
import { SetSmartSupply, SetSmartSupplyUseLeftovers } from "../../Actions";
|
||||||
import { Material } from "../../Material";
|
|
||||||
import { dialogBoxCreate } from "../../../ui/React/DialogBox";
|
import { dialogBoxCreate } from "../../../ui/React/DialogBox";
|
||||||
import { Modal } from "../../../ui/React/Modal";
|
import { Modal } from "../../../ui/React/Modal";
|
||||||
import { useDivision } from "../Context";
|
import { useDivision } from "../Context";
|
||||||
@ -62,7 +61,7 @@ export function SmartSupplyModal(props: IProps): React.ReactElement {
|
|||||||
// Create React components for materials
|
// Create React components for materials
|
||||||
const mats = [];
|
const mats = [];
|
||||||
for (const matName of Object.keys(props.warehouse.materials)) {
|
for (const matName of Object.keys(props.warehouse.materials)) {
|
||||||
if (!(props.warehouse.materials[matName] instanceof Material)) continue;
|
if (!props.warehouse.materials[matName]) continue;
|
||||||
if (!Object.keys(division.reqMats).includes(matName)) continue;
|
if (!Object.keys(division.reqMats).includes(matName)) continue;
|
||||||
mats.push(<Leftover key={matName} warehouse={props.warehouse} matName={matName} />);
|
mats.push(<Leftover key={matName} warehouse={props.warehouse} matName={matName} />);
|
||||||
}
|
}
|
||||||
|
@ -41,8 +41,7 @@ export function ThrowPartyModal(props: IProps): React.ReactElement {
|
|||||||
|
|
||||||
if (mult > 0) {
|
if (mult > 0) {
|
||||||
dialogBoxCreate(
|
dialogBoxCreate(
|
||||||
"You threw a party for the office! The morale and happiness " +
|
"You threw a party for the office! The morale and happiness of each employee increased by " +
|
||||||
"of each employee increased by " +
|
|
||||||
numeralWrapper.formatPercentage(mult - 1),
|
numeralWrapper.formatPercentage(mult - 1),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@ import React from "react";
|
|||||||
import { numeralWrapper } from "../../../ui/numeralFormat";
|
import { numeralWrapper } from "../../../ui/numeralFormat";
|
||||||
import { CorporationConstants } from "../../data/Constants";
|
import { CorporationConstants } from "../../data/Constants";
|
||||||
import { OfficeSpace } from "../../OfficeSpace";
|
import { OfficeSpace } from "../../OfficeSpace";
|
||||||
import { ICorporation } from "../../ICorporation";
|
import { Corporation } from "../../Corporation";
|
||||||
import { UpgradeOfficeSize } from "../../Actions";
|
import { UpgradeOfficeSize } from "../../Actions";
|
||||||
import { Modal } from "../../../ui/React/Modal";
|
import { Modal } from "../../../ui/React/Modal";
|
||||||
import { useCorporation } from "../Context";
|
import { useCorporation } from "../Context";
|
||||||
@ -14,7 +14,7 @@ import Box from "@mui/material/Box";
|
|||||||
interface IUpgradeButton {
|
interface IUpgradeButton {
|
||||||
cost: number;
|
cost: number;
|
||||||
size: number;
|
size: number;
|
||||||
corp: ICorporation;
|
corp: Corporation;
|
||||||
office: OfficeSpace;
|
office: OfficeSpace;
|
||||||
onClose: () => void;
|
onClose: () => void;
|
||||||
rerender: () => void;
|
rerender: () => void;
|
||||||
|
29
src/CotMG/BaseGift.ts
Normal file
29
src/CotMG/BaseGift.ts
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
import { ActiveFragment } from "./ActiveFragment";
|
||||||
|
|
||||||
|
export class BaseGift {
|
||||||
|
fragments: ActiveFragment[];
|
||||||
|
_width?: number;
|
||||||
|
_height?: number;
|
||||||
|
|
||||||
|
constructor(width?: number, height?: number, fragments: ActiveFragment[] = []) {
|
||||||
|
this.fragments = fragments;
|
||||||
|
this._width = width;
|
||||||
|
this._height = height;
|
||||||
|
}
|
||||||
|
|
||||||
|
width(): number {
|
||||||
|
return this._width || 4;
|
||||||
|
}
|
||||||
|
height(): number {
|
||||||
|
return this._height || 4;
|
||||||
|
}
|
||||||
|
fragmentAt(worldX: number, worldY: number): ActiveFragment | undefined {
|
||||||
|
for (const aFrag of this.fragments) {
|
||||||
|
if (aFrag.fullAt(worldX, worldY)) {
|
||||||
|
return aFrag;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
}
|
@ -1,67 +0,0 @@
|
|||||||
import { ActiveFragment } from "./ActiveFragment";
|
|
||||||
import { IStaneksGift } from "./IStaneksGift";
|
|
||||||
|
|
||||||
export class DummyGift implements IStaneksGift {
|
|
||||||
storedCycles = 0;
|
|
||||||
fragments: ActiveFragment[] = [];
|
|
||||||
_width: number;
|
|
||||||
_height: number;
|
|
||||||
|
|
||||||
constructor(width: number, height: number, fragments: ActiveFragment[]) {
|
|
||||||
this.fragments = fragments;
|
|
||||||
this._width = width;
|
|
||||||
this._height = height;
|
|
||||||
}
|
|
||||||
|
|
||||||
width(): number {
|
|
||||||
return this._width;
|
|
||||||
}
|
|
||||||
height(): number {
|
|
||||||
return this._height;
|
|
||||||
}
|
|
||||||
charge(): void {
|
|
||||||
throw new Error("unimplemented for dummy gift");
|
|
||||||
}
|
|
||||||
process(): void {
|
|
||||||
throw new Error("unimplemented for dummy gift");
|
|
||||||
}
|
|
||||||
effect(): number {
|
|
||||||
throw new Error("unimplemented for dummy gift");
|
|
||||||
}
|
|
||||||
canPlace(): boolean {
|
|
||||||
throw new Error("unimplemented for dummy gift");
|
|
||||||
}
|
|
||||||
place(): boolean {
|
|
||||||
throw new Error("unimplemented for dummy gift");
|
|
||||||
}
|
|
||||||
findFragment(): ActiveFragment | undefined {
|
|
||||||
throw new Error("unimplemented for dummy gift");
|
|
||||||
}
|
|
||||||
fragmentAt(worldX: number, worldY: number): ActiveFragment | undefined {
|
|
||||||
for (const aFrag of this.fragments) {
|
|
||||||
if (aFrag.fullAt(worldX, worldY)) {
|
|
||||||
return aFrag;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
delete(): boolean {
|
|
||||||
throw new Error("unimplemented for dummy gift");
|
|
||||||
}
|
|
||||||
clear(): void {
|
|
||||||
throw new Error("unimplemented for dummy gift");
|
|
||||||
}
|
|
||||||
count(): number {
|
|
||||||
throw new Error("unimplemented for dummy gift");
|
|
||||||
}
|
|
||||||
inBonus(): boolean {
|
|
||||||
throw new Error("unimplemented for dummy gift");
|
|
||||||
}
|
|
||||||
prestigeAugmentation(): void {
|
|
||||||
throw new Error("unimplemented for dummy gift");
|
|
||||||
}
|
|
||||||
prestigeSourceFile(): void {
|
|
||||||
throw new Error("unimplemented for dummy gift");
|
|
||||||
}
|
|
||||||
}
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user