Finish removing player passing

This commit is contained in:
Snarling 2022-09-17 21:09:15 -04:00
parent c864fd7edf
commit 21a2d49de7
23 changed files with 112 additions and 203 deletions

@ -1,14 +1,13 @@
import { ActiveFragment } from "./ActiveFragment";
import { Fragment } from "./Fragment";
import { IPlayer } from "../PersonObjects/IPlayer";
export interface IStaneksGift {
storedCycles: number;
fragments: ActiveFragment[];
width(): number;
height(): number;
charge(player: IPlayer, fragment: ActiveFragment, threads: number): void;
process(p: IPlayer, n: number): void;
charge(fragment: ActiveFragment, threads: number): void;
process(n: number): void;
effect(fragment: ActiveFragment): number;
canPlace(x: number, y: number, rotation: number, fragment: Fragment): boolean;
place(x: number, y: number, rotation: number, fragment: Fragment): boolean;

@ -3,7 +3,6 @@ import { Fragment } from "./Fragment";
import { ActiveFragment } from "./ActiveFragment";
import { FragmentType } from "./FragmentType";
import { IStaneksGift } from "./IStaneksGift";
import { IPlayer } from "../PersonObjects/IPlayer";
import { Factions } from "../Faction/Factions";
import { CalculateEffect } from "./formulas/effect";
import { StaneksGiftEvents } from "./StaneksGiftEvents";
@ -30,7 +29,7 @@ export class StaneksGift implements IStaneksGift {
return Math.max(3, Math.min(Math.floor(this.baseSize() / 2 + 0.6), StanekConstants.MaxSize));
}
charge(player: IPlayer, af: ActiveFragment, threads: number): void {
charge(af: ActiveFragment, threads: number): void {
if (threads > af.highestCharge) {
af.numCharge = (af.highestCharge * af.numCharge) / threads + 1;
af.highestCharge = threads;
@ -39,19 +38,19 @@ export class StaneksGift implements IStaneksGift {
}
const cotmg = Factions[FactionNames.ChurchOfTheMachineGod];
cotmg.playerReputation += (player.mults.faction_rep * (Math.pow(threads, 0.95) * (cotmg.favor + 100))) / 1000;
cotmg.playerReputation += (Player.mults.faction_rep * (Math.pow(threads, 0.95) * (cotmg.favor + 100))) / 1000;
}
inBonus(): boolean {
return (this.storedCycles * CONSTANTS._idleSpeed) / 1000 > 1;
}
process(p: IPlayer, numCycles = 1): void {
if (!p.hasAugmentation(AugmentationNames.StaneksGift1)) return;
process(numCycles = 1): void {
if (!Player.hasAugmentation(AugmentationNames.StaneksGift1)) return;
this.storedCycles += numCycles;
this.storedCycles -= 10;
this.storedCycles = Math.max(0, this.storedCycles);
this.updateMults(p);
this.updateMults();
StaneksGiftEvents.emit();
}
@ -210,19 +209,19 @@ export class StaneksGift implements IStaneksGift {
return mults;
}
updateMults(p: IPlayer): void {
updateMults(): void {
// applyEntropy also reapplies all augmentations and source files
// This wraps up the reset nicely
p.applyEntropy(p.entropy);
Player.applyEntropy(Player.entropy);
const mults = this.calculateMults();
p.mults = mergeMultipliers(p.mults, mults);
p.updateSkillLevels();
const zoeAmt = p.sleeves.reduce((n, sleeve) => n + (sleeve.hasAugmentation(AugmentationNames.ZOE) ? 1 : 0), 0);
Player.mults = mergeMultipliers(Player.mults, mults);
Player.updateSkillLevels();
const zoeAmt = Player.sleeves.reduce((n, sleeve) => n + (sleeve.hasAugmentation(AugmentationNames.ZOE) ? 1 : 0), 0);
if (zoeAmt === 0) return;
// Less powerful for each copy.
const scaling = 3 / (zoeAmt + 2);
const sleeveMults = scaleMultipliers(mults, scaling);
for (const sleeve of p.sleeves) {
for (const sleeve of Player.sleeves) {
if (!sleeve.hasAugmentation(AugmentationNames.ZOE)) continue;
sleeve.resetMultipliers();
sleeve.mults = mergeMultipliers(sleeve.mults, sleeveMults);

@ -23,7 +23,7 @@ import { AllGangs } from "./AllGangs";
import { GangMember } from "./GangMember";
import { WorkerScript } from "../Netscript/WorkerScript";
import { IPlayer } from "../PersonObjects/IPlayer";
import { Player } from "../Player";
import { PowerMultiplier } from "./data/power";
import { IGang } from "./IGang";
@ -82,7 +82,7 @@ export class Gang implements IGang {
return AllGangs[this.facName].territory;
}
process(numCycles = 1, player: IPlayer): void {
process(numCycles = 1): void {
const CyclesPerSecond = 1000 / CONSTANTS._idleSpeed;
if (isNaN(numCycles)) {
@ -95,7 +95,7 @@ export class Gang implements IGang {
const cycles = Math.min(this.storedCycles, 5 * CyclesPerSecond);
try {
this.processGains(cycles, player);
this.processGains(cycles);
this.processExperienceGains(cycles);
this.processTerritoryAndPowerGains(cycles);
this.storedCycles -= cycles;
@ -104,7 +104,7 @@ export class Gang implements IGang {
}
}
processGains(numCycles = 1, player: IPlayer): void {
processGains(numCycles = 1): void {
// Get gains per cycle
let moneyGains = 0;
let respectGains = 0;
@ -132,7 +132,7 @@ export class Gang implements IGang {
}
const favorMult = 1 + fac.favor / 100;
fac.playerReputation += (player.mults.faction_rep * gain * favorMult) / GangConstants.GangRespectToReputationRatio;
fac.playerReputation += (Player.mults.faction_rep * gain * favorMult) / GangConstants.GangRespectToReputationRatio;
// Keep track of respect gained per member
for (let i = 0; i < this.members.length; ++i) {
@ -148,7 +148,7 @@ export class Gang implements IGang {
this.wanted = newWanted;
if (this.wanted < 1) this.wanted = 1;
}
player.gainMoney(moneyGains * numCycles, "gang");
Player.gainMoney(moneyGains * numCycles, "gang");
}
processTerritoryAndPowerGains(numCycles = 1): void {

@ -1,7 +1,6 @@
import { GangMemberUpgrade } from "./GangMemberUpgrade";
import { GangMember } from "./GangMember";
import { WorkerScript } from "../Netscript/WorkerScript";
import { IPlayer } from "../PersonObjects/IPlayer";
import { IAscensionResult } from "./IAscensionResult";
import { IReviverValue } from "src/utils/JSONReviver";
@ -28,8 +27,8 @@ export interface IGang {
getPower(): number;
getTerritory(): number;
process(numCycles: number, player: IPlayer): void;
processGains(numCycles: number, player: IPlayer): void;
process(numCycles: number): void;
processGains(numCycles: number): void;
processTerritoryAndPowerGains(numCycles: number): void;
processExperienceGains(numCycles: number): void;
clash(won: boolean): void;

@ -1,30 +1,30 @@
import { IPlayer } from "../../PersonObjects/IPlayer";
import { Player } from "../../Player";
import { calculateSkill } from "../../PersonObjects/formulas/skill";
function calculateRawDiff(player: IPlayer, stats: number, startingDifficulty: number): number {
const difficulty = startingDifficulty - Math.pow(stats, 0.9) / 250 - player.skills.intelligence / 1600;
function calculateRawDiff(stats: number, startingDifficulty: number): number {
const difficulty = startingDifficulty - Math.pow(stats, 0.9) / 250 - Player.skills.intelligence / 1600;
if (difficulty < 0) return 0;
if (difficulty > 3) return 3;
return difficulty;
}
export function calculateDifficulty(player: IPlayer, startingSecurityLevel: number): number {
export function calculateDifficulty(startingSecurityLevel: number): number {
const totalStats =
player.skills.strength +
player.skills.defense +
player.skills.dexterity +
player.skills.agility +
player.skills.charisma;
return calculateRawDiff(player, totalStats, startingSecurityLevel);
Player.skills.strength +
Player.skills.defense +
Player.skills.dexterity +
Player.skills.agility +
Player.skills.charisma;
return calculateRawDiff(totalStats, startingSecurityLevel);
}
export function calculateReward(player: IPlayer, startingSecurityLevel: number): number {
export function calculateReward(startingSecurityLevel: number): number {
const xpMult = 10 * 60 * 15;
const total =
calculateSkill(player.mults.strength_exp * xpMult, player.mults.strength) +
calculateSkill(player.mults.defense_exp * xpMult, player.mults.defense) +
calculateSkill(player.mults.agility_exp * xpMult, player.mults.agility) +
calculateSkill(player.mults.dexterity_exp * xpMult, player.mults.dexterity) +
calculateSkill(player.mults.charisma_exp * xpMult, player.mults.charisma);
return calculateRawDiff(player, total, startingSecurityLevel);
calculateSkill(Player.mults.strength_exp * xpMult, Player.mults.strength) +
calculateSkill(Player.mults.defense_exp * xpMult, Player.mults.defense) +
calculateSkill(Player.mults.agility_exp * xpMult, Player.mults.agility) +
calculateSkill(Player.mults.dexterity_exp * xpMult, Player.mults.dexterity) +
calculateSkill(Player.mults.charisma_exp * xpMult, Player.mults.charisma);
return calculateRawDiff(total, startingSecurityLevel);
}

@ -1,15 +1,10 @@
import { IPlayer } from "../../PersonObjects/IPlayer";
import { Player } from "../../Player";
import { BitNodeMultipliers } from "../../BitNode/BitNodeMultipliers";
import { LocationsMetadata } from "../../Locations/data/LocationsMetadata";
import { AugmentationNames } from "../../Augmentation/data/AugmentationNames";
import { Faction } from "../../Faction/Faction";
export function calculateSellInformationCashReward(
player: IPlayer,
reward: number,
maxLevel: number,
difficulty: number,
): number {
export function calculateSellInformationCashReward(reward: number, maxLevel: number, difficulty: number): number {
const levelBonus = maxLevel * Math.pow(1.01, maxLevel);
return (
@ -17,17 +12,12 @@ export function calculateSellInformationCashReward(
Math.pow(difficulty, 3) *
3e3 *
levelBonus *
(player.hasAugmentation(AugmentationNames.WKSharmonizer, true) ? 1.5 : 1) *
(Player.hasAugmentation(AugmentationNames.WKSharmonizer, true) ? 1.5 : 1) *
BitNodeMultipliers.InfiltrationMoney
);
}
export function calculateTradeInformationRepReward(
player: IPlayer,
reward: number,
maxLevel: number,
difficulty: number,
): number {
export function calculateTradeInformationRepReward(reward: number, maxLevel: number, difficulty: number): number {
const levelBonus = maxLevel * Math.pow(1.01, maxLevel);
return (
@ -35,12 +25,12 @@ export function calculateTradeInformationRepReward(
Math.pow(difficulty, 1.2) *
30 *
levelBonus *
(player.hasAugmentation(AugmentationNames.WKSharmonizer, true) ? 1.5 : 1) *
(Player.hasAugmentation(AugmentationNames.WKSharmonizer, true) ? 1.5 : 1) *
BitNodeMultipliers.InfiltrationRep
);
}
export function calculateInfiltratorsRepReward(player: IPlayer, faction: Faction, difficulty: number): number {
export function calculateInfiltratorsRepReward(faction: Faction, difficulty: number): number {
const maxStartingSecurityLevel = LocationsMetadata.reduce((acc, data): number => {
const startingSecurityLevel = data.infiltrationData?.startingSecurityLevel || 0;
return acc > startingSecurityLevel ? acc : startingSecurityLevel;
@ -48,6 +38,6 @@ export function calculateInfiltratorsRepReward(player: IPlayer, faction: Faction
const baseRepGain = (difficulty / maxStartingSecurityLevel) * 5000;
return (
baseRepGain * (player.hasAugmentation(AugmentationNames.WKSharmonizer, true) ? 2 : 1) * (1 + faction.favor / 100)
baseRepGain * (Player.hasAugmentation(AugmentationNames.WKSharmonizer, true) ? 2 : 1) * (1 + faction.favor / 100)
);
}

@ -1,7 +1,6 @@
import React, { useState } from "react";
import { Location } from "../../Locations/Location";
import { Router } from "../../ui/GameRoot";
import { Player } from "../../Player";
import { calculateDifficulty, calculateReward } from "../formulas/game";
import { Game } from "./Game";
import { Intro } from "./Intro";
@ -14,8 +13,8 @@ export function InfiltrationRoot(props: IProps): React.ReactElement {
if (props.location.infiltrationData === undefined) throw new Error("Trying to do infiltration on invalid location.");
const startingSecurityLevel = props.location.infiltrationData.startingSecurityLevel;
const difficulty = calculateDifficulty(Player, startingSecurityLevel);
const reward = calculateReward(Player, startingSecurityLevel);
const difficulty = calculateDifficulty(startingSecurityLevel);
const reward = calculateReward(startingSecurityLevel);
function cancel(): void {
Router.toCity();

@ -30,9 +30,9 @@ export function Victory(props: IProps): React.ReactElement {
}
const soa = Factions[FactionNames.ShadowsOfAnarchy];
const repGain = calculateTradeInformationRepReward(Player, props.Reward, props.MaxLevel, props.StartingDifficulty);
const moneyGain = calculateSellInformationCashReward(Player, props.Reward, props.MaxLevel, props.StartingDifficulty);
const infiltrationRepGain = calculateInfiltratorsRepReward(Player, soa, props.StartingDifficulty);
const repGain = calculateTradeInformationRepReward(props.Reward, props.MaxLevel, props.StartingDifficulty);
const moneyGain = calculateSellInformationCashReward(props.Reward, props.MaxLevel, props.StartingDifficulty);
const infiltrationRepGain = calculateInfiltratorsRepReward(soa, props.StartingDifficulty);
const isMemberOfInfiltrators = Player.factions.includes(FactionNames.ShadowsOfAnarchy);

@ -1,6 +1,4 @@
import { IPlayer } from "../PersonObjects/IPlayer";
export type Milestone = {
title: string;
fulfilled: (p: IPlayer) => boolean;
fulfilled: () => boolean;
};

@ -1,16 +1,16 @@
import { Milestone } from "./Milestone";
import { IPlayer } from "../PersonObjects/IPlayer";
import { Player } from "../Player";
import { Factions } from "../Faction/Factions";
import { Faction } from "../Faction/Faction";
import { GetServer } from "../Server/AllServers";
import { FactionNames } from "../Faction/data/FactionNames";
import { Server } from "../Server/Server";
function allFactionAugs(p: IPlayer, f: Faction): boolean {
function allFactionAugs(f: Faction): boolean {
const factionAugs = f.augmentations.slice().filter((aug) => aug !== "NeuroFlux Governor");
for (const factionAug of factionAugs) {
if (
!p.augmentations.some((aug) => {
!Player.augmentations.some((aug) => {
return aug.name == factionAug;
})
)
@ -38,63 +38,63 @@ export const Milestones: Milestone[] = [
},
{
title: "Join the faction hinted at in csec-test.msg",
fulfilled: (p: IPlayer): boolean => {
return p.factions.includes(FactionNames.CyberSec);
fulfilled: (): boolean => {
return Player.factions.includes(FactionNames.CyberSec);
},
},
{
title: `Install all the Augmentations from ${FactionNames.CyberSec}`,
fulfilled: (p: IPlayer): boolean => {
return allFactionAugs(p, Factions[FactionNames.CyberSec]);
fulfilled: (): boolean => {
return allFactionAugs(Factions[FactionNames.CyberSec]);
},
},
{
title: "Join the faction hinted at in nitesec-test.msg",
fulfilled: (p: IPlayer): boolean => {
return p.factions.includes(FactionNames.NiteSec);
fulfilled: (): boolean => {
return Player.factions.includes(FactionNames.NiteSec);
},
},
{
title: `Install all the Augmentations from ${FactionNames.NiteSec}`,
fulfilled: (p: IPlayer): boolean => {
return allFactionAugs(p, Factions[FactionNames.NiteSec]);
fulfilled: (): boolean => {
return allFactionAugs(Factions[FactionNames.NiteSec]);
},
},
{
title: "Join the faction hinted at in j3.msg",
fulfilled: (p: IPlayer): boolean => {
return p.factions.includes(FactionNames.TheBlackHand);
fulfilled: (): boolean => {
return Player.factions.includes(FactionNames.TheBlackHand);
},
},
{
title: `Install all the Augmentations from ${FactionNames.TheBlackHand}`,
fulfilled: (p: IPlayer): boolean => {
return allFactionAugs(p, Factions[FactionNames.TheBlackHand]);
fulfilled: (): boolean => {
return allFactionAugs(Factions[FactionNames.TheBlackHand]);
},
},
{
title: "Join the faction hinted at in 19dfj3l1nd.msg",
fulfilled: (p: IPlayer): boolean => {
return p.factions.includes(FactionNames.BitRunners);
fulfilled: (): boolean => {
return Player.factions.includes(FactionNames.BitRunners);
},
},
{
title: `Install all the Augmentations from ${FactionNames.BitRunners}`,
fulfilled: (p: IPlayer): boolean => {
return allFactionAugs(p, Factions[FactionNames.BitRunners]);
fulfilled: (): boolean => {
return allFactionAugs(Factions[FactionNames.BitRunners]);
},
},
{
title: "Complete fl1ght.exe",
fulfilled: (p: IPlayer): boolean => {
fulfilled: (): boolean => {
// technically wrong but whatever
return p.factions.includes(FactionNames.Daedalus);
return Player.factions.includes(FactionNames.Daedalus);
},
},
{
title: `Install the special Augmentation from ${FactionNames.Daedalus}`,
fulfilled: (p: IPlayer): boolean => {
return p.augmentations.some((aug) => aug.name == "The Red Pill");
fulfilled: (): boolean => {
return Player.augmentations.some((aug) => aug.name == "The Red Pill");
},
},
{

@ -1,4 +1,3 @@
import { Player } from "../../Player";
import { Milestones } from "../Milestones";
import { Milestone } from "../Milestone";
import * as React from "react";
@ -9,7 +8,7 @@ import Box from "@mui/material/Box";
function highestMilestone(milestones: Milestone[]): number {
let n = -1;
for (let i = 0; i < milestones.length; i++) {
if (milestones[i].fulfilled(Player)) n = i;
if (milestones[i].fulfilled()) n = i;
}
return n;
@ -21,7 +20,7 @@ export function MilestonesRoot(): JSX.Element {
if (i <= n + 1) {
return (
<Typography key={i}>
[{milestone.fulfilled(Player) ? "x" : " "}] {milestone.title}
[{milestone.fulfilled() ? "x" : " "}] {milestone.title}
</Typography>
);
}

@ -21,7 +21,7 @@ import { CONSTANTS } from "../Constants";
import { influenceStockThroughServerHack } from "../StockMarket/PlayerInfluencing";
import { IPort, NetscriptPort } from "../NetscriptPort";
import { NetscriptPorts } from "../NetscriptWorker";
import { IPlayer } from "../PersonObjects/IPlayer";
import { IPerson } from "../PersonObjects/IPerson";
import { FormulaGang } from "../Gang/formulas/formulas";
import { GangMember } from "../Gang/GangMember";
import { GangMemberTask } from "../Gang/GangMemberTask";
@ -498,7 +498,7 @@ function getValidPort(ctx: NetscriptContext, port: number): IPort {
return iport;
}
function player(ctx: NetscriptContext, p: unknown): IPlayer {
function player(ctx: NetscriptContext, p: unknown): IPerson {
const fakePlayer = {
hp: undefined,
mults: undefined,
@ -518,7 +518,7 @@ function player(ctx: NetscriptContext, p: unknown): IPlayer {
entropy: undefined,
};
if (!roughlyIs(fakePlayer, p)) throw makeRuntimeErrorMsg(ctx, `player should be a Player.`, "TYPE");
return p as IPlayer;
return p as IPerson;
}
function server(ctx: NetscriptContext, s: unknown): Server {

@ -266,7 +266,7 @@ const base: InternalAPI<NS> = {
);
return helpers.netscriptDelay(ctx, growTime * 1000).then(function () {
const moneyBefore = server.moneyAvailable <= 0 ? 1 : server.moneyAvailable;
processSingleServerGrowth(server, threads, Player, host.cpuCores);
processSingleServerGrowth(server, threads, host.cpuCores);
const moneyAfter = server.moneyAvailable;
ctx.workerScript.scriptRef.recordGrow(server.hostname, threads);
const expGain = calculateHackingExpGain(server, Player) * threads;
@ -304,7 +304,7 @@ const base: InternalAPI<NS> = {
throw helpers.makeRuntimeErrorMsg(ctx, `Invalid argument: growth must be numeric and >= 1, is ${growth}.`);
}
return numCycleForGrowth(server, Number(growth), Player, cores);
return numCycleForGrowth(server, Number(growth), cores);
},
growthAnalyzeSecurity:
(ctx: NetscriptContext) =>
@ -321,7 +321,7 @@ const base: InternalAPI<NS> = {
}
const maxThreadsNeeded = Math.ceil(
numCycleForGrowthCorrected(server, server.moneyMax, server.moneyAvailable, Player, cores),
numCycleForGrowthCorrected(server, server.moneyMax, server.moneyAvailable, cores),
);
threads = Math.min(threads, maxThreadsNeeded);

@ -1,5 +1,3 @@
import { Player as player } from "../Player";
import {
Infiltration as IInfiltration,
InfiltrationLocation,
@ -32,15 +30,15 @@ export function NetscriptInfiltration(): InternalAPI<IInfiltration> {
if (location.infiltrationData === undefined)
throw helpers.makeRuntimeErrorMsg(ctx, `Location '${location}' does not provide infiltrations.`);
const startingSecurityLevel = location.infiltrationData.startingSecurityLevel;
const difficulty = calculateDifficulty(player, startingSecurityLevel);
const reward = calculateReward(player, startingSecurityLevel);
const difficulty = calculateDifficulty(startingSecurityLevel);
const reward = calculateReward(startingSecurityLevel);
const maxLevel = location.infiltrationData.maxClearanceLevel;
return {
location: JSON.parse(JSON.stringify(location)),
reward: {
tradeRep: calculateTradeInformationRepReward(player, reward, maxLevel, startingSecurityLevel),
sellCash: calculateSellInformationCashReward(player, reward, maxLevel, startingSecurityLevel),
SoARep: calculateInfiltratorsRepReward(player, Factions[FactionNames.ShadowsOfAnarchy], startingSecurityLevel),
tradeRep: calculateTradeInformationRepReward(reward, maxLevel, startingSecurityLevel),
sellCash: calculateSellInformationCashReward(reward, maxLevel, startingSecurityLevel),
SoARep: calculateInfiltratorsRepReward(Factions[FactionNames.ShadowsOfAnarchy], startingSecurityLevel),
},
difficulty: difficulty,
};

@ -53,7 +53,7 @@ export function NetscriptStanek(): InternalAPI<IStanek> {
//Charge the fragment
const time = staneksGift.inBonus() ? 200 : 1000;
return helpers.netscriptDelay(ctx, time).then(function () {
staneksGift.charge(player, fragment, ctx.workerScript.scriptRef.threads);
staneksGift.charge(fragment, ctx.workerScript.scriptRef.threads);
helpers.log(ctx, () => `Charged fragment with ${ctx.workerScript.scriptRef.threads} threads.`);
return Promise.resolve();
});

@ -52,7 +52,7 @@ export function prestigeAugmentation(): void {
// Reset home computer (only the programs) and add to AllServers
AddToAllServers(homeComp);
prestigeHomeComputer(Player, homeComp);
prestigeHomeComputer(homeComp);
if (augmentationExists(AugmentationNames.Neurolink) && Player.hasAugmentation(AugmentationNames.Neurolink, true)) {
homeComp.programs.push(Programs.FTPCrackProgram.name);
@ -194,7 +194,7 @@ export function prestigeSourceFile(flume: boolean): void {
// Reset home computer (only the programs) and add to AllServers
AddToAllServers(homeComp);
prestigeHomeComputer(Player, homeComp);
prestigeHomeComputer(homeComp);
// Re-create foreign servers
initForeignServers(Player.getHomeComputer());

@ -43,7 +43,7 @@ export function scriptCalculateOfflineProduction(runningScript: RunningScript):
const host = GetServer(runningScript.server);
if (host === null) throw new Error("getServer of null key?");
if (!(serv instanceof Server)) throw new Error("trying to grow a non-normal server");
const growth = processSingleServerGrowth(serv, timesGrown, Player, host.cpuCores);
const growth = processSingleServerGrowth(serv, timesGrown, host.cpuCores);
runningScript.log(
`'${serv.hostname}' grown by ${numeralWrapper.format(growth * 100 - 100, "0.000000%")} while offline`,
);

@ -5,7 +5,7 @@ import { calculateServerGrowth } from "./formulas/grow";
import { BitNodeMultipliers } from "../BitNode/BitNodeMultipliers";
import { CONSTANTS } from "../Constants";
import { IPlayer } from "../PersonObjects/IPlayer";
import { Player } from "../Player";
import { Programs } from "../Programs/Programs";
import { LiteratureNames } from "../Literature/data/LiteratureNames";
@ -48,7 +48,7 @@ export function safetlyCreateUniqueServer(params: IConstructorParams): Server {
* @param p - Reference to Player object
* @returns Number of "growth cycles" needed
*/
export function numCycleForGrowth(server: Server, growth: number, p: IPlayer, cores = 1): number {
export function numCycleForGrowth(server: Server, growth: number, cores = 1): number {
let ajdGrowthRate = 1 + (CONSTANTS.ServerBaseGrowthRate - 1) / server.hackDifficulty;
if (ajdGrowthRate > CONSTANTS.ServerMaxGrowthRate) {
ajdGrowthRate = CONSTANTS.ServerMaxGrowthRate;
@ -60,7 +60,7 @@ export function numCycleForGrowth(server: Server, growth: number, p: IPlayer, co
const cycles =
Math.log(growth) /
(Math.log(ajdGrowthRate) *
p.mults.hacking_grow *
Player.mults.hacking_grow *
serverGrowthPercentage *
BitNodeMultipliers.ServerGrowthRate *
coreBonus);
@ -68,33 +68,6 @@ export function numCycleForGrowth(server: Server, growth: number, p: IPlayer, co
return cycles;
}
/**
* Replacement function for the above function that accounts for the +$1/thread functionality of grow
* with parameters that are the same (for compatibility), but functionality is slightly different.
* This function can ONLY be used to calculate the threads needed for a given server in its current state,
* and so wouldn't be appropriate to use for formulas.exe or ns.growthAnalyze (as those are meant to
* provide theoretical scenarios, or inverse hack respectively). Players COULD use this function with a
* custom server object with the correct moneyAvailable and moneyMax amounts, combined with a multiplier
* correctly calculated to bring the server to a new moneyAvailable (ie, passing in moneyAvailable 300 and x2
* when you want the number of threads required to grow that particular server from 300 to 600), and this
* function would pass back the correct number of threads. But the key thing is that it doesn't just
* inverse/undo a hack (since the amount hacked from/to matters, not just the multiplier).
* The above is also a rather unnecessarily obtuse way of thinking about it for a formulas.exe type of
* application, so another function with different parameters is provided for that case below this one.
* Instead this function is meant to hand-off from the old numCycleForGrowth function to the new one
* where used internally for pro-rating or the like. Where you have applied a grow and want to determine
* how many threads were needed for THAT SPECIFIC grow case using a multiplier.
* Ideally, this function, and the original function above will be depreciated to use the methodology
* and inputs of the new function below this one. Even for internal cases (it's actually easier to do so).
* @param server - Server being grown
* @param growth - How much the server money is expected to be multiplied by (e.g. 1.5 for *1.5 / +50%)
* @param p - Reference to Player object
* @returns Number of "growth cycles" needed
*/
export function numCycleForGrowthTransition(server: Server, growth: number, p: IPlayer, cores = 1): number {
return numCycleForGrowthCorrected(server, server.moneyAvailable * growth, server.moneyAvailable, p, cores);
}
/**
* This function calculates the number of threads needed to grow a server from one $amount to a higher $amount
* (ie, how many threads to grow this server from $200 to $600 for example). Used primarily for a formulas (or possibly growthAnalyze)
@ -104,16 +77,10 @@ export function numCycleForGrowthTransition(server: Server, growth: number, p: I
* @param server - Server being grown
* @param targetMoney - How much you want the server grown TO (not by), for instance, to grow from 200 to 600, input 600
* @param startMoney - How much you are growing the server from, for instance, to grow from 200 to 600, input 200
* @param p - Reference to Player object
* @param cores - Number of cores on the host performing grow
* @returns Number of "growth cycles" needed
*/
export function numCycleForGrowthCorrected(
server: Server,
targetMoney: number,
startMoney: number,
p: IPlayer,
cores = 1,
): number {
export function numCycleForGrowthCorrected(server: Server, targetMoney: number, startMoney: number, cores = 1): number {
if (startMoney < 0) {
startMoney = 0;
} // servers "can't" have less than 0 dollars on them
@ -132,7 +99,7 @@ export function numCycleForGrowthCorrected(
const serverGrowthPercentage = server.serverGrowth / 100.0;
const coreMultiplier = 1 + (cores - 1) / 16;
const threadMultiplier =
serverGrowthPercentage * p.mults.hacking_grow * coreMultiplier * BitNodeMultipliers.ServerGrowthRate;
serverGrowthPercentage * Player.mults.hacking_grow * coreMultiplier * BitNodeMultipliers.ServerGrowthRate;
/* To understand what is done below we need to do some math. I hope the explanation is clear enough.
* First of, the names will be shortened for ease of manipulation:
@ -241,47 +208,9 @@ export function numCycleForGrowthCorrected(
return cca + 1;
}
/**
* This function calculates the number of threads needed to grow a server based on a pre-hack money and hackAmt
* (ie, if you're hacking a server with $1e6 moneyAvail for 60%, this function will tell you how many threads to regrow it
* A good replacement for the current ns.growthAnalyze if you want players to have more control/responsibility
* @param server - Server being grown
* @param hackProp - the proportion of money hacked (total, not per thread, like 0.60 for hacking 60% of available money)
* @param prehackMoney - how much money the server had before being hacked (like 200000 for hacking a server that had $200000 on it at time of hacking)
* @param p - Reference to Player object
* @returns Number of "growth cycles" needed to reverse the described hack
*/
export function numCycleForGrowthByHackAmt(
server: Server,
hackProp: number,
prehackMoney: number,
p: IPlayer,
cores = 1,
): number {
if (prehackMoney > server.moneyMax) prehackMoney = server.moneyMax;
const posthackMoney = Math.floor(prehackMoney * Math.min(1, Math.max(0, 1 - hackProp)));
return numCycleForGrowthCorrected(server, prehackMoney, posthackMoney, p, cores);
}
/**
* This function calculates the number of threads needed to grow a server based on an expected growth multiplier assuming it will max out
* (ie, if you expect to grow a server by 60% to reach maxMoney, this function will tell you how many threads to grow it)
* PROBABLY the best replacement for the current ns.growthAnalyze to maintain existing scripts
* @param server - Server being grown
* @param growth - How much the server is being grown by, as a multiple in DECIMAL form (e.g. 1.5 rather than 50). Infinity is acceptable.
* @param p - Reference to Player object
* @returns Number of "growth cycles" needed
*/
export function numCycleForGrowthByMultiplier(server: Server, growth: number, p: IPlayer, cores = 1): number {
if (growth < 1.0) growth = 1.0;
const targetMoney = server.moneyMax;
const startingMoney = server.moneyMax / growth;
return numCycleForGrowthCorrected(server, targetMoney, startingMoney, p, cores);
}
//Applied server growth for a single server. Returns the percentage growth
export function processSingleServerGrowth(server: Server, threads: number, p: IPlayer, cores = 1): number {
let serverGrowth = calculateServerGrowth(server, threads, p, cores);
export function processSingleServerGrowth(server: Server, threads: number, cores = 1): number {
let serverGrowth = calculateServerGrowth(server, threads, Player, cores);
if (serverGrowth < 1) {
console.warn("serverGrowth calculated to be less than 1");
serverGrowth = 1;
@ -303,7 +232,7 @@ export function processSingleServerGrowth(server: Server, threads: number, p: IP
// if there was any growth at all, increase security
if (oldMoneyAvailable !== server.moneyAvailable) {
let usedCycles = numCycleForGrowthCorrected(server, server.moneyAvailable, oldMoneyAvailable, p, cores);
let usedCycles = numCycleForGrowthCorrected(server, server.moneyAvailable, oldMoneyAvailable, cores);
// Growing increases server security twice as much as hacking
usedCycles = Math.min(Math.max(0, Math.ceil(usedCycles)), threads);
server.fortify(2 * CONSTANTS.ServerFortifyAmount * usedCycles);
@ -311,7 +240,7 @@ export function processSingleServerGrowth(server: Server, threads: number, p: IP
return server.moneyAvailable / oldMoneyAvailable;
}
export function prestigeHomeComputer(player: IPlayer, homeComp: Server): void {
export function prestigeHomeComputer(homeComp: Server): void {
const hasBitflume = homeComp.programs.includes(Programs.BitFlume.name);
homeComp.programs.length = 0; //Remove programs

@ -1,9 +1,9 @@
import { CONSTANTS } from "../../Constants";
import { Server } from "../Server";
import { BitNodeMultipliers } from "../../BitNode/BitNodeMultipliers";
import { IPlayer } from "../../PersonObjects/IPlayer";
import { IPerson } from "../../PersonObjects/IPerson";
export function calculateServerGrowth(server: Server, threads: number, p: IPlayer, cores = 1): number {
export function calculateServerGrowth(server: Server, threads: number, p: IPerson, cores = 1): number {
const numServerGrowthCycles = Math.max(Math.floor(threads), 0);
//Get adjusted growth rate, which accounts for server security

@ -250,7 +250,7 @@ export class Terminal implements ITerminal {
if (!(server instanceof Server)) throw new Error("server should be normal server");
const expGain = calculateHackingExpGain(server, Player);
const oldSec = server.hackDifficulty;
const growth = processSingleServerGrowth(server, 25, Player, server.cpuCores) - 1;
const growth = processSingleServerGrowth(server, 25, server.cpuCores) - 1;
const newSec = server.hackDifficulty;
Player.gainHackingExp(expGain);

@ -3,7 +3,7 @@ import { getSubdirectories } from "./DirectoryServerHelpers";
import { Aliases, GlobalAliases, substituteAliases } from "../Alias";
import { DarkWebItems } from "../DarkWeb/DarkWebItems";
import { IPlayer } from "../PersonObjects/IPlayer";
import { Player } from "../Player";
import { GetAllServers } from "../Server/AllServers";
import { Server } from "../Server/Server";
import { ParseCommand, ParseCommands } from "./Parser";
@ -57,7 +57,6 @@ const commands = [
];
export async function determineAllPossibilitiesForTabCompletion(
p: IPlayer,
input: string,
index: number,
currPath = "",
@ -65,8 +64,8 @@ export async function determineAllPossibilitiesForTabCompletion(
input = substituteAliases(input);
let allPos: string[] = [];
allPos = allPos.concat(Object.keys(GlobalAliases));
const currServ = p.getCurrentServer();
const homeComputer = p.getHomeComputer();
const currServ = Player.getCurrentServer();
const homeComputer = Player.getHomeComputer();
let parentDirPath = "";
let evaledParentDirPath: string | null = null;

@ -222,7 +222,7 @@ export function TerminalInput(): React.ReactElement {
if (index < -1) {
index = 0;
}
const allPos = await determineAllPossibilitiesForTabCompletion(Player, copy, index, Terminal.cwd());
const allPos = await determineAllPossibilitiesForTabCompletion(copy, index, Terminal.cwd());
if (allPos.length == 0) {
return;
}

@ -103,11 +103,11 @@ const Engine: {
// Gang, if applicable
if (Player.inGang() && Player.gang !== null) {
Player.gang.process(numCycles, Player);
Player.gang.process(numCycles);
}
// Staneks gift
staneksGift.process(Player, numCycles);
staneksGift.process(numCycles);
// Corporation
if (Player.corporation instanceof Corporation) {
@ -330,7 +330,7 @@ const Engine: {
// Gang progress for BitNode 2
const gang = Player.gang;
if (Player.inGang() && gang !== null) {
gang.process(numCyclesOffline, Player);
gang.process(numCyclesOffline);
}
// Corporation offline progress
@ -343,7 +343,7 @@ const Engine: {
Player.bladeburner.storeCycles(numCyclesOffline);
}
staneksGift.process(Player, numCyclesOffline);
staneksGift.process(numCyclesOffline);
// Sleeves offline progress
for (let i = 0; i < Player.sleeves.length; ++i) {