NETSCRIPT: ns.sleeve.getSleeve added. getPlayer and getSleeve can both be used for formulas. (#200)

* BREAKING CHANGE: Removed getSleeveStats and getSleeveInformation because this info is provided by getSleeve in a more usable form.
* BREAKING CHANGE: Removed tor, inBladeburner, and hasCorporation fields from ns.getPlayer. Functionality still exists via added functions ns.hasTorRouter, ns.corporation.hasCorporation, and ns.bladeburner.inBladeburner.
* Separated ns definitions for Person, Sleeve, and Player interfaces with both Player and Sleeve just extending Person.
Added getSleeve, which provides a Sleeve object similar to getPlayer.
* Renamed the sleeve ns layer's interface as sleeve lowercase because of name conflict. todo: May move all the ns layers interface names to lowercase for consistency
* Added ns.formulas.work.crimeSuccessChance and reworked to allow both sleeve and player calculations.
* Removed internal Person.getIntelligenceBonus function which was just a wrapper for calculateIntelligenceBonus. Any use of the former in formulas creates a conflict where ns-provided Person objects throw an error.
* Renamed helpers.player to helpers.person for netscript person validation. Reduced number of fields validated due to Person being a smaller interface.
* Fixed bug in bladeburner where Player multipliers and int were being used no matter which person was performing the task
* Fixed leak of Player.jobs at ns.getPlayer
* Person / Player / Sleeve classes now implement the netscript equivalent interfaces. Netscript helper for person no longer asserts that it's a real Person class member, only that it's a Person interface. Functions that use netscript persons have been changed to expect just a person interface to prevent needing this incorrect type assertion.
This commit is contained in:
Snarling
2022-11-09 07:26:26 -05:00
committed by GitHub
parent 6f08aee8f6
commit 8e0e0eaa88
31 changed files with 251 additions and 337 deletions
@@ -1,6 +1,7 @@
import { StaticAugmentations } from "../../Augmentation/StaticAugmentations";
import { GraftableAugmentation } from "./GraftableAugmentation";
import { Player } from "@player";
import { calculateIntelligenceBonus } from "../formulas/intelligence";
export const getGraftingAvailableAugs = (): string[] => {
const augs: string[] = [];
@@ -14,7 +15,7 @@ export const getGraftingAvailableAugs = (): string[] => {
};
export const graftingIntBonus = (): number => {
return 1 + (Player.getIntelligenceBonus(3) - 1) / 3;
return 1 + (calculateIntelligenceBonus(Player.skills.intelligence, 3) - 1) / 3;
};
export const calculateGraftingTimeWithBonus = (aug: GraftableAugmentation): number => {
+2 -6
View File
@@ -2,14 +2,14 @@ import * as personMethods from "./PersonMethods";
import { PlayerOwnedAugmentation } from "../Augmentation/PlayerOwnedAugmentation";
import { CityName } from "../Locations/data/CityNames";
import { calculateSkill } from "./formulas/skill";
import { calculateIntelligenceBonus } from "./formulas/intelligence";
import { defaultMultipliers } from "./Multipliers";
import { Skills } from "./Skills";
import { HP } from "./HP";
import { Person as IPerson } from "../ScriptEditor/NetscriptDefinitions";
import { IReviverValue } from "../utils/JSONReviver";
// Base class representing a person-like object
export abstract class Person {
export abstract class Person implements IPerson {
hp: HP = { current: 10, max: 10 };
skills: Skills = {
hacking: 1,
@@ -58,10 +58,6 @@ export abstract class Person {
this.mults = defaultMultipliers();
}
getIntelligenceBonus(weight: number): number {
return calculateIntelligenceBonus(this.skills.intelligence, weight);
}
abstract takeDamage(amt: number): boolean;
abstract whoAmI(): string;
abstract toJSON(): IReviverValue;
+2 -3
View File
@@ -26,8 +26,9 @@ import { getRandomInt } from "../../utils/helpers/getRandomInt";
import { CONSTANTS } from "../../Constants";
import { Work } from "src/Work/Work";
import { Person } from "../Person";
import { Player as IPlayer } from "../../ScriptEditor/NetscriptDefinitions";
export class PlayerObject extends Person {
export class PlayerObject extends Person implements IPlayer {
// Player-specific properties
bitNodeN = 1; //current bitnode
corporation: Corporation | null = null;
@@ -102,11 +103,9 @@ export class PlayerObject extends Person {
getUpgradeHomeRamCost = serverMethods.getUpgradeHomeRamCost;
getUpgradeHomeCoresCost = serverMethods.getUpgradeHomeCoresCost;
gotoLocation = generalMethods.gotoLocation;
hasCorporation = corporationMethods.hasCorporation;
hasGangWith = gangMethods.hasGangWith;
hasTorRouter = serverMethods.hasTorRouter;
hasProgram = generalMethods.hasProgram;
inBladeburner = bladeburnerMethods.inBladeburner;
inGang = gangMethods.inGang;
isAwareOfGang = gangMethods.isAwareOfGang;
isQualified = generalMethods.isQualified;
@@ -5,10 +5,6 @@ export function canAccessBladeburner(this: PlayerObject): boolean {
return this.bitNodeN === 6 || this.bitNodeN === 7 || this.sourceFileLvl(6) > 0 || this.sourceFileLvl(7) > 0;
}
export function inBladeburner(this: PlayerObject): boolean {
return Boolean(this.bladeburner);
}
export function startBladeburner(this: PlayerObject): void {
this.bladeburner = new Bladeburner();
}
@@ -9,10 +9,6 @@ export function canAccessCorporation(this: PlayerObject): boolean {
return this.bitNodeN === 3 || this.sourceFileLvl(3) > 0;
}
export function hasCorporation(this: PlayerObject): boolean {
return Boolean(this.corporation);
}
export function startCorporation(this: PlayerObject, corpName: string, additionalShares = 0): void {
this.corporation = new Corporation({
name: corpName,
@@ -138,9 +138,10 @@ export function prestigeSourceFile(this: PlayerObject): void {
}
}
// Gang
this.gang = null;
resetGangs();
this.corporation = null;
this.bladeburner = null;
// Reset Stock market
this.hasWseAccount = false;
+2 -1
View File
@@ -40,8 +40,9 @@ import { SleeveSupportWork } from "./Work/SleeveSupportWork";
import { SleeveBladeburnerWork } from "./Work/SleeveBladeburnerWork";
import { SleeveCrimeWork } from "./Work/SleeveCrimeWork";
import * as sleeveMethods from "./SleeveMethods";
import { Sleeve as ISleeve } from "../../ScriptEditor/NetscriptDefinitions";
export class Sleeve extends Person {
export class Sleeve extends Person implements ISleeve {
currentWork: Work | null = null;
/** Clone retains 'memory' synchronization (and maybe exp?) upon prestige/installing Augs */
@@ -2,6 +2,7 @@ import { Player } from "@player";
import { Generic_fromJSON, Generic_toJSON, IReviverValue, Reviver } from "../../../utils/JSONReviver";
import { Sleeve } from "../Sleeve";
import { Work, WorkType } from "./Work";
import { calculateIntelligenceBonus } from "../../formulas/intelligence";
export const isSleeveSynchroWork = (w: Work | null): w is SleeveSynchroWork =>
w !== null && w.type === WorkType.SYNCHRO;
@@ -12,7 +13,10 @@ export class SleeveSynchroWork extends Work {
}
process(sleeve: Sleeve, cycles: number): number {
sleeve.sync = Math.min(100, sleeve.sync + Player.getIntelligenceBonus(0.5) * 0.0002 * cycles);
sleeve.sync = Math.min(
100,
sleeve.sync + calculateIntelligenceBonus(Player.skills.intelligence, 0.5) * 0.0002 * cycles,
);
if (sleeve.sync >= 100) sleeve.stopWork();
return 0;
}
+32 -29
View File
@@ -2,6 +2,8 @@ import React from "react";
import { Typography, Table, TableBody, TableCell, TableRow } from "@mui/material";
import { CONSTANTS } from "../../../Constants";
import { numeralWrapper } from "../../../ui/numeralFormat";
import { Settings } from "../../../Settings/Settings";
import { StatsRow } from "../../../ui/React/StatsRow";
@@ -15,7 +17,8 @@ import { isSleeveClassWork } from "../Work/SleeveClassWork";
import { isSleeveFactionWork } from "../Work/SleeveFactionWork";
import { isSleeveCompanyWork } from "../Work/SleeveCompanyWork";
import { isSleeveCrimeWork } from "../Work/SleeveCrimeWork";
import { BitNodeMultipliers } from "../../../BitNode/BitNodeMultipliers";
const CYCLES_PER_SEC = 1000 / CONSTANTS.MilliPerCycle;
interface IProps {
sleeve: Sleeve;
@@ -99,37 +102,37 @@ export function EarningsElement(props: IProps): React.ReactElement {
if (isSleeveCrimeWork(props.sleeve.currentWork)) {
const gains = props.sleeve.currentWork.getExp(props.sleeve);
data = [
[`Money:`, <Money money={5 * gains.money} />],
[`Hacking Exp:`, `${numeralWrapper.formatExp(5 * gains.hackExp)}`],
[`Strength Exp:`, `${numeralWrapper.formatExp(5 * gains.strExp)}`],
[`Defense Exp:`, `${numeralWrapper.formatExp(5 * gains.defExp)}`],
[`Dexterity Exp:`, `${numeralWrapper.formatExp(5 * gains.dexExp)}`],
[`Agility Exp:`, `${numeralWrapper.formatExp(5 * gains.agiExp)}`],
[`Charisma Exp:`, `${numeralWrapper.formatExp(5 * gains.chaExp)}`],
[`Money:`, <Money money={gains.money} />],
[`Hacking Exp:`, `${numeralWrapper.formatExp(gains.hackExp)}`],
[`Strength Exp:`, `${numeralWrapper.formatExp(gains.strExp)}`],
[`Defense Exp:`, `${numeralWrapper.formatExp(gains.defExp)}`],
[`Dexterity Exp:`, `${numeralWrapper.formatExp(gains.dexExp)}`],
[`Agility Exp:`, `${numeralWrapper.formatExp(gains.agiExp)}`],
[`Charisma Exp:`, `${numeralWrapper.formatExp(gains.chaExp)}`],
];
}
if (isSleeveClassWork(props.sleeve.currentWork)) {
const rates = props.sleeve.currentWork.calculateRates(props.sleeve);
data = [
[`Money:`, <MoneyRate money={5 * rates.money} />],
[`Hacking Exp:`, `${numeralWrapper.formatExp(5 * rates.hackExp)} / sec`],
[`Strength Exp:`, `${numeralWrapper.formatExp(5 * rates.strExp)} / sec`],
[`Defense Exp:`, `${numeralWrapper.formatExp(5 * rates.defExp)} / sec`],
[`Dexterity Exp:`, `${numeralWrapper.formatExp(5 * rates.dexExp)} / sec`],
[`Agility Exp:`, `${numeralWrapper.formatExp(5 * rates.agiExp)} / sec`],
[`Charisma Exp:`, `${numeralWrapper.formatExp(5 * rates.chaExp)} / sec`],
[`Money:`, <MoneyRate money={CYCLES_PER_SEC * rates.money} />],
[`Hacking Exp:`, `${numeralWrapper.formatExp(CYCLES_PER_SEC * rates.hackExp)} / sec`],
[`Strength Exp:`, `${numeralWrapper.formatExp(CYCLES_PER_SEC * rates.strExp)} / sec`],
[`Defense Exp:`, `${numeralWrapper.formatExp(CYCLES_PER_SEC * rates.defExp)} / sec`],
[`Dexterity Exp:`, `${numeralWrapper.formatExp(CYCLES_PER_SEC * rates.dexExp)} / sec`],
[`Agility Exp:`, `${numeralWrapper.formatExp(CYCLES_PER_SEC * rates.agiExp)} / sec`],
[`Charisma Exp:`, `${numeralWrapper.formatExp(CYCLES_PER_SEC * rates.chaExp)} / sec`],
];
}
if (isSleeveFactionWork(props.sleeve.currentWork)) {
const rates = props.sleeve.currentWork.getExpRates(props.sleeve);
const repGain = props.sleeve.currentWork.getReputationRate(props.sleeve);
data = [
[`Hacking Exp:`, `${numeralWrapper.formatExp(5 * rates.hackExp)} / sec`],
[`Strength Exp:`, `${numeralWrapper.formatExp(5 * rates.strExp)} / sec`],
[`Defense Exp:`, `${numeralWrapper.formatExp(5 * rates.defExp)} / sec`],
[`Dexterity Exp:`, `${numeralWrapper.formatExp(5 * rates.dexExp)} / sec`],
[`Agility Exp:`, `${numeralWrapper.formatExp(5 * rates.agiExp)} / sec`],
[`Charisma Exp:`, `${numeralWrapper.formatExp(5 * rates.chaExp)} / sec`],
[`Hacking Exp:`, `${numeralWrapper.formatExp(CYCLES_PER_SEC * rates.hackExp)} / sec`],
[`Strength Exp:`, `${numeralWrapper.formatExp(CYCLES_PER_SEC * rates.strExp)} / sec`],
[`Defense Exp:`, `${numeralWrapper.formatExp(CYCLES_PER_SEC * rates.defExp)} / sec`],
[`Dexterity Exp:`, `${numeralWrapper.formatExp(CYCLES_PER_SEC * rates.dexExp)} / sec`],
[`Agility Exp:`, `${numeralWrapper.formatExp(CYCLES_PER_SEC * rates.agiExp)} / sec`],
[`Charisma Exp:`, `${numeralWrapper.formatExp(CYCLES_PER_SEC * rates.chaExp)} / sec`],
[`Reputation:`, <ReputationRate reputation={repGain} />],
];
}
@@ -137,14 +140,14 @@ export function EarningsElement(props: IProps): React.ReactElement {
if (isSleeveCompanyWork(props.sleeve.currentWork)) {
const rates = props.sleeve.currentWork.getGainRates(props.sleeve);
data = [
[`Money:`, <MoneyRate money={5 * rates.money * BitNodeMultipliers.CompanyWorkMoney} />],
[`Hacking Exp:`, `${numeralWrapper.formatExp(5 * rates.hackExp)} / sec`],
[`Strength Exp:`, `${numeralWrapper.formatExp(5 * rates.strExp)} / sec`],
[`Defense Exp:`, `${numeralWrapper.formatExp(5 * rates.defExp)} / sec`],
[`Dexterity Exp:`, `${numeralWrapper.formatExp(5 * rates.dexExp)} / sec`],
[`Agility Exp:`, `${numeralWrapper.formatExp(5 * rates.agiExp)} / sec`],
[`Charisma Exp:`, `${numeralWrapper.formatExp(5 * rates.chaExp)} / sec`],
[`Reputation:`, <ReputationRate reputation={5 * rates.reputation} />],
[`Money:`, <MoneyRate money={CYCLES_PER_SEC * rates.money} />],
[`Hacking Exp:`, `${numeralWrapper.formatExp(CYCLES_PER_SEC * rates.hackExp)} / sec`],
[`Strength Exp:`, `${numeralWrapper.formatExp(CYCLES_PER_SEC * rates.strExp)} / sec`],
[`Defense Exp:`, `${numeralWrapper.formatExp(CYCLES_PER_SEC * rates.defExp)} / sec`],
[`Dexterity Exp:`, `${numeralWrapper.formatExp(CYCLES_PER_SEC * rates.dexExp)} / sec`],
[`Agility Exp:`, `${numeralWrapper.formatExp(CYCLES_PER_SEC * rates.agiExp)} / sec`],
[`Charisma Exp:`, `${numeralWrapper.formatExp(CYCLES_PER_SEC * rates.chaExp)} / sec`],
[`Reputation:`, <ReputationRate reputation={CYCLES_PER_SEC * rates.reputation} />],
];
}
+1 -1
View File
@@ -246,7 +246,7 @@ const canDo: {
"Take University Course": (sleeve: Sleeve) =>
[CityName.Aevum, CityName.Sector12, CityName.Volhaven].includes(sleeve.city),
"Workout at Gym": (sleeve: Sleeve) => [CityName.Aevum, CityName.Sector12, CityName.Volhaven].includes(sleeve.city),
"Perform Bladeburner Actions": () => Player.inBladeburner(),
"Perform Bladeburner Actions": () => !!Player.bladeburner,
"Shock Recovery": (sleeve: Sleeve) => sleeve.shock < 100,
Synchronize: (sleeve: Sleeve) => sleeve.sync < 100,
};
+4 -4
View File
@@ -1,7 +1,7 @@
import { CONSTANTS } from "../../Constants";
import { BitNodeMultipliers } from "../../BitNode/BitNodeMultipliers";
import { CalculateShareMult } from "../../NetworkShare/Share";
import { Person } from "../Person";
import { Person as IPerson } from "../../ScriptEditor/NetscriptDefinitions";
import { calculateIntelligenceBonus } from "./intelligence";
function mult(favor: number): number {
@@ -12,7 +12,7 @@ function mult(favor: number): number {
return favorMult * BitNodeMultipliers.FactionWorkRepGain;
}
export function getHackingWorkRepGain(p: Person, favor: number): number {
export function getHackingWorkRepGain(p: IPerson, favor: number): number {
return (
((p.skills.hacking + p.skills.intelligence / 3) / CONSTANTS.MaxSkillLevel) *
p.mults.faction_rep *
@@ -22,7 +22,7 @@ export function getHackingWorkRepGain(p: Person, favor: number): number {
);
}
export function getFactionSecurityWorkRepGain(p: Person, favor: number): number {
export function getFactionSecurityWorkRepGain(p: IPerson, favor: number): number {
const t =
(0.9 *
(p.skills.strength +
@@ -35,7 +35,7 @@ export function getFactionSecurityWorkRepGain(p: Person, favor: number): number
return t * p.mults.faction_rep * mult(favor) * calculateIntelligenceBonus(p.skills.intelligence, 1);
}
export function getFactionFieldWorkRepGain(p: Person, favor: number): number {
export function getFactionFieldWorkRepGain(p: IPerson, favor: number): number {
const t =
(0.9 *
(p.skills.strength +