mirror of
https://github.com/bitburner-official/bitburner-src.git
synced 2026-04-16 06:18:42 +02:00
DNET: Player feedback (#2545)
This commit is contained in:
committed by
GitHub
parent
73b7921ef0
commit
1b6b07faae
@@ -6,10 +6,12 @@
|
||||
|
||||
Sends a network request to try to authenticate on a darkweb server. The target server must be directly connected to the server that the script is running on. The speed of authentication scales with the number of threads used.
|
||||
|
||||
If successful, grants the script a session, allowing it to exec() scripts on that server, or scp() files to it. (scp() \*from\* the server is always allowed.)
|
||||
If successful, grants the current script a session, allowing it to exec() scripts on that server, or scp() files to it. (scp() \*from\* the server is always allowed.)
|
||||
|
||||
Note that the charisma level on a server is not a requirement for authentication, but authentication takes longer if the player's charisma is below the server's charisma level.
|
||||
|
||||
Note that the session granted is only for the current script instance (by PID) - other running scripts will need to use connectToSession with the correct password to also get a session with the target server.
|
||||
|
||||
**Signature:**
|
||||
|
||||
```typescript
|
||||
@@ -92,5 +94,5 @@ A promise that resolves to a [DarknetResult](./bitburner.darknetresult.md) objec
|
||||
|
||||
## Remarks
|
||||
|
||||
RAM cost: 0.6 GB
|
||||
RAM cost: 0.4 GB
|
||||
|
||||
|
||||
@@ -6,10 +6,12 @@
|
||||
|
||||
Attempts to connect to a target darkweb server that you have previously authenticated on. Unlike `authenticate`<!-- -->, connectToSession can be used to get a session on servers at any distance.
|
||||
|
||||
If successful, grants the script a session, allowing it to scp() files from that target. It also allows starting scripts with exec() on that target, if the target is directly connected to the server that the script is running on, or has a backdoor or stasis link.
|
||||
If successful, grants the script a session, allowing it to scp() files to that target. It also allows starting scripts with exec() on that target, if the target is directly connected to the server that the script is running on, or has a backdoor or stasis link.
|
||||
|
||||
If unsuccessful, more detail may be able to be gathered by using heartbleed() to look at the resulting logs on the server.
|
||||
|
||||
Note that the session granted is only for the current script instance (by PID) - other running scripts will need to use connectToSession with the correct password to also get a session with the target server.
|
||||
|
||||
**Signature:**
|
||||
|
||||
```typescript
|
||||
|
||||
@@ -34,10 +34,12 @@ Description
|
||||
|
||||
Sends a network request to try to authenticate on a darkweb server. The target server must be directly connected to the server that the script is running on. The speed of authentication scales with the number of threads used.
|
||||
|
||||
If successful, grants the script a session, allowing it to exec() scripts on that server, or scp() files to it. (scp() \*from\* the server is always allowed.)
|
||||
If successful, grants the current script a session, allowing it to exec() scripts on that server, or scp() files to it. (scp() \*from\* the server is always allowed.)
|
||||
|
||||
Note that the charisma level on a server is not a requirement for authentication, but authentication takes longer if the player's charisma is below the server's charisma level.
|
||||
|
||||
Note that the session granted is only for the current script instance (by PID) - other running scripts will need to use connectToSession with the correct password to also get a session with the target server.
|
||||
|
||||
|
||||
</td></tr>
|
||||
<tr><td>
|
||||
@@ -49,10 +51,12 @@ Note that the charisma level on a server is not a requirement for authentication
|
||||
|
||||
Attempts to connect to a target darkweb server that you have previously authenticated on. Unlike `authenticate`<!-- -->, connectToSession can be used to get a session on servers at any distance.
|
||||
|
||||
If successful, grants the script a session, allowing it to scp() files from that target. It also allows starting scripts with exec() on that target, if the target is directly connected to the server that the script is running on, or has a backdoor or stasis link.
|
||||
If successful, grants the script a session, allowing it to scp() files to that target. It also allows starting scripts with exec() on that target, if the target is directly connected to the server that the script is running on, or has a backdoor or stasis link.
|
||||
|
||||
If unsuccessful, more detail may be able to be gathered by using heartbleed() to look at the resulting logs on the server.
|
||||
|
||||
Note that the session granted is only for the current script instance (by PID) - other running scripts will need to use connectToSession with the correct password to also get a session with the target server.
|
||||
|
||||
|
||||
</td></tr>
|
||||
<tr><td>
|
||||
|
||||
13
markdown/bitburner.multipliers.dnet_money.md
Normal file
13
markdown/bitburner.multipliers.dnet_money.md
Normal file
@@ -0,0 +1,13 @@
|
||||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [bitburner](./bitburner.md) > [Multipliers](./bitburner.multipliers.md) > [dnet\_money](./bitburner.multipliers.dnet_money.md)
|
||||
|
||||
## Multipliers.dnet\_money property
|
||||
|
||||
Multiplier to amount of money gained from phishing and caches on darknet servers
|
||||
|
||||
**Signature:**
|
||||
|
||||
```typescript
|
||||
dnet_money: number;
|
||||
```
|
||||
@@ -318,6 +318,25 @@ number
|
||||
Multiplier to dexterity skill
|
||||
|
||||
|
||||
</td></tr>
|
||||
<tr><td>
|
||||
|
||||
[dnet\_money](./bitburner.multipliers.dnet_money.md)
|
||||
|
||||
|
||||
</td><td>
|
||||
|
||||
|
||||
</td><td>
|
||||
|
||||
number
|
||||
|
||||
|
||||
</td><td>
|
||||
|
||||
Multiplier to amount of money gained from phishing and caches on darknet servers
|
||||
|
||||
|
||||
</td></tr>
|
||||
<tr><td>
|
||||
|
||||
|
||||
@@ -40,6 +40,7 @@ export interface AugmentationCtorParams {
|
||||
faction_rep?: number;
|
||||
crime_money?: number;
|
||||
crime_success?: number;
|
||||
dnet_money?: number;
|
||||
work_money?: number;
|
||||
hacknet_node_money?: number;
|
||||
hacknet_node_purchase_cost?: number;
|
||||
|
||||
@@ -1859,9 +1859,11 @@ export const Augmentations: Record<AugmentationName, Augmentation> = (() => {
|
||||
"Created by a mysterious figure known only as 'The Sculptor', this augmentation appears as a set of silvery " +
|
||||
"metallic patterns on the user's upper back and shoulders. " +
|
||||
"Awarded to those who discover the secrets of the labyrinth.",
|
||||
stats: "This augmentation increases the stasis link limit by one, and raises charisma by 15% and agility by 10%.",
|
||||
charisma: 1.15,
|
||||
stats:
|
||||
"This augmentation increases the stasis link limit by one, and raises charisma by 5% and agility by 10%, and darknet money by 30%.",
|
||||
charisma: 1.05,
|
||||
agility: 1.1,
|
||||
dnet_money: 1.3,
|
||||
isSpecial: true,
|
||||
factions: [],
|
||||
},
|
||||
@@ -1873,9 +1875,9 @@ export const Augmentations: Record<AugmentationName, Augmentation> = (() => {
|
||||
"Its creator, the enigmatic Sculptor, refuses to reveal the details of how it works, and only mutters about 'liveware APIs'. " +
|
||||
"Awarded to those who discover the secrets of the labyrinth.",
|
||||
stats:
|
||||
"This augmentation increases the speed of authentication and heartbleed by 20%, and raises charisma and dexterity by 20%.",
|
||||
charisma: 1.2,
|
||||
dexterity: 1.2,
|
||||
"This augmentation increases the speed of authentication and heartbleed by 20%, and raises charisma and dexterity by 6%.",
|
||||
charisma: 1.06,
|
||||
dexterity: 1.06,
|
||||
isSpecial: true,
|
||||
prereqs: [AugmentationName.TheBrokenWings],
|
||||
factions: [],
|
||||
@@ -1888,9 +1890,10 @@ export const Augmentations: Record<AugmentationName, Augmentation> = (() => {
|
||||
"Appearing as a simple insignia on the user's forarm, its true function is unknown. It is said to be one of the tools of The Sculptor. " +
|
||||
"Awarded to those who discover the secrets of the labyrinth.",
|
||||
stats:
|
||||
"This augmentation increases the stasis link limit by one, and raises charisma by 35% and strength by 25%.",
|
||||
charisma: 1.35,
|
||||
strength: 1.25,
|
||||
"This augmentation increases the stasis link limit by one, and raises charisma by 7%, strength by 10%, and darknet money by 10%.",
|
||||
charisma: 1.07,
|
||||
strength: 1.1,
|
||||
dnet_money: 1.1,
|
||||
isSpecial: true,
|
||||
prereqs: [AugmentationName.TheBoots],
|
||||
factions: [],
|
||||
@@ -1902,9 +1905,10 @@ export const Augmentations: Record<AugmentationName, Augmentation> = (() => {
|
||||
"This skeletal augmentation greatly enhances the users durability and health. Inspired by the original Staff of Medicine that is said to " +
|
||||
"have been given to Daedalus as a reward for the completion of the Labyrinth, which all modern augments are a descendant of. ",
|
||||
stats:
|
||||
"This augmentation increases the stasis link limit by one, and raises charisma xp by 20% and defense by 30%.",
|
||||
charisma_exp: 1.2,
|
||||
defense: 1.3,
|
||||
"This augmentation increases the stasis link limit by one, and raises charisma xp, defense, and darknet money by 10%.",
|
||||
charisma_exp: 1.1,
|
||||
defense: 1.1,
|
||||
dnet_money: 1.1,
|
||||
isSpecial: true,
|
||||
prereqs: [AugmentationName.TheHammer],
|
||||
factions: [],
|
||||
@@ -1917,10 +1921,10 @@ export const Augmentations: Record<AugmentationName, Augmentation> = (() => {
|
||||
"This augmentation enhances the user's ability to assess probabilities, predict outcomes, and adapt strategies in real-time, " +
|
||||
"making them exceptionally persuasive and confident in negotiations and social interactions. " +
|
||||
"Awarded to those who discover the secrets of the labyrinth.",
|
||||
stats: "This augmentation raises charisma by 40%, hacking by 10%, and company rep by 5%.",
|
||||
charisma: 1.4,
|
||||
hacking: 1.1,
|
||||
stats: "This augmentation raises charisma by 9%, company rep by 5%, and darknet money by 15%.",
|
||||
charisma: 1.09,
|
||||
company_rep: 1.05,
|
||||
dnet_money: 1.15,
|
||||
isSpecial: true,
|
||||
prereqs: [AugmentationName.TheStaff],
|
||||
factions: [],
|
||||
@@ -1934,10 +1938,11 @@ export const Augmentations: Record<AugmentationName, Augmentation> = (() => {
|
||||
"turning every interaction into a calculated success. The technique is sometimes referred to as Solomonoff's Lightsaber, as it is a " +
|
||||
"more powerful version of Occam's razor. " +
|
||||
"The final augment awarded to those who discover the secrets of the labyrinth.",
|
||||
stats: "This augmentation raises charisma by 50%, hacking by 16%, and company rep by 10%.",
|
||||
charisma: 1.5,
|
||||
hacking: 1.16,
|
||||
stats: "This augmentation raises charisma, hacking, darknet money, and company rep by 10%.",
|
||||
charisma: 1.1,
|
||||
hacking: 1.1,
|
||||
company_rep: 1.1,
|
||||
dnet_money: 1.1,
|
||||
isSpecial: true,
|
||||
prereqs: [AugmentationName.TheLaw],
|
||||
factions: [],
|
||||
|
||||
@@ -263,6 +263,13 @@ export function PlayerMultipliers(): React.ReactElement {
|
||||
bnMult: currentNodeMults.CrimeMoney,
|
||||
color: Settings.theme.money,
|
||||
},
|
||||
{
|
||||
mult: "Darknet Money",
|
||||
current: Player.mults.dnet_money,
|
||||
augmented: Player.mults.dnet_money * mults.dnet_money,
|
||||
bnMult: currentNodeMults.DarknetMoneyMultiplier,
|
||||
color: Settings.theme.money,
|
||||
},
|
||||
];
|
||||
|
||||
if (Player.canAccessBladeburner() && currentNodeMults.BladeburnerRank > 0) {
|
||||
|
||||
@@ -625,6 +625,8 @@ export function getBitNodeMultipliers(n: number, lvl: number): BitNodeMultiplier
|
||||
StaneksGiftPowerMultiplier: 0.75,
|
||||
StaneksGiftExtraSize: -2,
|
||||
|
||||
DarknetMoneyMultiplier: 0.4,
|
||||
|
||||
WorldDaemonDifficulty: 2,
|
||||
});
|
||||
}
|
||||
@@ -653,6 +655,8 @@ export function getBitNodeMultipliers(n: number, lvl: number): BitNodeMultiplier
|
||||
StaneksGiftPowerMultiplier: 1.5,
|
||||
StaneksGiftExtraSize: 0,
|
||||
|
||||
DarknetMoneyMultiplier: 0.4,
|
||||
|
||||
WorldDaemonDifficulty: 3,
|
||||
});
|
||||
}
|
||||
@@ -682,6 +686,8 @@ export function getBitNodeMultipliers(n: number, lvl: number): BitNodeMultiplier
|
||||
StaneksGiftPowerMultiplier: 1.3,
|
||||
StaneksGiftExtraSize: 0,
|
||||
|
||||
DarknetMoneyMultiplier: 0.7,
|
||||
|
||||
WorldDaemonDifficulty: 1.5,
|
||||
});
|
||||
}
|
||||
@@ -830,6 +836,8 @@ export function getBitNodeMultipliers(n: number, lvl: number): BitNodeMultiplier
|
||||
StaneksGiftPowerMultiplier: 0.5,
|
||||
StaneksGiftExtraSize: 2,
|
||||
|
||||
DarknetMoneyMultiplier: 0.5,
|
||||
|
||||
WorldDaemonDifficulty: 2,
|
||||
});
|
||||
}
|
||||
@@ -873,6 +881,8 @@ export function getBitNodeMultipliers(n: number, lvl: number): BitNodeMultiplier
|
||||
StaneksGiftPowerMultiplier: 0.75,
|
||||
StaneksGiftExtraSize: -3,
|
||||
|
||||
DarknetMoneyMultiplier: 0.4,
|
||||
|
||||
WorldDaemonDifficulty: 2,
|
||||
});
|
||||
}
|
||||
@@ -946,6 +956,7 @@ export function getBitNodeMultipliers(n: number, lvl: number): BitNodeMultiplier
|
||||
ManualHackMoney: dec,
|
||||
ScriptHackMoney: dec,
|
||||
CodingContractMoney: dec,
|
||||
DarknetMoneyMultiplier: dec,
|
||||
|
||||
ClassGymExpGain: dec,
|
||||
CompanyWorkExpGain: dec,
|
||||
@@ -1025,6 +1036,7 @@ export function getBitNodeMultipliers(n: number, lvl: number): BitNodeMultiplier
|
||||
|
||||
StaneksGiftPowerMultiplier: 2,
|
||||
StaneksGiftExtraSize: 1,
|
||||
DarknetMoneyMultiplier: 0.5,
|
||||
|
||||
WorldDaemonDifficulty: 3,
|
||||
});
|
||||
|
||||
@@ -55,6 +55,9 @@ export class CodingContract {
|
||||
processed outside of this file */
|
||||
reward: ICodingContractReward | null;
|
||||
|
||||
/* Scalar for the reward, used to generate lower-value CCTs more frequently */
|
||||
rewardScaling: number = 1;
|
||||
|
||||
/* Number of times the Contract has been attempted */
|
||||
tries = 0;
|
||||
|
||||
@@ -65,6 +68,7 @@ export class CodingContract {
|
||||
fn = "default.cct",
|
||||
type = CodingContractName.FindLargestPrimeFactor,
|
||||
reward: ICodingContractReward | null = null,
|
||||
rewardScaling: number = 1,
|
||||
) {
|
||||
const path = resolveContractFilePath(fn);
|
||||
if (!path) {
|
||||
@@ -78,6 +82,7 @@ export class CodingContract {
|
||||
this.type = type;
|
||||
this.state = CodingContractTypes[type].generate();
|
||||
this.reward = reward;
|
||||
this.rewardScaling = rewardScaling;
|
||||
}
|
||||
|
||||
getAnswer() {
|
||||
|
||||
@@ -130,6 +130,7 @@ interface IGenerateContractParams {
|
||||
server?: string;
|
||||
filename?: ContractFilePath;
|
||||
reward?: ICodingContractReward;
|
||||
rewardScaling?: number;
|
||||
}
|
||||
|
||||
export function generateContract(params: IGenerateContractParams): void {
|
||||
@@ -163,7 +164,7 @@ export function generateContract(params: IGenerateContractParams): void {
|
||||
if (filename == null) {
|
||||
return;
|
||||
}
|
||||
const contract = new CodingContract(filename, problemType, reward);
|
||||
const contract = new CodingContract(filename, problemType, reward, params.rewardScaling);
|
||||
server.addContract(contract);
|
||||
}
|
||||
|
||||
|
||||
@@ -80,6 +80,7 @@ export function initDarkwebServer(): void {
|
||||
darkweb.isStationary = true;
|
||||
darkweb.hasAdminRights = true;
|
||||
darkweb.blockedRam = 0;
|
||||
darkweb.maxRam = 16;
|
||||
darkweb.scripts = scripts;
|
||||
darkweb.contracts = contracts;
|
||||
if (hasTOR) {
|
||||
|
||||
@@ -17,7 +17,7 @@ import {
|
||||
getAllDarknetServers,
|
||||
getAllMovableDarknetServers,
|
||||
getAllOpenPositions,
|
||||
getBackdooredDarkwebServers,
|
||||
getBackdooredDarknetServers,
|
||||
getDarknetCyclesPerMutation,
|
||||
getIslands,
|
||||
} from "../utils/darknetNetworkUtils";
|
||||
@@ -89,7 +89,7 @@ export const mutateDarknet = (): void => {
|
||||
}
|
||||
|
||||
if (Math.random() < 0.1) {
|
||||
const backdooredServers = getBackdooredDarkwebServers();
|
||||
const backdooredServers = getBackdooredDarknetServers();
|
||||
const server = backdooredServers[Math.floor(Math.random() * backdooredServers.length)];
|
||||
if (server) {
|
||||
restartServer(server);
|
||||
@@ -98,7 +98,7 @@ export const mutateDarknet = (): void => {
|
||||
}
|
||||
|
||||
if (Math.random() < 0.05) {
|
||||
const backdooredServers = getBackdooredDarkwebServers();
|
||||
const backdooredServers = getBackdooredDarknetServers();
|
||||
const server = backdooredServers[Math.floor(Math.random() * backdooredServers.length)];
|
||||
if (server) {
|
||||
deleteDarknetServer(server);
|
||||
|
||||
@@ -1,27 +1,26 @@
|
||||
import { tryGeneratingRandomContract } from "../../CodingContract/ContractGenerator";
|
||||
import { generateContract } from "../../CodingContract/ContractGenerator";
|
||||
import { Player } from "@player";
|
||||
import { formatMoney, formatNumber } from "../../ui/formatNumber";
|
||||
import { formatMoney } from "../../ui/formatNumber";
|
||||
import { getLabAugReward, isLabyrinthServer, LAB_CACHE_NAME } from "./labyrinth";
|
||||
import { SnackbarEvents } from "../../ui/React/Snackbar";
|
||||
import { AugmentationName, CompletedProgramName, ToastVariant } from "@enums";
|
||||
import { AugmentationName, CompletedProgramName, StockSymbol, ToastVariant } from "@enums";
|
||||
import { currentNodeMults } from "../../BitNode/BitNodeMultipliers";
|
||||
import { CreateProgramWork } from "../../Work/CreateProgramWork";
|
||||
import { initStockMarket, isStockMarketInitialized } from "../../StockMarket/StockMarket";
|
||||
import { initStockMarket, isStockMarketInitialized, StockMarket } from "../../StockMarket/StockMarket";
|
||||
import { cachePrefixes } from "../models/dictionaryData";
|
||||
import type { DarknetServer } from "../../Server/DarknetServer";
|
||||
import { type CacheFilePath, resolveCacheFilePath } from "../../Paths/CacheFilePath";
|
||||
import type { CacheResult, Result } from "@nsdefs";
|
||||
import { resolveCacheFilePath } from "../../Paths/CacheFilePath";
|
||||
import type { CacheResult } from "@nsdefs";
|
||||
import { addClue, cctCooldownReached } from "./effects";
|
||||
|
||||
export const generateCacheFilename: (prefix?: string) => CacheFilePath | null = (prefix) => {
|
||||
export const generateCacheFilename = (isPhishingCache: boolean, prefix?: string) => {
|
||||
const filenamePrefix = prefix ?? cachePrefixes[Math.floor(Math.random() * cachePrefixes.length)];
|
||||
return resolveCacheFilePath(`${filenamePrefix}_${Math.random().toString().substring(2, 5)}.cache`);
|
||||
const suffix = isPhishingCache ? ".d.cache" : ".cache";
|
||||
return resolveCacheFilePath(`${filenamePrefix}_${Math.random().toString().substring(2, 5)}${suffix}`);
|
||||
};
|
||||
|
||||
export const addCacheToServer: (server: DarknetServer, prefix?: string) => Result<{ cacheFilename: CacheFilePath }> = (
|
||||
server,
|
||||
prefix,
|
||||
) => {
|
||||
const cacheFilename = generateCacheFilename(prefix);
|
||||
export const addCacheToServer = (server: DarknetServer, isPhishingCache: boolean, prefix?: string) => {
|
||||
const cacheFilename = generateCacheFilename(isPhishingCache, prefix);
|
||||
if (!cacheFilename) {
|
||||
return { success: false, message: `Cannot generate path. prefix: ${prefix}` };
|
||||
}
|
||||
@@ -42,9 +41,13 @@ export const getRewardFromCache = (server: DarknetServer, cacheName: string, sup
|
||||
};
|
||||
}
|
||||
|
||||
const rewards = [getMoneyReward, getXpReward, getProgramAndStockMarketRelatedRewards, getCCTReward];
|
||||
const rewards = [getMoneyReward, getProgramAndStockMarketRelatedRewards, getStockReward, getDataFileReward];
|
||||
if (cacheName.endsWith(".d.cache")) {
|
||||
// only include ccts from caches generated from phishing attacks
|
||||
rewards.push(getCCTReward);
|
||||
}
|
||||
const reward = rewards[Math.floor(Math.random() * rewards.length)];
|
||||
const result = reward(difficulty);
|
||||
const result = reward(difficulty, server);
|
||||
|
||||
if (!suppressToast) {
|
||||
SnackbarEvents.emit(
|
||||
@@ -62,16 +65,17 @@ export const getRewardFromCache = (server: DarknetServer, cacheName: string, sup
|
||||
};
|
||||
};
|
||||
|
||||
export const getCCTReward = (difficulty: number): string => {
|
||||
if (Math.random() < difficulty * 0.2) {
|
||||
export const getCCTReward = (difficulty: number, server: DarknetServer): string => {
|
||||
if (!cctCooldownReached()) {
|
||||
return getMoneyReward(difficulty);
|
||||
}
|
||||
|
||||
const contractCount = Math.floor(Math.min(20, difficulty) * 0.2 - 1.5 + Math.random() * 3);
|
||||
if (contractCount <= 0) {
|
||||
const contractCount = Math.min(Math.floor(Math.min(20, difficulty) * 0.1 - 1.5 + Math.random() * 3), 3);
|
||||
if (contractCount < 1) {
|
||||
return getMoneyReward(difficulty);
|
||||
}
|
||||
tryGeneratingRandomContract(contractCount);
|
||||
for (let i = 0; i < contractCount; i++) {
|
||||
generateContract({ server: server.hostname, rewardScaling: 1 / 5 });
|
||||
}
|
||||
return `New coding contracts are now available on the network!`;
|
||||
};
|
||||
|
||||
@@ -83,16 +87,32 @@ export const getMoneyReward = (difficulty: number): string => {
|
||||
((200 + Player.skills.charisma) / 200) *
|
||||
sf15_3Factor *
|
||||
Player.mults.crime_money *
|
||||
Player.mults.dnet_money *
|
||||
currentNodeMults.DarknetMoneyMultiplier; // TODO: adjust balance
|
||||
Player.gainMoney(reward, "darknet");
|
||||
return `You have discovered a cache with ${formatMoney(reward)}.`;
|
||||
};
|
||||
|
||||
export const getXpReward = (difficulty: number): string => {
|
||||
const sf15_3Factor = Player.activeSourceFileLvl(15) > 3 ? 1.5 : 1;
|
||||
const reward = 1.2 ** difficulty * 500 * sf15_3Factor * Player.mults.charisma_exp; // TODO: adjust balance
|
||||
Player.gainCharismaExp(reward);
|
||||
return `You have discovered a cache with ${formatNumber(reward, 0)} cha XP.`;
|
||||
export const getStockReward = (difficulty: number): string => {
|
||||
if (!isStockMarketInitialized()) {
|
||||
initStockMarket();
|
||||
}
|
||||
const stockSymbols = Object.keys(StockSymbol);
|
||||
const randomStock = stockSymbols[Math.floor(Math.random() * stockSymbols.length)];
|
||||
const shares = Math.floor(1 + difficulty * 5 + Math.random() * 10);
|
||||
StockMarket[randomStock].playerShares += shares;
|
||||
return `You have discovered a stock option cache containing ${shares} shares of ${randomStock}!`;
|
||||
};
|
||||
|
||||
export const getDataFileReward = (difficulty: number, server: DarknetServer): string => {
|
||||
const currentDataFiles = server.textFiles.size;
|
||||
addClue(server);
|
||||
addClue(server);
|
||||
const dataFilesGained = server.textFiles.size - currentDataFiles;
|
||||
if (dataFilesGained === 0) {
|
||||
return getMoneyReward(difficulty);
|
||||
}
|
||||
return `You have discovered a data file cache!`;
|
||||
};
|
||||
|
||||
export const getProgramAndStockMarketRelatedRewards = (difficulty: number): string => {
|
||||
@@ -135,7 +155,7 @@ export const getProgramAndStockMarketRelatedRewards = (difficulty: number): stri
|
||||
return `You have discovered a cache of stolen 4S Data!`;
|
||||
}
|
||||
|
||||
return getXpReward(difficulty);
|
||||
return getMoneyReward(difficulty);
|
||||
};
|
||||
|
||||
const getLabReward = (): string => {
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { Player } from "@player";
|
||||
import type { DarknetServerData, Person as IPerson } from "@nsdefs";
|
||||
import { AugmentationName, CompletedProgramName, LiteratureName } from "@enums";
|
||||
import { generateContract } from "../../CodingContract/ContractGenerator";
|
||||
import {
|
||||
commonPasswordDictionary,
|
||||
notebookFileNames,
|
||||
@@ -20,7 +19,7 @@ import { populateDarknet } from "../controllers/NetworkGenerator";
|
||||
import { getDarknetServer } from "../utils/darknetServerUtils";
|
||||
import {
|
||||
getAllMovableDarknetServers,
|
||||
getBackdooredDarkwebServers,
|
||||
getBackdooredDarknetServers,
|
||||
getNearbyNonEmptyPasswordServer,
|
||||
getStasisLinkServers,
|
||||
} from "../utils/darknetNetworkUtils";
|
||||
@@ -41,14 +40,9 @@ export const handleSuccessfulAuth = (server: DarknetServer, threads: number, pid
|
||||
server.hasAdminRights = true;
|
||||
addClue(server);
|
||||
|
||||
const cctChance = Math.min(0.12, 0.02 * (server.difficulty - 1));
|
||||
if (Math.random() < cctChance) {
|
||||
generateContract({ server: server.hostname });
|
||||
}
|
||||
|
||||
const chance = 0.1 * 1.05 ** server?.difficulty;
|
||||
if (Math.random() < chance && !isLabyrinthServer(server.hostname)) {
|
||||
addCacheToServer(server);
|
||||
addCacheToServer(server, false);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -110,7 +104,7 @@ export const calculateAuthenticationTime = (
|
||||
};
|
||||
|
||||
export const getBackdoorAuthTimeDebuff = () => {
|
||||
const backdooredServerCount = getBackdooredDarkwebServers().length;
|
||||
const backdooredServerCount = getBackdooredDarknetServers().length;
|
||||
const serverCount = getAllMovableDarknetServers().filter((s) => s.hasAdminRights).length;
|
||||
const safeBackdoors = Math.max(serverCount / (NET_WIDTH * 3), 2);
|
||||
const backdoorSurplus = Math.max(0, backdooredServerCount - safeBackdoors);
|
||||
@@ -132,7 +126,7 @@ export const getMultiplierFromCharisma = (scalar = 1) => {
|
||||
|
||||
export const calculatePasswordAttemptChaGain = (server: DarknetServerData, threads: number = 1, success = false) => {
|
||||
const baseXpGain = 3;
|
||||
const difficultyBase = 0.8;
|
||||
const difficultyBase = 1.1;
|
||||
const xpGain = baseXpGain + difficultyBase ** server.difficulty;
|
||||
const alreadyHackedMult = server.hasAdminRights ? 0.2 : 1;
|
||||
const successMult = success && !server.hasAdminRights ? 10 : 1;
|
||||
@@ -264,7 +258,7 @@ export const setStasisLink = (ctx: NetscriptContext, server: DarknetServer, shou
|
||||
|
||||
export const chargeServerMigration = (server: DarknetServer, threads = 1) => {
|
||||
const chargeIncrease = ((Player.skills.charisma + 500) / (server.difficulty * 200 + 1000)) * 0.01 * threads;
|
||||
const xpGained = Player.mults.charisma_exp * 50 * ((200 + Player.skills.charisma) / 200) * threads;
|
||||
const xpGained = Player.mults.charisma_exp * 5 * threads * server.difficulty;
|
||||
Player.gainCharismaExp(xpGained);
|
||||
const currentCharge = DarknetState.migrationInductionServers.get(server.hostname) ?? 0;
|
||||
const newCharge = Math.min(currentCharge + chargeIncrease, 1);
|
||||
@@ -292,4 +286,9 @@ export const getDarkscapeNavigator = () => {
|
||||
populateDarknet();
|
||||
};
|
||||
|
||||
export const cctCooldownReached = () => {
|
||||
const timeSinceLastCCT = new Date().getTime() - DarknetState.lastCctRewardTime.getTime();
|
||||
return timeSinceLastCCT > 10 * 60 * 1000;
|
||||
};
|
||||
|
||||
export const hasFullDarknetAccess = (): boolean => Player.bitNodeN === 15 || Player.activeSourceFileLvl(15) > 0;
|
||||
|
||||
@@ -303,7 +303,7 @@ export const handleLabyrinthPassword = (
|
||||
server.hasAdminRights = true;
|
||||
const cacheCount = getLabyrinthDetails().name === SpecialServers.BonusLab ? 3 : 1;
|
||||
for (let i = 0; i < cacheCount; i++) {
|
||||
addCacheToServer(server, LAB_CACHE_NAME);
|
||||
addCacheToServer(server, false, LAB_CACHE_NAME);
|
||||
}
|
||||
addSessionToServer(labServer, pid);
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ import { errorMessage } from "../../Netscript/ErrorMessages";
|
||||
import type { BaseServer } from "../../Server/BaseServer";
|
||||
import { GetServer } from "../../Server/AllServers";
|
||||
import { GenericResponseMessage, ResponseCodeEnum } from "../Enums";
|
||||
import { getBackdooredDarkwebServers } from "../utils/darknetNetworkUtils";
|
||||
import { getBackdooredDarknetServers } from "../utils/darknetNetworkUtils";
|
||||
import { hasDarknetAccess } from "../utils/darknetAuthUtils";
|
||||
import { DarknetServer } from "../../Server/DarknetServer";
|
||||
import { CompletedProgramName } from "../../Enums";
|
||||
@@ -149,6 +149,6 @@ export function expectRunningOnDarknetServer(ctx: NetscriptContext): DarknetServ
|
||||
}
|
||||
|
||||
export function getTimeoutChance() {
|
||||
const backdooredDarknetServerCount = getBackdooredDarkwebServers().length - 2;
|
||||
const backdooredDarknetServerCount = getBackdooredDarknetServers().length - 2;
|
||||
return Math.max(Math.min(backdooredDarknetServerCount * 0.03, 0.5), 0);
|
||||
}
|
||||
|
||||
@@ -10,23 +10,20 @@ import { ResponseCodeEnum } from "../Enums";
|
||||
import { isLabyrinthServer } from "./labyrinth";
|
||||
|
||||
export const getPhishingAttackSpeed = () => Math.max(10000 * (400 / (400 + Player.skills.charisma)), 200);
|
||||
const getPhishingCacheCooldownDuration = () => (hasDarknetBonusTime() ? 12_000 : 24_000);
|
||||
|
||||
export const handlePhishingAttack = (ctx: NetscriptContext, server: DarknetServer) => {
|
||||
const threads = ctx.workerScript.scriptRef.threads;
|
||||
const xpGained = Player.mults.charisma_exp * threads * 50 * ((200 + Player.skills.charisma) / 200);
|
||||
Player.gainCharismaExp(xpGained);
|
||||
const xpReward = Player.mults.charisma_exp * threads * 50;
|
||||
|
||||
const timeSinceLastRewardCache = new Date().getTime() - DarknetState.lastPhishingCacheTime.getTime();
|
||||
const rewardCacheChance = 0.005 * Player.mults.crime_success * threads * ((400 + Player.skills.charisma) / 400);
|
||||
const moneyRewardChance = 0.05 * Player.mults.crime_success * ((100 + Player.skills.charisma) / 100);
|
||||
const cooldown = getPhishingCacheCooldownDuration();
|
||||
const moneyRewardChance = 0.05 * Player.mults.crime_success * ((200 + Player.skills.charisma) / 200);
|
||||
const isLabServer = isLabyrinthServer(server.hostname);
|
||||
|
||||
if (timeSinceLastRewardCache > cooldown && Math.random() < rewardCacheChance && !isLabServer) {
|
||||
addCacheToServer(server);
|
||||
if (phishingCacheCooldownReached() && Math.random() < rewardCacheChance && !isLabServer) {
|
||||
addCacheToServer(server, true);
|
||||
Player.gainCharismaExp(xpReward);
|
||||
DarknetState.lastPhishingCacheTime = new Date();
|
||||
const result = `Phishing attack succeeded! Found a cache file. (Gained ${formatNumber(xpGained, 1)} cha xp)`;
|
||||
const result = `Phishing attack succeeded! Found a cache file. (Gained ${formatNumber(xpReward, 1)} cha xp)`;
|
||||
helpers.log(ctx, () => result);
|
||||
return {
|
||||
success: true,
|
||||
@@ -38,17 +35,19 @@ export const handlePhishingAttack = (ctx: NetscriptContext, server: DarknetServe
|
||||
const bonusTimeFactor = hasDarknetBonusTime() ? 1.3 : 1;
|
||||
const depthFactor = 0.1 + server.depth * 0.05;
|
||||
const moneyReward =
|
||||
2000 *
|
||||
500 *
|
||||
Player.mults.crime_money *
|
||||
Player.mults.dnet_money *
|
||||
depthFactor *
|
||||
threads *
|
||||
((200 + Player.skills.charisma) / 200) *
|
||||
((400 + Player.skills.charisma) / 400) *
|
||||
bonusTimeFactor *
|
||||
randomFactor *
|
||||
currentNodeMults.DarknetMoneyMultiplier;
|
||||
Player.gainMoney(moneyReward, "darknet");
|
||||
Player.gainCharismaExp(xpReward);
|
||||
const result = `Phishing attack succeeded! $${formatNumber(moneyReward, 2)} retrieved. (Gained ${formatNumber(
|
||||
xpGained,
|
||||
xpReward,
|
||||
1,
|
||||
)} cha xp)`;
|
||||
helpers.log(ctx, () => result);
|
||||
@@ -58,7 +57,8 @@ export const handlePhishingAttack = (ctx: NetscriptContext, server: DarknetServe
|
||||
message: result,
|
||||
};
|
||||
}
|
||||
const result = `There were no takers on that phishing attempt. (Gained ${formatNumber(xpGained, 1)} cha xp)`;
|
||||
Player.gainCharismaExp(xpReward / 4);
|
||||
const result = `There were no takers on that phishing attempt. (Gained ${formatNumber(xpReward / 4, 1)} cha xp)`;
|
||||
helpers.log(ctx, () => result);
|
||||
return {
|
||||
success: false,
|
||||
@@ -66,3 +66,8 @@ export const handlePhishingAttack = (ctx: NetscriptContext, server: DarknetServe
|
||||
message: result,
|
||||
};
|
||||
};
|
||||
|
||||
const phishingCacheCooldownReached = () => {
|
||||
const timeSinceLastRewardCache = new Date().getTime() - DarknetState.lastPhishingCacheTime.getTime();
|
||||
return timeSinceLastRewardCache > 3 * 60 * 1000; // 3 minutes;
|
||||
};
|
||||
|
||||
@@ -27,8 +27,7 @@ export const handleRamBlockRemoved = (ctx: NetscriptContext, server: DarknetServ
|
||||
if (server.blockedRam <= 0) {
|
||||
handleRamBlockClearedRewards(server);
|
||||
}
|
||||
const xpGained =
|
||||
Player.mults.charisma_exp * threads * 10 * 1.1 ** difficulty * ((200 + Player.skills.charisma) / 200);
|
||||
const xpGained = Player.mults.charisma_exp * threads * 10 * 1.1 ** difficulty;
|
||||
Player.gainCharismaExp(xpGained);
|
||||
|
||||
const result = `Liberated ${formatNumber(
|
||||
@@ -48,7 +47,7 @@ export const handleRamBlockRemoved = (ctx: NetscriptContext, server: DarknetServ
|
||||
*/
|
||||
export const handleRamBlockClearedRewards = (server: DarknetServer) => {
|
||||
if (!isLabyrinthServer(server.hostname)) {
|
||||
addCacheToServer(server);
|
||||
addCacheToServer(server, false);
|
||||
}
|
||||
if (Math.random() < 0.3) {
|
||||
addClue(server);
|
||||
|
||||
@@ -17,6 +17,7 @@ import { getRamBlock } from "../effects/ramblock";
|
||||
import { hasFullDarknetAccess } from "../effects/effects";
|
||||
import { getFriendlyType, TypeAssertionError } from "../../utils/TypeAssertion";
|
||||
import { isIPAddress } from "../../Types/strings";
|
||||
import { roundToTwo } from "../../utils/helpers/roundToTwo";
|
||||
|
||||
export type PasswordResponse = {
|
||||
code: DarknetResponseCode;
|
||||
@@ -58,7 +59,7 @@ export type DarknetServerOptions = {
|
||||
};
|
||||
|
||||
export const DnetServerBuilder = (options: DarknetServerOptions): DarknetServer => {
|
||||
const maxRam = 16 * 2 ** Math.floor(options.difficulty / 4);
|
||||
const maxRam = getMaxRam(options.difficulty);
|
||||
const ramBlock = options.preventBlockedRam ? 0 : getRamBlock(maxRam);
|
||||
const name = options.name ?? generateDarknetServerName();
|
||||
|
||||
@@ -192,3 +193,10 @@ const l33tifyName = (name: string): string => {
|
||||
}
|
||||
return updatedName;
|
||||
};
|
||||
|
||||
const getMaxRam = (difficulty: number): number => {
|
||||
const baseRam = 16 * 2 ** Math.floor(difficulty / 6);
|
||||
const sizeMutations = [0.5, 1, 1, 1.15, 1.4];
|
||||
const mutation = sizeMutations[Math.floor(Math.random() * sizeMutations.length)];
|
||||
return roundToTwo(Math.max(baseRam * mutation, 16));
|
||||
};
|
||||
|
||||
@@ -47,6 +47,7 @@ export const DarknetState = {
|
||||
labLocations: { "-1": [1, 1] } as Record<number, [number, number] | undefined>,
|
||||
|
||||
lastPhishingCacheTime: new Date(),
|
||||
lastCctRewardTime: new Date(),
|
||||
lastStormTime: new Date(),
|
||||
|
||||
stockPromotions: {} as Record<string, number>,
|
||||
|
||||
@@ -14,7 +14,7 @@ import { exceptionAlert } from "../../utils/helpers/exceptionAlert";
|
||||
const MAX_LOG_LINES = 200;
|
||||
|
||||
export const capturePackets = (server: DarknetServer) => {
|
||||
const BASE_PASSWORD_INCLUSION_RATE = 0.18;
|
||||
const BASE_PASSWORD_INCLUSION_RATE = 0.12;
|
||||
const DIFFICULTY_MODIFIER = 0.88;
|
||||
const difficulty = server.difficulty * 1.3;
|
||||
const vulnerability = server.modelId === ModelIds.packetSniffer ? 8 : 1;
|
||||
|
||||
@@ -252,7 +252,7 @@ export function NetworkDisplayWrapper(): React.ReactElement {
|
||||
<Typography variant={"h5"} sx={{ fontWeight: "bold" }}>
|
||||
Dark Net
|
||||
</Typography>
|
||||
{instability && (
|
||||
{instability > 0 && (
|
||||
<Tooltip
|
||||
title={
|
||||
<>
|
||||
@@ -299,13 +299,13 @@ export function NetworkDisplayWrapper(): React.ReactElement {
|
||||
{DarknetState.Network.slice(0, netDisplayDepth).map((row) =>
|
||||
row.map(
|
||||
(server) =>
|
||||
server && (
|
||||
!!server && (
|
||||
<ServerStatusBox server={server} key={server.ip} enableAuth={allowAuth(server)} classes={classes} />
|
||||
),
|
||||
),
|
||||
)}
|
||||
|
||||
{labyrinth && netDisplayDepth > depth && (
|
||||
{!!labyrinth && netDisplayDepth > depth && (
|
||||
<ServerStatusBox server={labyrinth} enableAuth={allowAuth(labyrinth)} classes={classes} />
|
||||
)}
|
||||
</div>
|
||||
|
||||
@@ -149,7 +149,7 @@ export const PasswordPrompt = ({ server, onClose }: PasswordPromptProps): React.
|
||||
<pre style={{ whiteSpace: "pre-wrap", margin: 0 }}>
|
||||
<span className={classes.serverDetailsText}>Hint:</span> {server.staticPasswordHint}
|
||||
<br />
|
||||
{server.passwordHintData && (
|
||||
{!!server.passwordHintData && (
|
||||
<>
|
||||
<span className={classes.serverDetailsText}>Data: </span> {server.passwordHintData}
|
||||
<br />
|
||||
|
||||
@@ -86,7 +86,7 @@ export const getAllAdjacentNeighbors = (x: number, y: number): DarknetServer[] =
|
||||
|
||||
export const getIslands = () => getAllMovableDarknetServers().filter((s) => !s.serversOnNetwork.length);
|
||||
|
||||
export const getBackdooredDarkwebServers = (): DarknetServer[] =>
|
||||
export const getBackdooredDarknetServers = (): DarknetServer[] =>
|
||||
getAllMovableDarknetServers().filter((s) => !s.hasStasisLink && s.backdoorInstalled);
|
||||
|
||||
export const getNearbyNonEmptyPasswordServer = (server: DarknetServer, disconnected = false) => {
|
||||
|
||||
@@ -950,6 +950,7 @@ import nsDoc_bitburner_multipliers_defense_exp_md from "../../markdown/bitburner
|
||||
import nsDoc_bitburner_multipliers_defense_md from "../../markdown/bitburner.multipliers.defense.md?raw";
|
||||
import nsDoc_bitburner_multipliers_dexterity_exp_md from "../../markdown/bitburner.multipliers.dexterity_exp.md?raw";
|
||||
import nsDoc_bitburner_multipliers_dexterity_md from "../../markdown/bitburner.multipliers.dexterity.md?raw";
|
||||
import nsDoc_bitburner_multipliers_dnet_money_md from "../../markdown/bitburner.multipliers.dnet_money.md?raw";
|
||||
import nsDoc_bitburner_multipliers_faction_rep_md from "../../markdown/bitburner.multipliers.faction_rep.md?raw";
|
||||
import nsDoc_bitburner_multipliers_hacking_chance_md from "../../markdown/bitburner.multipliers.hacking_chance.md?raw";
|
||||
import nsDoc_bitburner_multipliers_hacking_exp_md from "../../markdown/bitburner.multipliers.hacking_exp.md?raw";
|
||||
@@ -2545,6 +2546,7 @@ AllPages["nsDoc/bitburner.multipliers.defense_exp.md"] = nsDoc_bitburner_multipl
|
||||
AllPages["nsDoc/bitburner.multipliers.defense.md"] = nsDoc_bitburner_multipliers_defense_md;
|
||||
AllPages["nsDoc/bitburner.multipliers.dexterity_exp.md"] = nsDoc_bitburner_multipliers_dexterity_exp_md;
|
||||
AllPages["nsDoc/bitburner.multipliers.dexterity.md"] = nsDoc_bitburner_multipliers_dexterity_md;
|
||||
AllPages["nsDoc/bitburner.multipliers.dnet_money.md"] = nsDoc_bitburner_multipliers_dnet_money_md;
|
||||
AllPages["nsDoc/bitburner.multipliers.faction_rep.md"] = nsDoc_bitburner_multipliers_faction_rep_md;
|
||||
AllPages["nsDoc/bitburner.multipliers.hacking_chance.md"] = nsDoc_bitburner_multipliers_hacking_chance_md;
|
||||
AllPages["nsDoc/bitburner.multipliers.hacking_exp.md"] = nsDoc_bitburner_multipliers_hacking_exp_md;
|
||||
|
||||
@@ -38,7 +38,11 @@ export function NetscriptCodingContract(): InternalAPI<ICodingContract> {
|
||||
const resultOfCheckingSolution = contract.isSolution(answer);
|
||||
switch (resultOfCheckingSolution.result) {
|
||||
case CodingContractResult.Success: {
|
||||
const reward = Player.gainCodingContractReward(contract.reward, contract.getDifficulty());
|
||||
const reward = Player.gainCodingContractReward(
|
||||
contract.reward,
|
||||
contract.getDifficulty(),
|
||||
contract.rewardScaling,
|
||||
);
|
||||
helpers.log(ctx, () => `Successfully completed Coding Contract '${contract.fn}'. Reward: ${reward}`);
|
||||
server.removeContract(contract.fn);
|
||||
return reward;
|
||||
|
||||
@@ -426,7 +426,7 @@ export function NetscriptDarknet(): InternalAPI<DarknetAPI> {
|
||||
|
||||
const server = serverCheck.server;
|
||||
const networkDelay =
|
||||
calculateAuthenticationTime(server, Player, ctx.workerScript.scriptRef.threads, "", true) * 4;
|
||||
calculateAuthenticationTime(server, Player, ctx.workerScript.scriptRef.threads, "", true) * 6;
|
||||
const xp = formatNumber(calculatePasswordAttemptChaGain(server, ctx.workerScript.scriptRef.threads), 1);
|
||||
|
||||
logger(ctx)(`Captured some outgoing transmissions from ${server.hostname}. (Gained ${xp} cha xp)`);
|
||||
|
||||
@@ -30,6 +30,7 @@ export const calculateEntropy = (stacks = 1): Multipliers => {
|
||||
|
||||
crime_money: Player.mults.crime_money * nerf,
|
||||
crime_success: Player.mults.crime_success * nerf,
|
||||
dnet_money: Player.mults.dnet_money * nerf,
|
||||
|
||||
hacknet_node_money: Player.mults.hacknet_node_money * nerf,
|
||||
hacknet_node_purchase_cost: Player.mults.hacknet_node_purchase_cost / nerf,
|
||||
|
||||
@@ -25,6 +25,7 @@ export interface Multipliers {
|
||||
work_money: number;
|
||||
crime_success: number;
|
||||
crime_money: number;
|
||||
dnet_money: number;
|
||||
bladeburner_max_stamina: number;
|
||||
bladeburner_stamina_gain: number;
|
||||
bladeburner_analysis: number;
|
||||
@@ -59,6 +60,7 @@ export const defaultMultipliers = (): Multipliers => {
|
||||
work_money: 1,
|
||||
crime_success: 1,
|
||||
crime_money: 1,
|
||||
dnet_money: 1,
|
||||
bladeburner_max_stamina: 1,
|
||||
bladeburner_stamina_gain: 1,
|
||||
bladeburner_analysis: 1,
|
||||
@@ -94,6 +96,7 @@ export const mergeMultipliers = (m0: Multipliers, m1: Multipliers): Multipliers
|
||||
work_money: m0.work_money * m1.work_money,
|
||||
crime_success: m0.crime_success * m1.crime_success,
|
||||
crime_money: m0.crime_money * m1.crime_money,
|
||||
dnet_money: m0.dnet_money * m1.dnet_money,
|
||||
bladeburner_max_stamina: m0.bladeburner_max_stamina * m1.bladeburner_max_stamina,
|
||||
bladeburner_stamina_gain: m0.bladeburner_stamina_gain * m1.bladeburner_stamina_gain,
|
||||
bladeburner_analysis: m0.bladeburner_analysis * m1.bladeburner_analysis,
|
||||
@@ -129,6 +132,7 @@ export const scaleMultipliers = (m0: Multipliers, v: number): Multipliers => {
|
||||
work_money: (m0.work_money - 1) * v + 1,
|
||||
crime_success: (m0.crime_success - 1) * v + 1,
|
||||
crime_money: (m0.crime_money - 1) * v + 1,
|
||||
dnet_money: (m0.dnet_money - 1) * v + 1,
|
||||
bladeburner_max_stamina: (m0.bladeburner_max_stamina - 1) * v + 1,
|
||||
bladeburner_stamina_gain: (m0.bladeburner_stamina_gain - 1) * v + 1,
|
||||
bladeburner_analysis: (m0.bladeburner_analysis - 1) * v + 1,
|
||||
|
||||
@@ -499,7 +499,8 @@ export function queueAugmentation(this: PlayerObject, name: AugmentationName): v
|
||||
export function gainCodingContractReward(
|
||||
this: PlayerObject,
|
||||
reward: ICodingContractReward | null,
|
||||
difficulty = 1,
|
||||
difficulty: number,
|
||||
rewardScaling: number,
|
||||
): string {
|
||||
if (!reward) {
|
||||
return `No reward for this contract`;
|
||||
@@ -509,20 +510,20 @@ export function gainCodingContractReward(
|
||||
case CodingContractRewardType.FactionReputation: {
|
||||
const factionsThatAllowHacking = Player.factions.filter((fac) => Factions[fac].getInfo().offerHackingWork);
|
||||
if (factionsThatAllowHacking.length === 0) {
|
||||
return this.gainCodingContractReward({ type: CodingContractRewardType.Money }, difficulty);
|
||||
return this.gainCodingContractReward({ type: CodingContractRewardType.Money }, difficulty, rewardScaling);
|
||||
}
|
||||
const randomFaction = factionsThatAllowHacking[getRandomIntInclusive(0, factionsThatAllowHacking.length - 1)];
|
||||
const repGain = CONSTANTS.CodingContractBaseFactionRepGain * difficulty;
|
||||
const repGain = CONSTANTS.CodingContractBaseFactionRepGain * difficulty * rewardScaling;
|
||||
Factions[randomFaction].playerReputation += repGain;
|
||||
return `Gained ${repGain} faction reputation for ${randomFaction}`;
|
||||
}
|
||||
case CodingContractRewardType.FactionReputationAll: {
|
||||
const factionsThatAllowHacking = Player.factions.filter((fac) => Factions[fac].getInfo().offerHackingWork);
|
||||
if (factionsThatAllowHacking.length === 0) {
|
||||
return this.gainCodingContractReward({ type: CodingContractRewardType.Money }, difficulty);
|
||||
return this.gainCodingContractReward({ type: CodingContractRewardType.Money }, difficulty, rewardScaling);
|
||||
}
|
||||
|
||||
const totalGain = CONSTANTS.CodingContractBaseFactionRepGain * difficulty;
|
||||
const totalGain = CONSTANTS.CodingContractBaseFactionRepGain * difficulty * rewardScaling;
|
||||
const gainPerFaction = Math.floor(totalGain / factionsThatAllowHacking.length);
|
||||
for (const facName of factionsThatAllowHacking) {
|
||||
Factions[facName].playerReputation += gainPerFaction;
|
||||
@@ -542,15 +543,17 @@ export function gainCodingContractReward(
|
||||
: CodingContractRewardType.FactionReputationAll,
|
||||
},
|
||||
difficulty,
|
||||
rewardScaling,
|
||||
);
|
||||
}
|
||||
const randomCompany = companies[getRandomIntInclusive(0, companies.length - 1)];
|
||||
const repGain = CONSTANTS.CodingContractBaseCompanyRepGain * difficulty;
|
||||
const repGain = CONSTANTS.CodingContractBaseCompanyRepGain * difficulty * rewardScaling;
|
||||
Companies[randomCompany].playerReputation += repGain;
|
||||
return `Gained ${repGain} company reputation for ${randomCompany}`;
|
||||
}
|
||||
case CodingContractRewardType.Money: {
|
||||
const moneyGain = CONSTANTS.CodingContractBaseMoneyGain * difficulty * currentNodeMults.CodingContractMoney;
|
||||
const moneyGain =
|
||||
CONSTANTS.CodingContractBaseMoneyGain * difficulty * currentNodeMults.CodingContractMoney * rewardScaling;
|
||||
this.gainMoney(moneyGain, "codingcontract");
|
||||
return `Gained ${formatMoney(moneyGain)}`;
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ function mult(favor: number): number {
|
||||
|
||||
export function getHackingWorkRepGain(p: IPerson, favor: number): number {
|
||||
return (
|
||||
((p.skills.hacking + p.skills.intelligence + getDarknetCharismaBonus(p, 0.15) / 3) / CONSTANTS.MaxSkillLevel) *
|
||||
((p.skills.hacking + p.skills.intelligence / 3 + getDarknetCharismaBonus(p, 0.1)) / CONSTANTS.MaxSkillLevel) *
|
||||
p.mults.faction_rep *
|
||||
calculateIntelligenceBonus(p.skills.intelligence, 1) *
|
||||
mult(favor) *
|
||||
@@ -30,7 +30,8 @@ export function getFactionSecurityWorkRepGain(p: IPerson, favor: number): number
|
||||
p.skills.defense +
|
||||
p.skills.dexterity +
|
||||
p.skills.agility +
|
||||
(p.skills.hacking + p.skills.intelligence + getDarknetCharismaBonus(p, 0.3)) * calculateCurrentShareBonus())) /
|
||||
getDarknetCharismaBonus(p, 0.3) +
|
||||
(p.skills.hacking + p.skills.intelligence) * calculateCurrentShareBonus())) /
|
||||
CONSTANTS.MaxSkillLevel /
|
||||
4.5;
|
||||
return t * p.mults.faction_rep * mult(favor) * calculateIntelligenceBonus(p.skills.intelligence, 1);
|
||||
|
||||
14
src/ScriptEditor/NetscriptDefinitions.d.ts
vendored
14
src/ScriptEditor/NetscriptDefinitions.d.ts
vendored
@@ -178,6 +178,8 @@ interface Multipliers {
|
||||
crime_money: number;
|
||||
/** Multiplier to crime success rate */
|
||||
crime_success: number;
|
||||
/** Multiplier to amount of money gained from phishing and caches on darknet servers */
|
||||
dnet_money: number;
|
||||
/** Multiplier to amount of money gained from working */
|
||||
work_money: number;
|
||||
/** Multiplier to amount of money produced by Hacknet Nodes */
|
||||
@@ -4497,13 +4499,16 @@ export interface Darknet {
|
||||
* Sends a network request to try to authenticate on a darkweb server. The target server must be directly connected
|
||||
* to the server that the script is running on. The speed of authentication scales with the number of threads used.
|
||||
*
|
||||
* If successful, grants the script a session, allowing it to exec() scripts on that server, or scp() files to it. (scp() *from* the server is always allowed.)
|
||||
* If successful, grants the current script a session, allowing it to exec() scripts on that server, or scp() files to it. (scp() *from* the server is always allowed.)
|
||||
*
|
||||
* Note that the charisma level on a server is not a requirement for authentication, but authentication takes longer
|
||||
* if the player's charisma is below the server's charisma level.
|
||||
*
|
||||
* Note that the session granted is only for the current script instance (by PID) - other running scripts will need to
|
||||
* use connectToSession with the correct password to also get a session with the target server.
|
||||
*
|
||||
* @remarks
|
||||
* RAM cost: 0.6 GB
|
||||
* RAM cost: 0.4 GB
|
||||
*
|
||||
* @param host - Hostname/IP of the target server (connected to the current server) to try a password.
|
||||
* @param password - Password to attempt to authenticate with.
|
||||
@@ -4518,12 +4523,15 @@ export interface Darknet {
|
||||
* Attempts to connect to a target darkweb server that you have previously authenticated on. Unlike `authenticate`,
|
||||
* connectToSession can be used to get a session on servers at any distance.
|
||||
*
|
||||
* If successful, grants the script a session, allowing it to scp() files from that target. It also allows starting scripts
|
||||
* If successful, grants the script a session, allowing it to scp() files to that target. It also allows starting scripts
|
||||
* with exec() on that target, if the target is directly connected to the server that the script is running on,
|
||||
* or has a backdoor or stasis link.
|
||||
*
|
||||
* If unsuccessful, more detail may be able to be gathered by using heartbleed() to look at the resulting logs on the server.
|
||||
*
|
||||
* Note that the session granted is only for the current script instance (by PID) - other running scripts will need to
|
||||
* use connectToSession with the correct password to also get a session with the target server.
|
||||
*
|
||||
* @remarks
|
||||
* RAM cost: 0.05 GB
|
||||
*
|
||||
|
||||
@@ -551,7 +551,11 @@ export class Terminal {
|
||||
switch (promptResult.result) {
|
||||
case CodingContractResult.Success:
|
||||
if (contract.reward !== null) {
|
||||
const reward = Player.gainCodingContractReward(contract.reward, contract.getDifficulty());
|
||||
const reward = Player.gainCodingContractReward(
|
||||
contract.reward,
|
||||
contract.getDifficulty(),
|
||||
contract.rewardScaling,
|
||||
);
|
||||
this.print(`Contract SUCCESS - ${reward}`);
|
||||
}
|
||||
server.removeContract(contract);
|
||||
|
||||
@@ -534,6 +534,12 @@ export function CharacterStats(): React.ReactElement {
|
||||
effValue: Player.mults.crime_money * currentNodeMults.CrimeMoney,
|
||||
color: Settings.theme.money,
|
||||
},
|
||||
{
|
||||
mult: "Darknet Money",
|
||||
value: Player.mults.dnet_money,
|
||||
effValue: Player.mults.dnet_money * currentNodeMults.DarknetMoneyMultiplier,
|
||||
color: Settings.theme.money,
|
||||
},
|
||||
]}
|
||||
color={Settings.theme.combat}
|
||||
/>
|
||||
|
||||
@@ -813,7 +813,7 @@ describe("Darknet server name generator", () => {
|
||||
describe("Cache filename generator", () => {
|
||||
test("Random prefix", () => {
|
||||
for (let i = 0; i < 10000; ++i) {
|
||||
const cacheFilename = generateCacheFilename();
|
||||
const cacheFilename = generateCacheFilename(false);
|
||||
if (!cacheFilename) {
|
||||
throw new Error("Invalid cache filename");
|
||||
}
|
||||
@@ -821,7 +821,7 @@ describe("Cache filename generator", () => {
|
||||
}
|
||||
});
|
||||
test("Cache file in labyrinth server", () => {
|
||||
const cacheFilename = generateCacheFilename(LAB_CACHE_NAME);
|
||||
const cacheFilename = generateCacheFilename(false, LAB_CACHE_NAME);
|
||||
if (!cacheFilename) {
|
||||
throw new Error("Invalid cache filename");
|
||||
}
|
||||
|
||||
@@ -774,7 +774,7 @@ describe("darkweb", () => {
|
||||
test("openCache", () => {
|
||||
const ns = getNsOnDarkWeb();
|
||||
const darkweb = getDarknetServerOrThrow(SpecialServers.DarkWeb);
|
||||
const result = addCacheToServer(darkweb, "test");
|
||||
const result = addCacheToServer(darkweb, false, "test");
|
||||
if (!result.success) {
|
||||
throw new Error("Cannot add cache");
|
||||
}
|
||||
|
||||
@@ -517,6 +517,7 @@ exports[`Check Save File Continuity PlayerSave continuity 1`] = `
|
||||
"defense_exp": 1,
|
||||
"dexterity": 1,
|
||||
"dexterity_exp": 1,
|
||||
"dnet_money": 1,
|
||||
"faction_rep": 1,
|
||||
"hacking": 1,
|
||||
"hacking_chance": 1,
|
||||
@@ -601,6 +602,7 @@ exports[`Check Save File Continuity PlayerSave continuity 1`] = `
|
||||
"defense_exp": 1,
|
||||
"dexterity": 1.3,
|
||||
"dexterity_exp": 1,
|
||||
"dnet_money": 1,
|
||||
"faction_rep": 1,
|
||||
"hacking": 1,
|
||||
"hacking_chance": 1,
|
||||
@@ -676,6 +678,7 @@ exports[`Check Save File Continuity PlayerSave continuity 1`] = `
|
||||
"defense_exp": 1,
|
||||
"dexterity": 1,
|
||||
"dexterity_exp": 1,
|
||||
"dnet_money": 1,
|
||||
"faction_rep": 1,
|
||||
"hacking": 1,
|
||||
"hacking_chance": 1,
|
||||
|
||||
Reference in New Issue
Block a user