diff --git a/.github/PULL_REQUEST_TEMPLATE b/.github/PULL_REQUEST_TEMPLATE
index fe4a745c6..5e99eddd2 100644
--- a/.github/PULL_REQUEST_TEMPLATE
+++ b/.github/PULL_REQUEST_TEMPLATE
@@ -5,16 +5,20 @@
# PR title
Formatted as such:
-SECTION: FIX #xzyw PLAYER DESCRIPTION
+SECTION: PLAYER DESCRIPTION
SECTION is something like "API", "UI", "MISC", "STANEK", "CORPORATION"
-FIX #xyzw is the issue number, if any
PLAYER DESCRIPTION is what you'd tell a non-contributor to convey what is changed.
# Linked issues
If your pull request is related to a git issue, please link it in the description using #xyz.
-If your PR should close the issue when it is merged in, use `fixes #xyz` or `closes #xyz`. It'll automate the process.
+If your PR should close the issue when it is merged in, use `fixes #xyz` or `closes #xyz` like this:
+
+closes #xxxx
+closes #yyyy
+
+It'll automate the process.
# Documentation
diff --git a/markdown/bitburner.sleeve.settobladeburneraction.md b/markdown/bitburner.sleeve.settobladeburneraction.md
index 3d9bf246c..02ae7c814 100644
--- a/markdown/bitburner.sleeve.settobladeburneraction.md
+++ b/markdown/bitburner.sleeve.settobladeburneraction.md
@@ -16,7 +16,7 @@ setToBladeburnerAction(sleeveNumber: number, action: string, contract?: string):
| Parameter | Type | Description |
| --- | --- | --- |
-| sleeveNumber | number | Index of the sleeve to workout at the gym. |
+| sleeveNumber | number | Index of the sleeve which will perform Action. |
| action | string | Name of the action to be performed. |
| contract | string | Name of the contract if applicable. |
diff --git a/src/Augmentation/data/AugmentationCreator.tsx b/src/Augmentation/data/AugmentationCreator.tsx
index e21aca702..19a086fc5 100644
--- a/src/Augmentation/data/AugmentationCreator.tsx
+++ b/src/Augmentation/data/AugmentationCreator.tsx
@@ -1661,17 +1661,17 @@ export const initGeneralAugmentations = (): Augmentation[] => [
}),
// Sleeve exclusive augmentations
- new Augmentation({
- name: AugmentationNames.UnnamedAug1,
- isSpecial: true,
- repCost: Infinity,
- moneyCost: 1e12,
- info: "This augmentation is exclusive to sleeves.",
- stats: <>Allows sleeves to benefit from Stanek's Gift but it is less powerful if several are installed.>,
- factions: [
- /*Technically in FactionNames.ChurchOfTheMachineGod but not really for display reasons */
- ],
- }),
+ // new Augmentation({
+ // name: AugmentationNames.UnnamedAug1,
+ // isSpecial: true,
+ // repCost: Infinity,
+ // moneyCost: 1e12,
+ // info: "This augmentation is exclusive to sleeves.",
+ // stats: <>Allows sleeves to benefit from Stanek's Gift but it is less powerful if several are installed.>,
+ // factions: [
+ // /*Technically in FactionNames.ChurchOfTheMachineGod but not really for display reasons */
+ // ],
+ // }),
];
export const initBladeburnerAugmentations = (): Augmentation[] => [
diff --git a/src/Corporation/Actions.ts b/src/Corporation/Actions.ts
index fbcad46f3..bf53d1e2f 100644
--- a/src/Corporation/Actions.ts
+++ b/src/Corporation/Actions.ts
@@ -1,6 +1,8 @@
+import { Player } from "../Player";
import { IPlayer } from "src/PersonObjects/IPlayer";
import { MaterialSizes } from "./MaterialSizes";
import { ICorporation } from "./ICorporation";
+import { Corporation } from "./Corporation";
import { IIndustry } from "./IIndustry";
import { IndustryStartingCosts, IndustryResearchTrees } from "./IndustryData";
import { Industry } from "./Industry";
@@ -463,6 +465,23 @@ export function Research(division: IIndustry, researchName: string): void {
// Get the Node from the Research Tree and set its 'researched' property
researchTree.research(researchName);
division.researched[researchName] = true;
+
+ // I couldn't figure out where else to put this so that warehouse size would get updated instantly
+ // whether research is done by script or UI. All other stats gets calculated in every cycle
+ // Warehouse size gets updated only when something increases it.
+ if (researchName == "Drones - Transport") {
+ for (let i = 0; i < CorporationConstants.Cities.length; ++i) {
+ const city = CorporationConstants.Cities[i];
+ const warehouse = division.warehouses[city];
+ if (!(warehouse instanceof Warehouse)) {
+ continue;
+ }
+ if (Player.corporation instanceof Corporation) {
+ // Stores cycles in a "buffer". Processed separately using Engine Counters
+ warehouse.updateSize(Player.corporation, division);
+ }
+ }
+ }
}
export function ExportMaterial(
diff --git a/src/Corporation/Corporation.tsx b/src/Corporation/Corporation.tsx
index b6acdadfa..cf6ac9125 100644
--- a/src/Corporation/Corporation.tsx
+++ b/src/Corporation/Corporation.tsx
@@ -83,6 +83,10 @@ export class Corporation {
const gameCycles = marketCycles * CorporationConstants.CyclesPerIndustryStateCycle;
this.storedCycles -= gameCycles;
+ this.divisions.forEach((ind) => {
+ ind.resetImports(state);
+ });
+
this.divisions.forEach((ind) => {
ind.process(marketCycles, state, this);
});
@@ -230,6 +234,7 @@ export class Corporation {
let sharePrice = this.sharePrice;
let sharesSold = 0;
let profit = 0;
+ let targetPrice = this.getTargetSharePrice();
const maxIterations = Math.ceil(numShares / CorporationConstants.SHARESPERPRICEUPDATE);
if (isNaN(maxIterations) || maxIterations > 10e6) {
@@ -249,9 +254,13 @@ export class Corporation {
sharesUntilUpdate = CorporationConstants.SHARESPERPRICEUPDATE;
sharesTracker -= sharesUntilUpdate;
sharesSold += sharesUntilUpdate;
-
+ targetPrice = this.valuation / (2 * (this.totalShares + sharesSold - this.numShares));
// Calculate what new share price would be
- sharePrice = this.valuation / (2 * (this.totalShares + sharesSold - this.numShares));
+ if (sharePrice <= targetPrice) {
+ sharePrice *= 1 + 0.5 * 0.01;
+ } else {
+ sharePrice *= 1 - 0.5 * 0.01;
+ }
}
}
diff --git a/src/Corporation/IIndustry.ts b/src/Corporation/IIndustry.ts
index 463af4bdf..0ea8646a1 100644
--- a/src/Corporation/IIndustry.ts
+++ b/src/Corporation/IIndustry.ts
@@ -54,6 +54,7 @@ export interface IIndustry {
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;
diff --git a/src/Corporation/Industry.ts b/src/Corporation/Industry.ts
index 083dd484a..8ec68f26f 100644
--- a/src/Corporation/Industry.ts
+++ b/src/Corporation/Industry.ts
@@ -523,24 +523,6 @@ export class Industry implements IIndustry {
expenses = 0;
this.calculateProductionFactors();
- //At the start of the export state, set the imports of everything to 0
- if (this.state === "EXPORT") {
- for (let i = 0; i < CorporationConstants.Cities.length; ++i) {
- const city = CorporationConstants.Cities[i];
- if (!(this.warehouses[city] instanceof Warehouse)) {
- continue;
- }
- const warehouse = this.warehouses[city];
- if (warehouse === 0) continue;
- for (const matName of Object.keys(warehouse.materials)) {
- if (warehouse.materials.hasOwnProperty(matName)) {
- const mat = warehouse.materials[matName];
- mat.imp = 0;
- }
- }
- }
- }
-
for (let i = 0; i < CorporationConstants.Cities.length; ++i) {
const city = CorporationConstants.Cities[i];
const office = this.offices[city];
@@ -1236,6 +1218,26 @@ export class Industry implements IIndustry {
return totalProfit;
}
+ resetImports(state: string): void {
+ //At the start of the export state, set the imports of everything to 0
+ if (state === "EXPORT") {
+ for (let i = 0; i < CorporationConstants.Cities.length; ++i) {
+ const city = CorporationConstants.Cities[i];
+ if (!(this.warehouses[city] instanceof Warehouse)) {
+ continue;
+ }
+ const warehouse = this.warehouses[city];
+ if (warehouse === 0) continue;
+ for (const matName of Object.keys(warehouse.materials)) {
+ if (warehouse.materials.hasOwnProperty(matName)) {
+ const mat = warehouse.materials[matName];
+ mat.imp = 0;
+ }
+ }
+ }
+ }
+ }
+
discontinueProduct(product: Product): void {
for (const productName of Object.keys(this.products)) {
if (this.products.hasOwnProperty(productName)) {
diff --git a/src/Corporation/ui/modals/IssueNewSharesModal.tsx b/src/Corporation/ui/modals/IssueNewSharesModal.tsx
index eee79a300..85c7f8b97 100644
--- a/src/Corporation/ui/modals/IssueNewSharesModal.tsx
+++ b/src/Corporation/ui/modals/IssueNewSharesModal.tsx
@@ -110,7 +110,7 @@ export function IssueNewSharesModal(props: IProps): React.ReactElement {
You can issue new equity shares (i.e. stocks) in order to raise capital for your corporation.
- * You can issue at most {numeralWrapper.formatMoney(maxNewShares)} new shares
+ * You can issue at most {numeralWrapper.format(maxNewShares, "0.000a")} new shares
* New shares are sold at a 10% discount
diff --git a/src/NetscriptFunctions/Singularity.ts b/src/NetscriptFunctions/Singularity.ts
index e5f51dd0f..c3b1adf16 100644
--- a/src/NetscriptFunctions/Singularity.ts
+++ b/src/NetscriptFunctions/Singularity.ts
@@ -954,7 +954,7 @@ export function NetscriptSingularity(): InternalAPI {
// if the player is in a gang and the target faction is any of the gang faction, fail
if (player.inGang() && faction.name === player.getGangFaction().name) {
- helpers.log(ctx, () => `You can't work for '${facName}' because youre managing a gang for it`);
+ helpers.log(ctx, () => `You can't work for '${facName}' because you're managing a gang for it.`);
return false;
}
diff --git a/src/PersonObjects/Sleeve/SleeveHelpers.ts b/src/PersonObjects/Sleeve/SleeveHelpers.ts
index 279388968..8bdf95fcc 100644
--- a/src/PersonObjects/Sleeve/SleeveHelpers.ts
+++ b/src/PersonObjects/Sleeve/SleeveHelpers.ts
@@ -2,12 +2,14 @@ import { FactionNames } from "../../Faction/data/FactionNames";
import { Sleeve } from "./Sleeve";
import { IPlayer } from "../IPlayer";
+import { Player } from "../../Player";
import { Augmentation } from "../../Augmentation/Augmentation";
import { StaticAugmentations } from "../../Augmentation/StaticAugmentations";
import { Factions } from "../../Faction/Factions";
import { Multipliers } from "../Multipliers";
import { AugmentationNames } from "../../Augmentation/data/AugmentationNames";
+import { getFactionAugmentationsFiltered } from "../../Faction/FactionHelpers";
export function findSleevePurchasableAugs(sleeve: Sleeve, p: IPlayer): Augmentation[] {
// You can only purchase Augmentations that are actually available from
@@ -55,8 +57,9 @@ export function findSleevePurchasableAugs(sleeve: Sleeve, p: IPlayer): Augmentat
// has enough reputation for (since that gang offers all augs)
if (p.inGang()) {
const fac = p.getGangFaction();
+ const gangAugs = getFactionAugmentationsFiltered(Player, fac);
- for (const augName of Object.keys(StaticAugmentations)) {
+ for (const augName of gangAugs) {
const aug = StaticAugmentations[augName];
if (!isAvailableForSleeve(aug)) continue;
diff --git a/src/PersonObjects/Sleeve/ui/FAQModal.tsx b/src/PersonObjects/Sleeve/ui/FAQModal.tsx
index e796f46c2..47488c57b 100644
--- a/src/PersonObjects/Sleeve/ui/FAQModal.tsx
+++ b/src/PersonObjects/Sleeve/ui/FAQModal.tsx
@@ -71,15 +71,8 @@ export function FAQModal({ open, onClose }: IProps): React.ReactElement {
Only one of your sleeves can work for a given company/faction a time. To clarify further, if you have two
- sleeves they can work for two different companies, but they cannot both work for the same company.
-
-
-
- Why did my Sleeve stop working?
-
-
- Sleeves are subject to the same time restrictions as you. This means that they automatically stop working at a
- company after 8 hours, and stop working for a faction after 20 hours.
+ sleeves they can work for two different companies/factions, but they cannot both work for the same
+ company/faction.
@@ -92,13 +85,16 @@ export function FAQModal({ open, onClose }: IProps): React.ReactElement {
Certain Augmentations, like {FactionNames.Bladeburners}-specific ones and NeuroFlux Governor, are not
- available for sleeves.
+ available for sleeves. You also need enough current reputation on some faction that offers that Augmentation.
Do sleeves get reset when installing Augmentations or switching BitNodes?
- Sleeves are reset when switching BitNodes, but not when installing Augmentations.
+
+ Sleeves are reset when switching BitNodes, but not when installing Augmentations. However installing
+ Augmentations on a sleeve does reset their stats.
+
What is Memory?
diff --git a/src/ScriptEditor/NetscriptDefinitions.d.ts b/src/ScriptEditor/NetscriptDefinitions.d.ts
index 3c2369282..5fa815893 100644
--- a/src/ScriptEditor/NetscriptDefinitions.d.ts
+++ b/src/ScriptEditor/NetscriptDefinitions.d.ts
@@ -2012,7 +2012,7 @@ export interface Singularity {
* guarantee that your browser will follow that time limit.
*
* @param crime - Name of crime to attempt.
- * @param focus - Acquire player focus on this program creation. Optional. Defaults to true.
+ * @param focus - Acquire player focus on this crime. Optional. Defaults to true.
* @returns The number of milliseconds it takes to attempt the specified crime.
*/
commitCrime(crime: string, focus?: boolean): number;
@@ -3511,7 +3511,7 @@ export interface Gang {
* Ascend the specified Gang Member.
*
* @param memberName - Name of member to ascend.
- * @returns Object with info about the ascension results. undefined if ascension did not occur.
+ * @returns Object with info about the ascension results. Undefined if ascension did not occur.
*/
ascendMember(memberName: string): GangMemberAscension | undefined;
@@ -3523,7 +3523,7 @@ export interface Gang {
* Get the result of an ascension without ascending.
*
* @param memberName - Name of member.
- * @returns Object with info about the ascension results. undefined if ascension is impossible.
+ * @returns Object with info about the ascension results. Undefined if ascension is impossible.
*/
getAscensionResult(memberName: string): GangMemberAscension | undefined;
@@ -7140,7 +7140,7 @@ interface CorporationInfo {
numShares: number;
/** Cooldown until shares can be sold again */
shareSaleCooldown: number;
- /** Amount of shares issued */
+ /** Amount of aqcuirable shares. */
issuedShares: number;
/** Price of the shares */
sharePrice: number;
diff --git a/src/Server/Server.ts b/src/Server/Server.ts
index 442b6d461..427b879e3 100644
--- a/src/Server/Server.ts
+++ b/src/Server/Server.ts
@@ -75,10 +75,11 @@ export class Server extends BaseServer {
this.moneyMax = 25 * this.moneyAvailable * BitNodeMultipliers.ServerMaxMoney;
//Hack Difficulty is synonymous with server security. Base Difficulty = Starting difficulty
- this.hackDifficulty =
+ const realDifficulty =
params.hackDifficulty != null ? params.hackDifficulty * BitNodeMultipliers.ServerStartingSecurity : 1;
+ this.hackDifficulty = Math.min(realDifficulty, 100);
this.baseDifficulty = this.hackDifficulty;
- this.minDifficulty = Math.max(1, Math.round(this.hackDifficulty / 3));
+ this.minDifficulty = Math.min(Math.max(1, Math.round(realDifficulty / 3)), 100);
this.serverGrowth = params.serverGrowth != null ? params.serverGrowth : 1; //Integer from 0 to 100. Affects money increase from grow()
//Port information, required for porthacking servers to get admin rights
diff --git a/src/Terminal/ui/TerminalRoot.tsx b/src/Terminal/ui/TerminalRoot.tsx
index a59ff4703..ef1e99662 100644
--- a/src/Terminal/ui/TerminalRoot.tsx
+++ b/src/Terminal/ui/TerminalRoot.tsx
@@ -125,7 +125,9 @@ export function TerminalRoot({ terminal, router, player }: IProps): React.ReactE
paragraph={false}
onClick={() => terminal.connectToServer(player, item.hostname)}
>
- {item.hostname}
+
+ {item.hostname}
+
>
)}
diff --git a/src/Work/CrimeWork.ts b/src/Work/CrimeWork.ts
index 28a813ea1..d7876047d 100644
--- a/src/Work/CrimeWork.ts
+++ b/src/Work/CrimeWork.ts
@@ -108,7 +108,7 @@ export class CrimeWork extends Work {
let karma = crime.karma;
const success = determineCrimeSuccess(player, crime.type);
if (success) {
- player.gainMoney(gains.money * player.mults.crime_money, "crime");
+ player.gainMoney(gains.money, "crime");
player.numPeopleKilled += crime.kills;
player.gainIntelligenceExp(gains.intExp);
} else {
diff --git a/src/Work/formulas/Crime.ts b/src/Work/formulas/Crime.ts
index 365bc7adc..af5d046d7 100644
--- a/src/Work/formulas/Crime.ts
+++ b/src/Work/formulas/Crime.ts
@@ -1,17 +1,18 @@
import { BitNodeMultipliers } from "../../BitNode/BitNodeMultipliers";
import { Crime } from "src/Crime/Crime";
import { newWorkStats, scaleWorkStats, WorkStats } from "../WorkStats";
+import { Player } from "../../Player";
export const calculateCrimeWorkStats = (crime: Crime): WorkStats => {
const gains = scaleWorkStats(
newWorkStats({
- money: crime.money,
- hackExp: crime.hacking_exp * 2,
- strExp: crime.strength_exp * 2,
- defExp: crime.defense_exp * 2,
- dexExp: crime.dexterity_exp * 2,
- agiExp: crime.agility_exp * 2,
- chaExp: crime.charisma_exp * 2,
+ money: crime.money * Player.mults.crime_money,
+ hackExp: crime.hacking_exp * 2 * Player.mults.hacking_exp,
+ strExp: crime.strength_exp * 2 * Player.mults.strength_exp,
+ defExp: crime.defense_exp * 2 * Player.mults.defense_exp,
+ dexExp: crime.dexterity_exp * 2 * Player.mults.dexterity_exp,
+ agiExp: crime.agility_exp * 2 * Player.mults.agility_exp,
+ chaExp: crime.charisma_exp * 2 * Player.mults.charisma_exp,
intExp: crime.intelligence_exp * 2,
}),
BitNodeMultipliers.CrimeExpGain,
diff --git a/src/engine.tsx b/src/engine.tsx
index db143f9aa..f7037ee06 100644
--- a/src/engine.tsx
+++ b/src/engine.tsx
@@ -262,7 +262,7 @@ const Engine: {
if (numCyclesOffline < 3000 * 100) {
// if we have less than 100 rolls, just roll them exactly.
for (let i = 0; i < numCyclesOffline / 3000; i++) {
- if (Math.random() < 0.25) numContracts++;
+ if (Math.random() <= 0.25) numContracts++;
}
} else {
// just average it.
diff --git a/src/utils/StringHelperFunctions.ts b/src/utils/StringHelperFunctions.ts
index 47f0db0e5..eecf5db15 100644
--- a/src/utils/StringHelperFunctions.ts
+++ b/src/utils/StringHelperFunctions.ts
@@ -38,15 +38,15 @@ function convertTimeMsToTimeElapsedString(time: number, showMilli = false): stri
let res = "";
if (days > 0) {
- res += `${days} days `;
+ res += `${days} day${days === 1 ? "" : "s"} `;
}
if (hours > 0 || (Settings.ShowMiddleNullTimeUnit && res != "")) {
- res += `${hours} hours `;
+ res += `${hours} hour${hours === 1 ? "" : "s"} `;
}
if (minutes > 0 || (Settings.ShowMiddleNullTimeUnit && res != "")) {
- res += `${minutes} minutes `;
+ res += `${minutes} minute${minutes === 1 ? "" : "s"} `;
}
- res += `${seconds} seconds`;
+ res += `${seconds} second${!showMilli && secTruncMinutes === 1 ? "" : "s"}`;
return res;
}