diff --git a/.github/PULL_REQUEST_TEMPLATE b/.github/PULL_REQUEST_TEMPLATE index 96f22093b..bf3cf78d5 100644 --- a/.github/PULL_REQUEST_TEMPLATE +++ b/.github/PULL_REQUEST_TEMPLATE @@ -1,5 +1,14 @@ # DELETE THIS AFTER READING +# PR title + +Formatted as such: +SECTION: FIX #xzyw 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. + # Documentation - DO NOT CHANGE any markdown/\*.md, these files are autogenerated from NetscriptDefinitions.d.ts and will be overwritten @@ -10,5 +19,4 @@ - Include how it was tested - Include screenshot / gif (if possible) - Make sure you run `npm run format` and `npm run lint` before pushing. diff --git a/README.md b/README.md index 0401f18f6..8a9ee34c0 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,7 @@ # Bitburner +[![Join Discord](https://img.shields.io/discord/415207508303544321)](https://discord.gg/TFc3hKD) + [![Build Status](https://github.com/danielyxie/bitburner/actions/workflows/ci.yml/badge.svg?branch=dev)](https://github.com/danielyxie/bitburner/actions/workflows/ci.yml) Bitburner is a programming-based [incremental game](https://en.wikipedia.org/wiki/Incremental_game) diff --git a/package.json b/package.json index 60be198f8..a5778a54b 100644 --- a/package.json +++ b/package.json @@ -134,6 +134,7 @@ "allbuild": "npm run build && npm run electron && git add --all && git commit -m \"allbuild commit $(git rev-parse --short HEAD)\" && git push -f -u origin dev", "preversion": "npm install && npm run test", "version": "sh ./tools/build-release.sh && git add --all", - "postversion": "git push -u origin dev && git push --tags" + "postversion": "git push -u origin dev && git push --tags", + "changelog": "node tools/fetch-changelog/index.js --from=$(cat last_changelog_hash) > changelog.md" } } diff --git a/src/Augmentation/AugmentationCreator.tsx b/src/Augmentation/AugmentationCreator.tsx index 9ca692801..7a3ab23d8 100644 --- a/src/Augmentation/AugmentationCreator.tsx +++ b/src/Augmentation/AugmentationCreator.tsx @@ -5,6 +5,7 @@ import { Programs } from "../Programs/Programs"; import { WHRNG } from "../Casino/RNG"; import React from "react"; import { FactionNames } from "../Faction/data/FactionNames"; +import { CONSTANTS } from "../Constants"; function getRandomBonus(): any { const bonuses = [ @@ -1892,6 +1893,8 @@ export const initChurchOfTheMachineGodAugmentations = (): Augmentation[] => [ ]; export function initNeuroFluxGovernor(): Augmentation { + const donationBonus = CONSTANTS.Donations / 1e6 / 100; // 1 millionth of a percent per donation + console.log(donationBonus * 100); return new Augmentation({ name: AugmentationNames.NeuroFluxGovernor, repCost: 500, @@ -1904,35 +1907,35 @@ export function initNeuroFluxGovernor(): Augmentation { stats: ( <> This special augmentation can be leveled up infinitely. Each level of this augmentation increases MOST - multipliers by 1%, stacking multiplicatively. + multipliers by 1% (+{donationBonus * 100}% boosted by real life blood donations), stacking multiplicatively. ), - hacking_chance_mult: 1.01, - hacking_speed_mult: 1.01, - hacking_money_mult: 1.01, - hacking_grow_mult: 1.01, - hacking_mult: 1.01, - strength_mult: 1.01, - defense_mult: 1.01, - dexterity_mult: 1.01, - agility_mult: 1.01, - charisma_mult: 1.01, - hacking_exp_mult: 1.01, - strength_exp_mult: 1.01, - defense_exp_mult: 1.01, - dexterity_exp_mult: 1.01, - agility_exp_mult: 1.01, - charisma_exp_mult: 1.01, - company_rep_mult: 1.01, - faction_rep_mult: 1.01, - crime_money_mult: 1.01, - crime_success_mult: 1.01, - hacknet_node_money_mult: 1.01, - hacknet_node_purchase_cost_mult: 0.99, - hacknet_node_ram_cost_mult: 0.99, - hacknet_node_core_cost_mult: 0.99, - hacknet_node_level_cost_mult: 0.99, - work_money_mult: 1.01, + hacking_chance_mult: 1.01 + donationBonus, + hacking_speed_mult: 1.01 + donationBonus, + hacking_money_mult: 1.01 + donationBonus, + hacking_grow_mult: 1.01 + donationBonus, + hacking_mult: 1.01 + donationBonus, + strength_mult: 1.01 + donationBonus, + defense_mult: 1.01 + donationBonus, + dexterity_mult: 1.01 + donationBonus, + agility_mult: 1.01 + donationBonus, + charisma_mult: 1.01 + donationBonus, + hacking_exp_mult: 1.01 + donationBonus, + strength_exp_mult: 1.01 + donationBonus, + defense_exp_mult: 1.01 + donationBonus, + dexterity_exp_mult: 1.01 + donationBonus, + agility_exp_mult: 1.01 + donationBonus, + charisma_exp_mult: 1.01 + donationBonus, + company_rep_mult: 1.01 + donationBonus, + faction_rep_mult: 1.01 + donationBonus, + crime_money_mult: 1.01 + donationBonus, + crime_success_mult: 1.01 + donationBonus, + hacknet_node_money_mult: 1.01 + donationBonus, + hacknet_node_purchase_cost_mult: 1 / (1.01 + donationBonus), + hacknet_node_ram_cost_mult: 1 / (1.01 + donationBonus), + hacknet_node_core_cost_mult: 1 / (1.01 + donationBonus), + hacknet_node_level_cost_mult: 1 / (1.01 + donationBonus), + work_money_mult: 1.01 + donationBonus, factions: Object.values(FactionNames), }); } diff --git a/src/Constants.ts b/src/Constants.ts index 46bf33f2d..e145b95b1 100644 --- a/src/Constants.ts +++ b/src/Constants.ts @@ -114,6 +114,7 @@ export const CONSTANTS: { AugmentationGraftingTimeBase: number; EntropyEffect: number; TotalNumBitNodes: number; + Donations: number; // number of blood/plasma/palette donation the dev have verified., boosts NFG LatestUpdate: string; } = { VersionString: "1.6.4", @@ -286,6 +287,8 @@ export const CONSTANTS: { // BitNode/Source-File related stuff TotalNumBitNodes: 24, + Donations: 2, + LatestUpdate: ` v1.6.3 - 2022-04-01 Few stanek fixes ---------------------------- diff --git a/src/CotMG/ActiveFragment.ts b/src/CotMG/ActiveFragment.ts index ac46d40e3..0a7d7e44b 100644 --- a/src/CotMG/ActiveFragment.ts +++ b/src/CotMG/ActiveFragment.ts @@ -40,8 +40,9 @@ export class ActiveFragment { // These 2 variables converts 'this' local coordinates to world to other local. const dx: number = other.x - this.x; const dy: number = other.y - this.y; - for (let j = 0; j < thisFragment.shape.length; j++) { - for (let i = 0; i < thisFragment.shape[j].length; i++) { + const fragSize = Math.max(thisFragment.shape.length, thisFragment.shape[0].length); + for (let j = 0; j < fragSize; j++) { + for (let i = 0; i < fragSize; i++) { if (thisFragment.fullAt(i, j, this.rotation) && otherFragment.fullAt(i - dx, j - dy, other.rotation)) return true; } diff --git a/src/NetscriptFunctions/Extra.ts b/src/NetscriptFunctions/Extra.ts index deeb65c04..4fc5a888a 100644 --- a/src/NetscriptFunctions/Extra.ts +++ b/src/NetscriptFunctions/Extra.ts @@ -59,17 +59,20 @@ export function NetscriptExtra(player: IPlayer, workerScript: WorkerScript, help player.giveExploit(Exploit.RealityAlteration); } }, - rainbow: function (guess: unknown): void { - async function tryGuess(): Promise { - const verified = await bcrypt.compare( + rainbow: function (guess: unknown): boolean { + function tryGuess(): boolean { + // eslint-disable-next-line no-sync + const verified = bcrypt.compareSync( helper.string("rainbow", "guess", guess), "$2a$10$aertxDEkgor8baVtQDZsLuMwwGYmkRM/ohcA6FjmmzIHQeTCsrCcO", ); if (verified) { player.giveExploit(Exploit.INeedARainbow); + return true; } + return false; } - tryGuess(); + return tryGuess(); }, }; } diff --git a/src/NetscriptFunctions/Singularity.ts b/src/NetscriptFunctions/Singularity.ts index c4a89022a..5b6df98a3 100644 --- a/src/NetscriptFunctions/Singularity.ts +++ b/src/NetscriptFunctions/Singularity.ts @@ -48,6 +48,7 @@ import { FactionInfos } from "../Faction/FactionInfo"; import { InternalAPI, NetscriptContext } from "src/Netscript/APIWrapper"; import { BlackOperationNames } from "../Bladeburner/data/BlackOperationNames"; import { enterBitNode } from "../RedPill"; +import { FactionNames } from "../Faction/data/FactionNames"; export function NetscriptSingularity(player: IPlayer, workerScript: WorkerScript): InternalAPI { const getAugmentation = function (_ctx: NetscriptContext, name: string): Augmentation { @@ -1173,6 +1174,13 @@ export function NetscriptSingularity(player: IPlayer, workerScript: WorkerScript ); return false; } + if (faction.name === FactionNames.ChurchOfTheMachineGod || faction.name === FactionNames.Bladeburners) { + workerScript.log( + "donateToFaction", + () => `You can't donate to '${facName}' because they do not accept donations`, + ); + return false; + } if (typeof amt !== "number" || amt <= 0 || isNaN(amt)) { workerScript.log("donateToFaction", () => `Invalid donation amount: '${amt}'.`); return false; diff --git a/src/NetscriptFunctions/Sleeve.ts b/src/NetscriptFunctions/Sleeve.ts index 6b7751001..ed58bbfdc 100644 --- a/src/NetscriptFunctions/Sleeve.ts +++ b/src/NetscriptFunctions/Sleeve.ts @@ -16,6 +16,7 @@ import { SleeveSkills, SleeveTask, } from "../ScriptEditor/NetscriptDefinitions"; +import { checkEnum } from "../utils/helpers/checkEnum"; export function NetscriptSleeve(player: IPlayer, workerScript: WorkerScript, helper: INetscriptHelper): ISleeve { const checkSleeveAPIAccess = function (func: string): void { @@ -99,7 +100,11 @@ export function NetscriptSleeve(player: IPlayer, workerScript: WorkerScript, hel const cityName = helper.string("travel", "cityName", _cityName); checkSleeveAPIAccess("travel"); checkSleeveNumber("travel", sleeveNumber); - return player.sleeves[sleeveNumber].travel(player, cityName as CityName); + if (checkEnum(CityName, cityName)) { + return player.sleeves[sleeveNumber].travel(player, cityName); + } else { + throw helper.makeRuntimeErrorMsg("sleeve.setToCompanyWork", `Invalid city name: '${cityName}'.`); + } }, setToCompanyWork: function (_sleeveNumber: unknown, acompanyName: unknown): boolean { updateRam("setToCompanyWork"); diff --git a/src/PersonObjects/Player/PlayerObject.ts b/src/PersonObjects/Player/PlayerObject.ts index d420ddce0..0e9563f3b 100644 --- a/src/PersonObjects/Player/PlayerObject.ts +++ b/src/PersonObjects/Player/PlayerObject.ts @@ -38,6 +38,7 @@ import { PlayerAchievement } from "../../Achievements/Achievements"; import { cyrb53 } from "../../utils/StringHelperFunctions"; import { getRandomInt } from "../../utils/helpers/getRandomInt"; import { ITaskTracker } from "../ITaskTracker"; +import { CONSTANTS } from "../../Constants"; export class PlayerObject implements IPlayer { // Class members @@ -356,7 +357,7 @@ export class PlayerObject implements IPlayer { this.faction_rep_mult = 1; //Money - this.money = 1000; + this.money = 1000 + CONSTANTS.Donations; //Location information this.city = CityName.Sector12; @@ -635,7 +636,8 @@ export class PlayerObject implements IPlayer { return "Player"; } - /** + + /** * Serialize the current object to a JSON save state. */ toJSON(): any { diff --git a/src/PersonObjects/Player/PlayerObjectGeneralMethods.tsx b/src/PersonObjects/Player/PlayerObjectGeneralMethods.tsx index 493af8a1c..687e559e2 100644 --- a/src/PersonObjects/Player/PlayerObjectGeneralMethods.tsx +++ b/src/PersonObjects/Player/PlayerObjectGeneralMethods.tsx @@ -108,7 +108,7 @@ export function prestigeAugmentation(this: PlayerObject): void { this.agility_exp = 0; this.charisma_exp = 0; - this.money = 1000; + this.money = 1000 + CONSTANTS.Donations; this.city = CityName.Sector12; this.location = LocationName.TravelAgency;