mirror of
https://github.com/bitburner-official/bitburner-src.git
synced 2024-11-18 21:53:50 +01:00
NETSCRIPT: Add ns.formulas.work.companyGains function (#195)
* added ns.formulas.work.companyGains. * Removed Work/Formulas folder, added Work/Formulas.ts * CompanyPosition.calculateJobPerformance now takes in a Person instead of taking in a full set of stats, and it takes INT into account. * formulas.crimeGains takes in a person object. * Renamed ns Player type to Person. * added multWorkStats, which multiplies a WorkStats object with a multipliers object. * Remove unused types in NetscriptDefinitons.d.ts * reuse formulas code in other parts of game * getSleeveInformation also returns skills Co-authored-by: Alexey <alexey.kozhemiakin@gmail.com>
This commit is contained in:
parent
5205ff2837
commit
9e869bc876
@ -1,3 +1,4 @@
|
|||||||
|
import { Person } from "../PersonObjects/Person";
|
||||||
import { CONSTANTS } from "../Constants";
|
import { CONSTANTS } from "../Constants";
|
||||||
import * as names from "./data/companypositionnames";
|
import * as names from "./data/companypositionnames";
|
||||||
|
|
||||||
@ -117,13 +118,13 @@ export class CompanyPosition {
|
|||||||
this.charismaExpGain = p.charismaExpGain != null ? p.charismaExpGain : 0;
|
this.charismaExpGain = p.charismaExpGain != null ? p.charismaExpGain : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
calculateJobPerformance(hack: number, str: number, def: number, dex: number, agi: number, cha: number): number {
|
calculateJobPerformance(worker: Person): number {
|
||||||
const hackRatio: number = (this.hackingEffectiveness * hack) / CONSTANTS.MaxSkillLevel;
|
const hackRatio: number = (this.hackingEffectiveness * worker.skills.hacking) / CONSTANTS.MaxSkillLevel;
|
||||||
const strRatio: number = (this.strengthEffectiveness * str) / CONSTANTS.MaxSkillLevel;
|
const strRatio: number = (this.strengthEffectiveness * worker.skills.strength) / CONSTANTS.MaxSkillLevel;
|
||||||
const defRatio: number = (this.defenseEffectiveness * def) / CONSTANTS.MaxSkillLevel;
|
const defRatio: number = (this.defenseEffectiveness * worker.skills.defense) / CONSTANTS.MaxSkillLevel;
|
||||||
const dexRatio: number = (this.dexterityEffectiveness * dex) / CONSTANTS.MaxSkillLevel;
|
const dexRatio: number = (this.dexterityEffectiveness * worker.skills.dexterity) / CONSTANTS.MaxSkillLevel;
|
||||||
const agiRatio: number = (this.agilityEffectiveness * agi) / CONSTANTS.MaxSkillLevel;
|
const agiRatio: number = (this.agilityEffectiveness * worker.skills.agility) / CONSTANTS.MaxSkillLevel;
|
||||||
const chaRatio: number = (this.charismaEffectiveness * cha) / CONSTANTS.MaxSkillLevel;
|
const chaRatio: number = (this.charismaEffectiveness * worker.skills.charisma) / CONSTANTS.MaxSkillLevel;
|
||||||
|
|
||||||
let reputationGain: number =
|
let reputationGain: number =
|
||||||
(this.repMultiplier * (hackRatio + strRatio + defRatio + dexRatio + agiRatio + chaRatio)) / 100;
|
(this.repMultiplier * (hackRatio + strRatio + defRatio + dexRatio + agiRatio + chaRatio)) / 100;
|
||||||
@ -131,7 +132,7 @@ export class CompanyPosition {
|
|||||||
console.error("Company reputation gain calculated to be NaN");
|
console.error("Company reputation gain calculated to be NaN");
|
||||||
reputationGain = 0;
|
reputationGain = 0;
|
||||||
}
|
}
|
||||||
|
reputationGain += worker.skills.intelligence / CONSTANTS.MaxSkillLevel;
|
||||||
return reputationGain;
|
return reputationGain;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14,7 +14,7 @@ import { Money } from "../../ui/React/Money";
|
|||||||
import { Router } from "../../ui/GameRoot";
|
import { Router } from "../../ui/GameRoot";
|
||||||
import { Box } from "@mui/material";
|
import { Box } from "@mui/material";
|
||||||
import { ClassWork, ClassType, Classes } from "../../Work/ClassWork";
|
import { ClassWork, ClassType, Classes } from "../../Work/ClassWork";
|
||||||
import { calculateCost } from "../../Work/formulas/Class";
|
import { calculateCost } from "../../Work/Formulas";
|
||||||
|
|
||||||
type IProps = {
|
type IProps = {
|
||||||
loc: Location;
|
loc: Location;
|
||||||
|
@ -15,7 +15,7 @@ import { Player } from "@player";
|
|||||||
import { Box } from "@mui/material";
|
import { Box } from "@mui/material";
|
||||||
|
|
||||||
import { ClassWork, ClassType, Classes } from "../../Work/ClassWork";
|
import { ClassWork, ClassType, Classes } from "../../Work/ClassWork";
|
||||||
import { calculateCost } from "../../Work/formulas/Class";
|
import { calculateCost } from "../../Work/Formulas";
|
||||||
|
|
||||||
type IProps = {
|
type IProps = {
|
||||||
loc: Location;
|
loc: Location;
|
||||||
|
@ -600,6 +600,7 @@ export const RamCosts: RamCostTree<Omit<NSFull, "args" | "enums">> = {
|
|||||||
crimeGains: 0,
|
crimeGains: 0,
|
||||||
classGains: 0,
|
classGains: 0,
|
||||||
factionGains: 0,
|
factionGains: 0,
|
||||||
|
companyGains: 0,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
} as const;
|
} as const;
|
||||||
|
@ -39,17 +39,20 @@ import { favorToRep as calculateFavorToRep, repToFavor as calculateRepToFavor }
|
|||||||
import { repFromDonation } from "../Faction/formulas/donation";
|
import { repFromDonation } from "../Faction/formulas/donation";
|
||||||
import { InternalAPI, NetscriptContext } from "../Netscript/APIWrapper";
|
import { InternalAPI, NetscriptContext } from "../Netscript/APIWrapper";
|
||||||
import { helpers } from "../Netscript/NetscriptHelpers";
|
import { helpers } from "../Netscript/NetscriptHelpers";
|
||||||
import { calculateCrimeWorkStats } from "../Work/formulas/Crime";
|
import { calculateCrimeWorkStats } from "../Work/Formulas";
|
||||||
import { Crimes } from "../Crime/Crimes";
|
import { Crimes } from "../Crime/Crimes";
|
||||||
import { calculateClassEarnings } from "../Work/formulas/Class";
|
import { calculateCompanyWorkStats } from "../Work/Formulas";
|
||||||
|
import { Companies } from "../Company/Companies";
|
||||||
|
import { calculateClassEarnings } from "../Work/Formulas";
|
||||||
import { ClassType } from "../Work/ClassWork";
|
import { ClassType } from "../Work/ClassWork";
|
||||||
import { LocationName } from "../Locations/data/LocationNames";
|
import { LocationName } from "../Locations/data/LocationNames";
|
||||||
import { calculateFactionExp, calculateFactionRep } from "../Work/formulas/Faction";
|
import { calculateFactionExp, calculateFactionRep } from "../Work/Formulas";
|
||||||
import { FactionWorkType } from "../Work/data/FactionWorkType";
|
import { FactionWorkType } from "../Work/data/FactionWorkType";
|
||||||
|
|
||||||
import { defaultMultipliers } from "../PersonObjects/Multipliers";
|
import { defaultMultipliers } from "../PersonObjects/Multipliers";
|
||||||
import { checkEnum } from "../utils/helpers/checkEnum";
|
import { checkEnum } from "../utils/helpers/checkEnum";
|
||||||
import { CrimeType } from "../utils/WorkType";
|
import { CrimeType } from "../utils/WorkType";
|
||||||
|
import { CompanyPositions } from "../Company/CompanyPositions";
|
||||||
|
|
||||||
export function NetscriptFormulas(): InternalAPI<IFormulas> {
|
export function NetscriptFormulas(): InternalAPI<IFormulas> {
|
||||||
const checkFormulasAccess = function (ctx: NetscriptContext): void {
|
const checkFormulasAccess = function (ctx: NetscriptContext): void {
|
||||||
@ -362,10 +365,11 @@ export function NetscriptFormulas(): InternalAPI<IFormulas> {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
work: {
|
work: {
|
||||||
crimeGains: (ctx) => (_crimeType) => {
|
crimeGains: (ctx) => (_person, _crimeType) => {
|
||||||
|
const person = helpers.player(ctx, _person);
|
||||||
const crimeType = helpers.string(ctx, "crimeType", _crimeType);
|
const crimeType = helpers.string(ctx, "crimeType", _crimeType);
|
||||||
if (!checkEnum(CrimeType, crimeType)) throw new Error(`Invalid crime type: ${crimeType}`);
|
if (!checkEnum(CrimeType, crimeType)) throw new Error(`Invalid crime type: ${crimeType}`);
|
||||||
return calculateCrimeWorkStats(Crimes[crimeType]);
|
return calculateCrimeWorkStats(person, Crimes[crimeType]);
|
||||||
},
|
},
|
||||||
classGains: (ctx) => (_person, _classType, _locationName) => {
|
classGains: (ctx) => (_person, _classType, _locationName) => {
|
||||||
const person = helpers.player(ctx, _person);
|
const person = helpers.player(ctx, _person);
|
||||||
@ -382,10 +386,22 @@ export function NetscriptFormulas(): InternalAPI<IFormulas> {
|
|||||||
exp.reputation = rep;
|
exp.reputation = rep;
|
||||||
return exp;
|
return exp;
|
||||||
},
|
},
|
||||||
// companyGains: (ctx) => (_player) {
|
|
||||||
// const player = helpers.player(ctx, _player);
|
|
||||||
|
|
||||||
// },
|
companyGains: (ctx) => (_player, _companyName, _positionName, _favor) => {
|
||||||
|
const player = helpers.player(ctx, _player);
|
||||||
|
CompanyPositions;
|
||||||
|
const positionName = helpers.string(ctx, "_positionName", _positionName);
|
||||||
|
const position = Object.values(CompanyPositions).find((c) => c.name === positionName);
|
||||||
|
if (!position) throw new Error(`Invalid position name: ${positionName}`);
|
||||||
|
|
||||||
|
const companyName = helpers.string(ctx, "_companyName", _companyName);
|
||||||
|
const company = Object.values(Companies).find((c) => c.name === companyName);
|
||||||
|
if (!company) throw new Error(`Invalid company name: ${companyName}`);
|
||||||
|
|
||||||
|
const favor = helpers.number(ctx, "favor", _favor);
|
||||||
|
|
||||||
|
return calculateCompanyWorkStats(player, company, position, favor);
|
||||||
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -49,7 +49,7 @@ import { FactionWorkType } from "../Work/data/FactionWorkType";
|
|||||||
import { CompanyWork } from "../Work/CompanyWork";
|
import { CompanyWork } from "../Work/CompanyWork";
|
||||||
import { canGetBonus, onExport } from "../ExportBonus";
|
import { canGetBonus, onExport } from "../ExportBonus";
|
||||||
import { saveObject } from "../SaveObject";
|
import { saveObject } from "../SaveObject";
|
||||||
import { calculateCrimeWorkStats } from "../Work/formulas/Crime";
|
import { calculateCrimeWorkStats } from "../Work/Formulas";
|
||||||
import { checkEnum } from "../utils/helpers/checkEnum";
|
import { checkEnum } from "../utils/helpers/checkEnum";
|
||||||
import { Crimes } from "../Crime/Crimes";
|
import { Crimes } from "../Crime/Crimes";
|
||||||
import { CrimeType } from "../utils/WorkType";
|
import { CrimeType } from "../utils/WorkType";
|
||||||
@ -1160,7 +1160,7 @@ export function NetscriptSingularity(): InternalAPI<ISingularity> {
|
|||||||
const crime = checkEnum(CrimeType, crimeType) ? Crimes[crimeType] : findCrime(crimeType);
|
const crime = checkEnum(CrimeType, crimeType) ? Crimes[crimeType] : findCrime(crimeType);
|
||||||
if (crime == null) throw helpers.makeRuntimeErrorMsg(ctx, `Invalid crime: '${crimeType}'`);
|
if (crime == null) throw helpers.makeRuntimeErrorMsg(ctx, `Invalid crime: '${crimeType}'`);
|
||||||
|
|
||||||
const crimeStatsWithMultipliers = calculateCrimeWorkStats(crime);
|
const crimeStatsWithMultipliers = calculateCrimeWorkStats(Player, crime);
|
||||||
|
|
||||||
return Object.assign({}, crime, {
|
return Object.assign({}, crime, {
|
||||||
money: crimeStatsWithMultipliers.money,
|
money: crimeStatsWithMultipliers.money,
|
||||||
|
@ -13,6 +13,7 @@ import { isSleeveCompanyWork } from "../PersonObjects/Sleeve/Work/SleeveCompanyW
|
|||||||
import { helpers } from "../Netscript/NetscriptHelpers";
|
import { helpers } from "../Netscript/NetscriptHelpers";
|
||||||
import { Crimes } from "../Crime/Crimes";
|
import { Crimes } from "../Crime/Crimes";
|
||||||
import { CrimeType } from "../utils/WorkType";
|
import { CrimeType } from "../utils/WorkType";
|
||||||
|
import { cloneDeep } from "lodash";
|
||||||
|
|
||||||
export function NetscriptSleeve(): InternalAPI<ISleeve> {
|
export function NetscriptSleeve(): InternalAPI<ISleeve> {
|
||||||
const checkSleeveAPIAccess = function (ctx: NetscriptContext) {
|
const checkSleeveAPIAccess = function (ctx: NetscriptContext) {
|
||||||
@ -200,6 +201,7 @@ export function NetscriptSleeve(): InternalAPI<ISleeve> {
|
|||||||
strengthExp: sl.mults.strength_exp,
|
strengthExp: sl.mults.strength_exp,
|
||||||
workMoney: sl.mults.work_money,
|
workMoney: sl.mults.work_money,
|
||||||
},
|
},
|
||||||
|
skills: cloneDeep(sl.skills),
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
getSleeveAugmentations: (ctx) => (_sleeveNumber) => {
|
getSleeveAugmentations: (ctx) => (_sleeveNumber) => {
|
||||||
|
@ -2,7 +2,7 @@ import { Generic_fromJSON, Generic_toJSON, IReviverValue, Reviver } from "../../
|
|||||||
import { applySleeveGains, Work, WorkType } from "./Work";
|
import { applySleeveGains, Work, WorkType } from "./Work";
|
||||||
import { ClassType } from "../../../Work/ClassWork";
|
import { ClassType } from "../../../Work/ClassWork";
|
||||||
import { LocationName } from "../../../Locations/data/LocationNames";
|
import { LocationName } from "../../../Locations/data/LocationNames";
|
||||||
import { calculateClassEarnings } from "../../../Work/formulas/Class";
|
import { calculateClassEarnings } from "../../../Work/Formulas";
|
||||||
import { Sleeve } from "../Sleeve";
|
import { Sleeve } from "../Sleeve";
|
||||||
import { scaleWorkStats, WorkStats } from "../../../Work/WorkStats";
|
import { scaleWorkStats, WorkStats } from "../../../Work/WorkStats";
|
||||||
|
|
||||||
|
@ -4,9 +4,11 @@ import { applySleeveGains, Work, WorkType } from "./Work";
|
|||||||
import { LocationName } from "../../../Locations/data/LocationNames";
|
import { LocationName } from "../../../Locations/data/LocationNames";
|
||||||
import { Companies } from "../../../Company/Companies";
|
import { Companies } from "../../../Company/Companies";
|
||||||
import { Company } from "../../../Company/Company";
|
import { Company } from "../../../Company/Company";
|
||||||
import { calculateCompanyWorkStats } from "../../../Work/formulas/Company";
|
import { calculateCompanyWorkStats } from "../../../Work/Formulas";
|
||||||
import { WorkStats } from "../../../Work/WorkStats";
|
import { WorkStats } from "../../../Work/WorkStats";
|
||||||
import { influenceStockThroughCompanyWork } from "../../../StockMarket/PlayerInfluencing";
|
import { influenceStockThroughCompanyWork } from "../../../StockMarket/PlayerInfluencing";
|
||||||
|
import { Player } from "@player";
|
||||||
|
import { CompanyPositions } from "../../../Company/CompanyPositions";
|
||||||
|
|
||||||
interface SleeveCompanyWorkParams {
|
interface SleeveCompanyWorkParams {
|
||||||
companyName: string;
|
companyName: string;
|
||||||
@ -30,7 +32,8 @@ export class SleeveCompanyWork extends Work {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getGainRates(sleeve: Sleeve): WorkStats {
|
getGainRates(sleeve: Sleeve): WorkStats {
|
||||||
return calculateCompanyWorkStats(sleeve, this.getCompany());
|
const company = this.getCompany();
|
||||||
|
return calculateCompanyWorkStats(sleeve, company, CompanyPositions[Player.jobs[company.name]], company.favor);
|
||||||
}
|
}
|
||||||
|
|
||||||
process(sleeve: Sleeve, cycles: number): number {
|
process(sleeve: Sleeve, cycles: number): number {
|
||||||
|
@ -5,10 +5,10 @@ import { applySleeveGains, Work, WorkType } from "./Work";
|
|||||||
import { CrimeType } from "../../../utils/WorkType";
|
import { CrimeType } from "../../../utils/WorkType";
|
||||||
import { Crimes } from "../../../Crime/Crimes";
|
import { Crimes } from "../../../Crime/Crimes";
|
||||||
import { Crime } from "../../../Crime/Crime";
|
import { Crime } from "../../../Crime/Crime";
|
||||||
import { newWorkStats, scaleWorkStats, WorkStats } from "../../../Work/WorkStats";
|
import { scaleWorkStats, WorkStats } from "../../../Work/WorkStats";
|
||||||
import { CONSTANTS } from "../../../Constants";
|
import { CONSTANTS } from "../../../Constants";
|
||||||
import { BitNodeMultipliers } from "../../../BitNode/BitNodeMultipliers";
|
|
||||||
import { checkEnum } from "../../../utils/helpers/checkEnum";
|
import { checkEnum } from "../../../utils/helpers/checkEnum";
|
||||||
|
import { calculateCrimeWorkStats } from "../../../Work/Formulas";
|
||||||
|
|
||||||
export const isSleeveCrimeWork = (w: Work | null): w is SleeveCrimeWork => w !== null && w.type === WorkType.CRIME;
|
export const isSleeveCrimeWork = (w: Work | null): w is SleeveCrimeWork => w !== null && w.type === WorkType.CRIME;
|
||||||
|
|
||||||
@ -26,17 +26,7 @@ export class SleeveCrimeWork extends Work {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getExp(sleeve: Sleeve): WorkStats {
|
getExp(sleeve: Sleeve): WorkStats {
|
||||||
const crime = this.getCrime();
|
return calculateCrimeWorkStats(sleeve, this.getCrime());
|
||||||
return newWorkStats({
|
|
||||||
money: crime.money * BitNodeMultipliers.CrimeMoney * sleeve.mults.crime_money,
|
|
||||||
hackExp: crime.hacking_exp * BitNodeMultipliers.CrimeExpGain * sleeve.mults.hacking_exp,
|
|
||||||
strExp: crime.strength_exp * BitNodeMultipliers.CrimeExpGain * sleeve.mults.strength_exp,
|
|
||||||
defExp: crime.defense_exp * BitNodeMultipliers.CrimeExpGain * sleeve.mults.defense_exp,
|
|
||||||
dexExp: crime.dexterity_exp * BitNodeMultipliers.CrimeExpGain * sleeve.mults.dexterity_exp,
|
|
||||||
agiExp: crime.agility_exp * BitNodeMultipliers.CrimeExpGain * sleeve.mults.agility_exp,
|
|
||||||
chaExp: crime.charisma_exp * BitNodeMultipliers.CrimeExpGain * sleeve.mults.charisma_exp,
|
|
||||||
intExp: crime.intelligence_exp * BitNodeMultipliers.CrimeExpGain,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cyclesNeeded(): number {
|
cyclesNeeded(): number {
|
||||||
|
@ -5,15 +5,9 @@ import { applySleeveGains, Work, WorkType } from "./Work";
|
|||||||
import { FactionWorkType } from "../../../Work/data/FactionWorkType";
|
import { FactionWorkType } from "../../../Work/data/FactionWorkType";
|
||||||
import { FactionNames } from "../../../Faction/data/FactionNames";
|
import { FactionNames } from "../../../Faction/data/FactionNames";
|
||||||
import { Factions } from "../../../Faction/Factions";
|
import { Factions } from "../../../Faction/Factions";
|
||||||
import { calculateFactionExp } from "../../../Work/formulas/Faction";
|
import { calculateFactionExp, calculateFactionRep } from "../../../Work/Formulas";
|
||||||
import { Faction } from "../../../Faction/Faction";
|
import { Faction } from "../../../Faction/Faction";
|
||||||
import {
|
|
||||||
getFactionFieldWorkRepGain,
|
|
||||||
getFactionSecurityWorkRepGain,
|
|
||||||
getHackingWorkRepGain,
|
|
||||||
} from "../../../PersonObjects/formulas/reputation";
|
|
||||||
import { scaleWorkStats, WorkStats } from "../../../Work/WorkStats";
|
import { scaleWorkStats, WorkStats } from "../../../Work/WorkStats";
|
||||||
import { BitNodeMultipliers } from "../../../BitNode/BitNodeMultipliers";
|
|
||||||
|
|
||||||
interface SleeveFactionWorkParams {
|
interface SleeveFactionWorkParams {
|
||||||
factionWorkType: FactionWorkType;
|
factionWorkType: FactionWorkType;
|
||||||
@ -38,17 +32,7 @@ export class SleeveFactionWork extends Work {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getReputationRate(sleeve: Sleeve): number {
|
getReputationRate(sleeve: Sleeve): number {
|
||||||
const faction = this.getFaction();
|
return calculateFactionRep(sleeve, this.factionWorkType, this.getFaction().favor) * sleeve.shockBonus();
|
||||||
const repFormulas = {
|
|
||||||
[FactionWorkType.HACKING]: getHackingWorkRepGain,
|
|
||||||
[FactionWorkType.FIELD]: getFactionFieldWorkRepGain,
|
|
||||||
[FactionWorkType.SECURITY]: getFactionSecurityWorkRepGain,
|
|
||||||
};
|
|
||||||
return (
|
|
||||||
repFormulas[this.factionWorkType](sleeve, faction.favor) *
|
|
||||||
sleeve.shockBonus() *
|
|
||||||
BitNodeMultipliers.FactionWorkRepGain
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
getFaction(): Faction {
|
getFaction(): Faction {
|
||||||
|
89
src/ScriptEditor/NetscriptDefinitions.d.ts
vendored
89
src/ScriptEditor/NetscriptDefinitions.d.ts
vendored
@ -37,7 +37,7 @@ type ScriptArg = string | number | boolean;
|
|||||||
type FilenameOrPID = number | string;
|
type FilenameOrPID = number | string;
|
||||||
|
|
||||||
/** @public */
|
/** @public */
|
||||||
interface Player {
|
interface Person {
|
||||||
hp: HP;
|
hp: HP;
|
||||||
skills: Skills;
|
skills: Skills;
|
||||||
exp: Skills;
|
exp: Skills;
|
||||||
@ -641,62 +641,6 @@ export interface NodeStats {
|
|||||||
totalProduction: number;
|
totalProduction: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @public */
|
|
||||||
export interface CharacterMult {
|
|
||||||
/** Agility stat */
|
|
||||||
agility: number;
|
|
||||||
/** Agility exp */
|
|
||||||
agilityExp: number;
|
|
||||||
/** Charisma stat */
|
|
||||||
charisma: number;
|
|
||||||
/** Charisma exp */
|
|
||||||
charismaExp: number;
|
|
||||||
/** Company reputation */
|
|
||||||
companyRep: number;
|
|
||||||
/** Money earned from crimes */
|
|
||||||
crimeMoney: number;
|
|
||||||
/** Crime success chance */
|
|
||||||
crimeSuccess: number;
|
|
||||||
/** Defense stat */
|
|
||||||
defense: number;
|
|
||||||
/** Defense exp */
|
|
||||||
defenseExp: number;
|
|
||||||
/** Dexterity stat */
|
|
||||||
dexterity: number;
|
|
||||||
/** Dexterity exp */
|
|
||||||
dexterityExp: number;
|
|
||||||
/** Faction reputation */
|
|
||||||
factionRep: number;
|
|
||||||
/** Hacking stat */
|
|
||||||
hacking: number;
|
|
||||||
/** Hacking exp */
|
|
||||||
hackingExp: number;
|
|
||||||
/** Strength stat */
|
|
||||||
strength: number;
|
|
||||||
/** Strength exp */
|
|
||||||
strengthExp: number;
|
|
||||||
/** Money earned from jobs */
|
|
||||||
workMoney: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @public */
|
|
||||||
export interface SleeveWorkGains {
|
|
||||||
/** Hacking exp gained from work */
|
|
||||||
workHackExpGain: number;
|
|
||||||
/** Strength exp gained from work */
|
|
||||||
workStrExpGain: number;
|
|
||||||
/** Defense exp gained from work, */
|
|
||||||
workDefExpGain: number;
|
|
||||||
/** Dexterity exp gained from work */
|
|
||||||
workDexExpGain: number;
|
|
||||||
/** Agility exp gained from work */
|
|
||||||
workAgiExpGain: number;
|
|
||||||
/** Charisma exp gained from work */
|
|
||||||
workChaExpGain: number;
|
|
||||||
/** Money gained from work */
|
|
||||||
workMoneyGain: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @public */
|
/** @public */
|
||||||
export interface SourceFileLvl {
|
export interface SourceFileLvl {
|
||||||
/** The number of the source file */
|
/** The number of the source file */
|
||||||
@ -966,7 +910,9 @@ export interface SleeveInformation {
|
|||||||
/** Does this sleeve have access to the tor router */
|
/** Does this sleeve have access to the tor router */
|
||||||
tor: boolean;
|
tor: boolean;
|
||||||
/** Sleeve multipliers */
|
/** Sleeve multipliers */
|
||||||
mult: CharacterMult;
|
mult: Multipliers;
|
||||||
|
/** Sleeve skills */
|
||||||
|
skills: Skills;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -3907,9 +3853,10 @@ export interface WorkStats {
|
|||||||
* @public
|
* @public
|
||||||
*/
|
*/
|
||||||
interface WorkFormulas {
|
interface WorkFormulas {
|
||||||
crimeGains(crimeType: CrimeType | CrimeNames): WorkStats;
|
crimeGains(person: Person, crimeType: CrimeType | CrimeNames): WorkStats;
|
||||||
classGains(player: Player, classType: string, locationName: string): WorkStats;
|
classGains(person: Person, classType: string, locationName: string): WorkStats;
|
||||||
factionGains(player: Player, workType: string, favor: number): WorkStats;
|
factionGains(person: Person, workType: string, favor: number): WorkStats;
|
||||||
|
companyGains(person: Person, companyName: string, workType: string, favor: number): WorkStats;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -3936,7 +3883,7 @@ interface ReputationFormulas {
|
|||||||
* @param amount - Amount of money donated
|
* @param amount - Amount of money donated
|
||||||
* @param player - Player info from {@link NS.getPlayer | getPlayer}
|
* @param player - Player info from {@link NS.getPlayer | getPlayer}
|
||||||
*/
|
*/
|
||||||
repFromDonation(amount: number, player: Player): number;
|
repFromDonation(amount: number, player: Person): number;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -3951,7 +3898,7 @@ interface HackingFormulas {
|
|||||||
* @param player - Player info from {@link NS.getPlayer | getPlayer}
|
* @param player - Player info from {@link NS.getPlayer | getPlayer}
|
||||||
* @returns The calculated hack chance.
|
* @returns The calculated hack chance.
|
||||||
*/
|
*/
|
||||||
hackChance(server: Server, player: Player): number;
|
hackChance(server: Server, player: Person): number;
|
||||||
/**
|
/**
|
||||||
* Calculate hack exp for one thread.
|
* Calculate hack exp for one thread.
|
||||||
* @remarks
|
* @remarks
|
||||||
@ -3960,7 +3907,7 @@ interface HackingFormulas {
|
|||||||
* @param player - Player info from {@link NS.getPlayer | getPlayer}
|
* @param player - Player info from {@link NS.getPlayer | getPlayer}
|
||||||
* @returns The calculated hack exp.
|
* @returns The calculated hack exp.
|
||||||
*/
|
*/
|
||||||
hackExp(server: Server, player: Player): number;
|
hackExp(server: Server, player: Person): number;
|
||||||
/**
|
/**
|
||||||
* Calculate hack percent for one thread.
|
* Calculate hack percent for one thread.
|
||||||
* (Ex: 0.25 would steal 25% of the server's current value.)
|
* (Ex: 0.25 would steal 25% of the server's current value.)
|
||||||
@ -3970,7 +3917,7 @@ interface HackingFormulas {
|
|||||||
* @param player - Player info from {@link NS.getPlayer | getPlayer}
|
* @param player - Player info from {@link NS.getPlayer | getPlayer}
|
||||||
* @returns The calculated hack percent.
|
* @returns The calculated hack percent.
|
||||||
*/
|
*/
|
||||||
hackPercent(server: Server, player: Player): number;
|
hackPercent(server: Server, player: Person): number;
|
||||||
/**
|
/**
|
||||||
* Calculate the percent a server would grow to.
|
* Calculate the percent a server would grow to.
|
||||||
* (Ex: 3.0 would would grow the server to 300% of its current value.)
|
* (Ex: 3.0 would would grow the server to 300% of its current value.)
|
||||||
@ -3980,28 +3927,28 @@ interface HackingFormulas {
|
|||||||
* @param cores - Number of cores on the computer that will execute grow.
|
* @param cores - Number of cores on the computer that will execute grow.
|
||||||
* @returns The calculated grow percent.
|
* @returns The calculated grow percent.
|
||||||
*/
|
*/
|
||||||
growPercent(server: Server, threads: number, player: Player, cores?: number): number;
|
growPercent(server: Server, threads: number, player: Person, cores?: number): number;
|
||||||
/**
|
/**
|
||||||
* Calculate hack time.
|
* Calculate hack time.
|
||||||
* @param server - Server info from {@link NS.getServer | getServer}
|
* @param server - Server info from {@link NS.getServer | getServer}
|
||||||
* @param player - Player info from {@link NS.getPlayer | getPlayer}
|
* @param player - Player info from {@link NS.getPlayer | getPlayer}
|
||||||
* @returns The calculated hack time.
|
* @returns The calculated hack time.
|
||||||
*/
|
*/
|
||||||
hackTime(server: Server, player: Player): number;
|
hackTime(server: Server, player: Person): number;
|
||||||
/**
|
/**
|
||||||
* Calculate grow time.
|
* Calculate grow time.
|
||||||
* @param server - Server info from {@link NS.getServer | getServer}
|
* @param server - Server info from {@link NS.getServer | getServer}
|
||||||
* @param player - Player info from {@link NS.getPlayer | getPlayer}
|
* @param player - Player info from {@link NS.getPlayer | getPlayer}
|
||||||
* @returns The calculated grow time.
|
* @returns The calculated grow time.
|
||||||
*/
|
*/
|
||||||
growTime(server: Server, player: Player): number;
|
growTime(server: Server, player: Person): number;
|
||||||
/**
|
/**
|
||||||
* Calculate weaken time.
|
* Calculate weaken time.
|
||||||
* @param server - Server info from {@link NS.getServer | getServer}
|
* @param server - Server info from {@link NS.getServer | getServer}
|
||||||
* @param player - Player info from {@link NS.getPlayer | getPlayer}
|
* @param player - Player info from {@link NS.getPlayer | getPlayer}
|
||||||
* @returns The calculated weaken time.
|
* @returns The calculated weaken time.
|
||||||
*/
|
*/
|
||||||
weakenTime(server: Server, player: Player): number;
|
weakenTime(server: Server, player: Person): number;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -4182,7 +4129,7 @@ interface GangFormulas {
|
|||||||
*/
|
*/
|
||||||
export interface Formulas {
|
export interface Formulas {
|
||||||
mockServer(): Server;
|
mockServer(): Server;
|
||||||
mockPlayer(): Player;
|
mockPlayer(): Person;
|
||||||
/** Reputation formulas */
|
/** Reputation formulas */
|
||||||
reputation: ReputationFormulas;
|
reputation: ReputationFormulas;
|
||||||
/** Skills formulas */
|
/** Skills formulas */
|
||||||
@ -6758,7 +6705,7 @@ export interface NS {
|
|||||||
*
|
*
|
||||||
* @returns Player info
|
* @returns Player info
|
||||||
*/
|
*/
|
||||||
getPlayer(): Player;
|
getPlayer(): Person;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get information about the sources of income for this run.
|
* Get information about the sources of income for this run.
|
||||||
|
@ -7,7 +7,7 @@ import { dialogBoxCreate } from "../ui/React/DialogBox";
|
|||||||
import { Money } from "../ui/React/Money";
|
import { Money } from "../ui/React/Money";
|
||||||
import { convertTimeMsToTimeElapsedString } from "../utils/StringHelperFunctions";
|
import { convertTimeMsToTimeElapsedString } from "../utils/StringHelperFunctions";
|
||||||
import { Player } from "@player";
|
import { Player } from "@player";
|
||||||
import { calculateClassEarnings as calculateClassEarningsRate } from "./formulas/Class";
|
import { calculateClassEarnings as calculateClassEarningsRate } from "./Formulas";
|
||||||
import { Work, WorkType } from "./Work";
|
import { Work, WorkType } from "./Work";
|
||||||
import { applyWorkStats, newWorkStats, sumWorkStats, WorkStats } from "./WorkStats";
|
import { applyWorkStats, newWorkStats, sumWorkStats, WorkStats } from "./WorkStats";
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@ import { Player } from "@player";
|
|||||||
import { Work, WorkType } from "./Work";
|
import { Work, WorkType } from "./Work";
|
||||||
import { influenceStockThroughCompanyWork } from "../StockMarket/PlayerInfluencing";
|
import { influenceStockThroughCompanyWork } from "../StockMarket/PlayerInfluencing";
|
||||||
import { LocationName } from "../Locations/data/LocationNames";
|
import { LocationName } from "../Locations/data/LocationNames";
|
||||||
import { calculateCompanyWorkStats } from "./formulas/Company";
|
import { calculateCompanyWorkStats } from "./Formulas";
|
||||||
import { Companies } from "../Company/Companies";
|
import { Companies } from "../Company/Companies";
|
||||||
import { applyWorkStats, scaleWorkStats, WorkStats } from "./WorkStats";
|
import { applyWorkStats, scaleWorkStats, WorkStats } from "./WorkStats";
|
||||||
import { Company } from "../Company/Company";
|
import { Company } from "../Company/Company";
|
||||||
@ -12,6 +12,7 @@ import { dialogBoxCreate } from "../ui/React/DialogBox";
|
|||||||
import { Reputation } from "../ui/React/Reputation";
|
import { Reputation } from "../ui/React/Reputation";
|
||||||
import { AugmentationNames } from "../Augmentation/data/AugmentationNames";
|
import { AugmentationNames } from "../Augmentation/data/AugmentationNames";
|
||||||
import { CONSTANTS } from "../Constants";
|
import { CONSTANTS } from "../Constants";
|
||||||
|
import { CompanyPositions } from "../Company/CompanyPositions";
|
||||||
|
|
||||||
interface CompanyWorkParams {
|
interface CompanyWorkParams {
|
||||||
companyName: string;
|
companyName: string;
|
||||||
@ -38,7 +39,11 @@ export class CompanyWork extends Work {
|
|||||||
if (!Player.hasAugmentation(AugmentationNames.NeuroreceptorManager, true)) {
|
if (!Player.hasAugmentation(AugmentationNames.NeuroreceptorManager, true)) {
|
||||||
focusBonus = Player.focus ? 1 : CONSTANTS.BaseFocusBonus;
|
focusBonus = Player.focus ? 1 : CONSTANTS.BaseFocusBonus;
|
||||||
}
|
}
|
||||||
return scaleWorkStats(calculateCompanyWorkStats(Player, this.getCompany()), focusBonus);
|
const company = this.getCompany();
|
||||||
|
return scaleWorkStats(
|
||||||
|
calculateCompanyWorkStats(Player, company, CompanyPositions[Player.jobs[company.name]], company.favor),
|
||||||
|
focusBonus,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
process(cycles: number): boolean {
|
process(cycles: number): boolean {
|
||||||
|
@ -8,7 +8,7 @@ import { dialogBoxCreate } from "../ui/React/DialogBox";
|
|||||||
import { CrimeType } from "../utils/WorkType";
|
import { CrimeType } from "../utils/WorkType";
|
||||||
import { Work, WorkType } from "./Work";
|
import { Work, WorkType } from "./Work";
|
||||||
import { scaleWorkStats, WorkStats } from "./WorkStats";
|
import { scaleWorkStats, WorkStats } from "./WorkStats";
|
||||||
import { calculateCrimeWorkStats } from "./formulas/Crime";
|
import { calculateCrimeWorkStats } from "./Formulas";
|
||||||
import { checkEnum } from "../utils/helpers/checkEnum";
|
import { checkEnum } from "../utils/helpers/checkEnum";
|
||||||
|
|
||||||
interface CrimeWorkParams {
|
interface CrimeWorkParams {
|
||||||
@ -47,7 +47,7 @@ export class CrimeWork extends Work {
|
|||||||
}
|
}
|
||||||
|
|
||||||
earnings(): WorkStats {
|
earnings(): WorkStats {
|
||||||
return calculateCrimeWorkStats(this.getCrime());
|
return calculateCrimeWorkStats(Player, this.getCrime());
|
||||||
}
|
}
|
||||||
|
|
||||||
commit(): void {
|
commit(): void {
|
||||||
|
@ -10,7 +10,7 @@ import { dialogBoxCreate } from "../ui/React/DialogBox";
|
|||||||
import { Reputation } from "../ui/React/Reputation";
|
import { Reputation } from "../ui/React/Reputation";
|
||||||
import { CONSTANTS } from "../Constants";
|
import { CONSTANTS } from "../Constants";
|
||||||
import { AugmentationNames } from "../Augmentation/data/AugmentationNames";
|
import { AugmentationNames } from "../Augmentation/data/AugmentationNames";
|
||||||
import { calculateFactionExp, calculateFactionRep } from "./formulas/Faction";
|
import { calculateFactionExp, calculateFactionRep } from "./Formulas";
|
||||||
import { FactionWorkType } from "./data/FactionWorkType";
|
import { FactionWorkType } from "./data/FactionWorkType";
|
||||||
|
|
||||||
interface FactionWorkParams {
|
interface FactionWorkParams {
|
||||||
|
142
src/Work/Formulas.ts
Normal file
142
src/Work/Formulas.ts
Normal file
@ -0,0 +1,142 @@
|
|||||||
|
import { BitNodeMultipliers } from "../BitNode/BitNodeMultipliers";
|
||||||
|
import { Crime } from "../Crime/Crime";
|
||||||
|
import { newWorkStats, scaleWorkStats, WorkStats, multWorkStats } from "./WorkStats";
|
||||||
|
import { Person } from "../PersonObjects/Person";
|
||||||
|
import { CONSTANTS } from "../Constants";
|
||||||
|
import { FactionWorkType } from "./data/FactionWorkType";
|
||||||
|
import {
|
||||||
|
getFactionFieldWorkRepGain,
|
||||||
|
getFactionSecurityWorkRepGain,
|
||||||
|
getHackingWorkRepGain,
|
||||||
|
} from "../PersonObjects/formulas/reputation";
|
||||||
|
import { Locations } from "../Locations/Locations";
|
||||||
|
import { Location } from "../Locations/Location";
|
||||||
|
import { Player } from "@player";
|
||||||
|
import { Class, Classes, ClassType } from "./ClassWork";
|
||||||
|
import { Server } from "../Server/Server";
|
||||||
|
import { GetServer } from "../Server/AllServers";
|
||||||
|
import { serverMetadata } from "../Server/data/servers";
|
||||||
|
import { LocationName } from "../Locations/data/LocationNames";
|
||||||
|
import { Company } from "../Company/Company";
|
||||||
|
import { CompanyPosition } from "../Company/CompanyPosition";
|
||||||
|
|
||||||
|
const gameCPS = 1000 / CONSTANTS._idleSpeed; // 5 cycles per second
|
||||||
|
export const FactionWorkStats: Record<FactionWorkType, WorkStats> = {
|
||||||
|
[FactionWorkType.HACKING]: newWorkStats({ hackExp: 15 }),
|
||||||
|
[FactionWorkType.FIELD]: newWorkStats({
|
||||||
|
hackExp: 10,
|
||||||
|
strExp: 10,
|
||||||
|
defExp: 10,
|
||||||
|
dexExp: 10,
|
||||||
|
agiExp: 10,
|
||||||
|
chaExp: 10,
|
||||||
|
}),
|
||||||
|
[FactionWorkType.SECURITY]: newWorkStats({
|
||||||
|
hackExp: 5,
|
||||||
|
strExp: 15,
|
||||||
|
defExp: 15,
|
||||||
|
dexExp: 15,
|
||||||
|
agiExp: 15,
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
|
||||||
|
export function calculateCrimeWorkStats(person: Person, crime: Crime): WorkStats {
|
||||||
|
const gains = scaleWorkStats(
|
||||||
|
multWorkStats(
|
||||||
|
//Todo: rework crime and workstats interfaces to use the same naming convention for exp values, then we can just make a workStats directly from a crime.
|
||||||
|
newWorkStats({
|
||||||
|
money: crime.money,
|
||||||
|
hackExp: crime.hacking_exp,
|
||||||
|
strExp: crime.strength_exp,
|
||||||
|
defExp: crime.defense_exp,
|
||||||
|
dexExp: crime.dexterity_exp,
|
||||||
|
agiExp: crime.agility_exp,
|
||||||
|
chaExp: crime.charisma_exp,
|
||||||
|
intExp: crime.intelligence_exp,
|
||||||
|
}),
|
||||||
|
person.mults,
|
||||||
|
person.mults.crime_money * BitNodeMultipliers.CrimeMoney,
|
||||||
|
),
|
||||||
|
BitNodeMultipliers.CrimeExpGain,
|
||||||
|
false,
|
||||||
|
);
|
||||||
|
return gains;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const calculateFactionRep = (person: Person, type: FactionWorkType, favor: number): number => {
|
||||||
|
const repFormulas = {
|
||||||
|
[FactionWorkType.HACKING]: getHackingWorkRepGain,
|
||||||
|
[FactionWorkType.FIELD]: getFactionFieldWorkRepGain,
|
||||||
|
[FactionWorkType.SECURITY]: getFactionSecurityWorkRepGain,
|
||||||
|
};
|
||||||
|
return repFormulas[type](person, favor);
|
||||||
|
};
|
||||||
|
|
||||||
|
export function calculateFactionExp(person: Person, type: FactionWorkType): WorkStats {
|
||||||
|
return scaleWorkStats(
|
||||||
|
multWorkStats(FactionWorkStats[type], person.mults),
|
||||||
|
BitNodeMultipliers.FactionWorkExpGain / gameCPS,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Calculate cost for a class */
|
||||||
|
export function calculateCost(classs: Class, location: Location): number {
|
||||||
|
const serverMeta = serverMetadata.find((s) => s.specialName === location.name);
|
||||||
|
const server = GetServer(serverMeta ? serverMeta.hostname : "");
|
||||||
|
const discount = (server as Server).backdoorInstalled ? 0.9 : 1;
|
||||||
|
return classs.earnings.money * location.costMult * discount;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function calculateClassEarnings(person: Person, type: ClassType, locationName: LocationName): WorkStats {
|
||||||
|
const hashManager = Player.hashManager;
|
||||||
|
const classs = Classes[type];
|
||||||
|
const location = Locations[locationName];
|
||||||
|
|
||||||
|
const hashMult = [ClassType.GymAgility, ClassType.GymDefense, ClassType.GymStrength, ClassType.GymDexterity].includes(
|
||||||
|
type,
|
||||||
|
)
|
||||||
|
? hashManager.getTrainingMult()
|
||||||
|
: hashManager.getStudyMult();
|
||||||
|
|
||||||
|
const earnings = multWorkStats(
|
||||||
|
scaleWorkStats(classs.earnings, (location.expMult / gameCPS) * hashMult, false),
|
||||||
|
person.mults,
|
||||||
|
);
|
||||||
|
earnings.money = calculateCost(classs, location) / gameCPS;
|
||||||
|
return earnings;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const calculateCompanyWorkStats = (
|
||||||
|
worker: Person,
|
||||||
|
company: Company,
|
||||||
|
companyPosition: CompanyPosition,
|
||||||
|
favor: number,
|
||||||
|
): WorkStats => {
|
||||||
|
// If player has SF-11, calculate salary multiplier from favor
|
||||||
|
const favorMult = isNaN(favor) ? 1 : 1 + favor / 100;
|
||||||
|
const bn11Mult = Player.sourceFileLvl(11) > 0 ? favorMult : 1;
|
||||||
|
|
||||||
|
const gains = scaleWorkStats(
|
||||||
|
multWorkStats(
|
||||||
|
{
|
||||||
|
money: companyPosition.baseSalary * company.salaryMultiplier * bn11Mult * BitNodeMultipliers.CompanyWorkMoney,
|
||||||
|
hackExp: companyPosition.hackingExpGain,
|
||||||
|
strExp: companyPosition.strengthExpGain,
|
||||||
|
defExp: companyPosition.defenseExpGain,
|
||||||
|
dexExp: companyPosition.dexterityExpGain,
|
||||||
|
agiExp: companyPosition.agilityExpGain,
|
||||||
|
chaExp: companyPosition.charismaExpGain,
|
||||||
|
},
|
||||||
|
worker.mults,
|
||||||
|
worker.mults.work_money,
|
||||||
|
),
|
||||||
|
company.expMultiplier * BitNodeMultipliers.CompanyWorkExpGain,
|
||||||
|
false,
|
||||||
|
);
|
||||||
|
|
||||||
|
const jobPerformance = companyPosition.calculateJobPerformance(worker);
|
||||||
|
|
||||||
|
gains.reputation = jobPerformance * worker.mults.company_rep * favorMult;
|
||||||
|
|
||||||
|
return gains;
|
||||||
|
};
|
@ -1,5 +1,6 @@
|
|||||||
import { Person } from "src/PersonObjects/Person";
|
import { Person } from "src/PersonObjects/Person";
|
||||||
import { Player } from "@player";
|
import { Player } from "@player";
|
||||||
|
import { Multipliers } from "../PersonObjects/Multipliers";
|
||||||
|
|
||||||
export interface WorkStats {
|
export interface WorkStats {
|
||||||
money: number;
|
money: number;
|
||||||
@ -13,19 +14,7 @@ export interface WorkStats {
|
|||||||
intExp: number;
|
intExp: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface newWorkStatsParams {
|
export const newWorkStats = (params?: Partial<WorkStats>): WorkStats => {
|
||||||
money?: number;
|
|
||||||
reputation?: number;
|
|
||||||
hackExp?: number;
|
|
||||||
strExp?: number;
|
|
||||||
defExp?: number;
|
|
||||||
dexExp?: number;
|
|
||||||
agiExp?: number;
|
|
||||||
chaExp?: number;
|
|
||||||
intExp?: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const newWorkStats = (params?: newWorkStatsParams): WorkStats => {
|
|
||||||
return {
|
return {
|
||||||
money: params?.money ?? 0,
|
money: params?.money ?? 0,
|
||||||
reputation: params?.reputation ?? 0,
|
reputation: params?.reputation ?? 0,
|
||||||
@ -39,6 +28,7 @@ export const newWorkStats = (params?: newWorkStatsParams): WorkStats => {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** Add two workStats objects */
|
||||||
export const sumWorkStats = (w0: WorkStats, w1: WorkStats): WorkStats => {
|
export const sumWorkStats = (w0: WorkStats, w1: WorkStats): WorkStats => {
|
||||||
return {
|
return {
|
||||||
money: w0.money + w1.money,
|
money: w0.money + w1.money,
|
||||||
@ -53,6 +43,7 @@ export const sumWorkStats = (w0: WorkStats, w1: WorkStats): WorkStats => {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** Scale all stats on a WorkStats object by a number. Money scaling optional but defaults to true. */
|
||||||
export const scaleWorkStats = (w: WorkStats, n: number, scaleMoney = true): WorkStats => {
|
export const scaleWorkStats = (w: WorkStats, n: number, scaleMoney = true): WorkStats => {
|
||||||
const m = scaleMoney ? n : 1;
|
const m = scaleMoney ? n : 1;
|
||||||
return {
|
return {
|
||||||
@ -107,3 +98,18 @@ export const applyWorkStatsExp = (target: Person, workStats: WorkStats, cycles:
|
|||||||
target.gainIntelligenceExp(gains.intExp);
|
target.gainIntelligenceExp(gains.intExp);
|
||||||
return gains;
|
return gains;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** Calculate the application of a person's multipliers to a WorkStats object */
|
||||||
|
export function multWorkStats(workStats: Partial<WorkStats>, mults: Multipliers, moneyMult = 1, repMult = 1) {
|
||||||
|
return {
|
||||||
|
money: (workStats.money ?? 0) * moneyMult,
|
||||||
|
reputation: (workStats.reputation ?? 0) * repMult,
|
||||||
|
hackExp: (workStats.hackExp ?? 0) * mults.hacking_exp,
|
||||||
|
strExp: (workStats.strExp ?? 0) * mults.strength_exp,
|
||||||
|
defExp: (workStats.defExp ?? 0) * mults.defense_exp,
|
||||||
|
dexExp: (workStats.dexExp ?? 0) * mults.dexterity_exp,
|
||||||
|
agiExp: (workStats.agiExp ?? 0) * mults.agility_exp,
|
||||||
|
chaExp: (workStats.chaExp ?? 0) * mults.charisma_exp,
|
||||||
|
intExp: workStats.intExp ?? 0,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
@ -1,53 +0,0 @@
|
|||||||
import { Locations } from "../../Locations/Locations";
|
|
||||||
import { Location } from "../../Locations/Location";
|
|
||||||
import { BitNodeMultipliers } from "../../BitNode/BitNodeMultipliers";
|
|
||||||
import { CONSTANTS } from "../../Constants";
|
|
||||||
import { Player } from "@player";
|
|
||||||
import { Class, Classes, ClassType } from "../ClassWork";
|
|
||||||
import { WorkStats } from "../WorkStats";
|
|
||||||
import { Server } from "../../Server/Server";
|
|
||||||
import { GetServer } from "../../Server/AllServers";
|
|
||||||
import { serverMetadata } from "../../Server/data/servers";
|
|
||||||
import { Person } from "../../PersonObjects/Person";
|
|
||||||
import { LocationName } from "../../Locations/data/LocationNames";
|
|
||||||
|
|
||||||
const gameCPS = 1000 / CONSTANTS._idleSpeed; // 5 cycles per second
|
|
||||||
|
|
||||||
export function calculateCost(classs: Class, location: Location): number {
|
|
||||||
const serverMeta = serverMetadata.find((s) => s.specialName === location.name);
|
|
||||||
const server = GetServer(serverMeta ? serverMeta.hostname : "");
|
|
||||||
const discount = (server as Server).backdoorInstalled ? 0.9 : 1;
|
|
||||||
return classs.earnings.money * location.costMult * discount;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function calculateClassEarnings(person: Person, type: ClassType, locationName: LocationName): WorkStats {
|
|
||||||
//Find cost and exp gain per game cycle
|
|
||||||
const hashManager = Player.hashManager;
|
|
||||||
const classs = Classes[type];
|
|
||||||
const location = Locations[locationName];
|
|
||||||
|
|
||||||
const hashMult = [ClassType.GymAgility, ClassType.GymDefense, ClassType.GymStrength, ClassType.GymDexterity].includes(
|
|
||||||
type,
|
|
||||||
)
|
|
||||||
? hashManager.getTrainingMult()
|
|
||||||
: hashManager.getStudyMult();
|
|
||||||
|
|
||||||
const cost = calculateCost(classs, location) / gameCPS;
|
|
||||||
const hackExp = ((classs.earnings.hackExp * location.expMult) / gameCPS) * hashMult;
|
|
||||||
const strExp = ((classs.earnings.strExp * location.expMult) / gameCPS) * hashMult;
|
|
||||||
const defExp = ((classs.earnings.defExp * location.expMult) / gameCPS) * hashMult;
|
|
||||||
const dexExp = ((classs.earnings.dexExp * location.expMult) / gameCPS) * hashMult;
|
|
||||||
const agiExp = ((classs.earnings.agiExp * location.expMult) / gameCPS) * hashMult;
|
|
||||||
const chaExp = ((classs.earnings.chaExp * location.expMult) / gameCPS) * hashMult;
|
|
||||||
return {
|
|
||||||
money: cost,
|
|
||||||
reputation: 0,
|
|
||||||
hackExp: hackExp * person.mults.hacking_exp * BitNodeMultipliers.ClassGymExpGain,
|
|
||||||
strExp: strExp * person.mults.strength_exp * BitNodeMultipliers.ClassGymExpGain,
|
|
||||||
defExp: defExp * person.mults.defense_exp * BitNodeMultipliers.ClassGymExpGain,
|
|
||||||
dexExp: dexExp * person.mults.dexterity_exp * BitNodeMultipliers.ClassGymExpGain,
|
|
||||||
agiExp: agiExp * person.mults.agility_exp * BitNodeMultipliers.ClassGymExpGain,
|
|
||||||
chaExp: chaExp * person.mults.charisma_exp * BitNodeMultipliers.ClassGymExpGain,
|
|
||||||
intExp: 0,
|
|
||||||
};
|
|
||||||
}
|
|
@ -1,75 +0,0 @@
|
|||||||
import { CompanyPositions } from "../../Company/CompanyPositions";
|
|
||||||
import { Company } from "../../Company/Company";
|
|
||||||
import { Player } from "@player";
|
|
||||||
import { WorkStats } from "../WorkStats";
|
|
||||||
import { BitNodeMultipliers } from "../../BitNode/BitNodeMultipliers";
|
|
||||||
import { CONSTANTS } from "../../Constants";
|
|
||||||
import { Person } from "../../PersonObjects/Person";
|
|
||||||
|
|
||||||
export const calculateCompanyWorkStats = (worker: Person, company: Company): WorkStats => {
|
|
||||||
const companyPositionName = Player.jobs[company.name];
|
|
||||||
const companyPosition = CompanyPositions[companyPositionName];
|
|
||||||
|
|
||||||
// If player has SF-11, calculate salary multiplier from favor
|
|
||||||
let favorMult = 1 + company.favor / 100;
|
|
||||||
if (isNaN(favorMult)) {
|
|
||||||
favorMult = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
let bn11Mult = 1;
|
|
||||||
if (Player.sourceFileLvl(11) > 0) {
|
|
||||||
bn11Mult = favorMult;
|
|
||||||
}
|
|
||||||
|
|
||||||
let jobPerformance = companyPosition.calculateJobPerformance(
|
|
||||||
worker.skills.hacking,
|
|
||||||
worker.skills.strength,
|
|
||||||
worker.skills.defense,
|
|
||||||
worker.skills.dexterity,
|
|
||||||
worker.skills.agility,
|
|
||||||
worker.skills.charisma,
|
|
||||||
);
|
|
||||||
|
|
||||||
jobPerformance += worker.skills.intelligence / CONSTANTS.MaxSkillLevel;
|
|
||||||
|
|
||||||
return {
|
|
||||||
money:
|
|
||||||
companyPosition.baseSalary *
|
|
||||||
company.salaryMultiplier *
|
|
||||||
worker.mults.work_money *
|
|
||||||
BitNodeMultipliers.CompanyWorkMoney *
|
|
||||||
bn11Mult,
|
|
||||||
reputation: jobPerformance * worker.mults.company_rep * favorMult,
|
|
||||||
hackExp:
|
|
||||||
companyPosition.hackingExpGain *
|
|
||||||
company.expMultiplier *
|
|
||||||
worker.mults.hacking_exp *
|
|
||||||
BitNodeMultipliers.CompanyWorkExpGain,
|
|
||||||
strExp:
|
|
||||||
companyPosition.strengthExpGain *
|
|
||||||
company.expMultiplier *
|
|
||||||
worker.mults.strength_exp *
|
|
||||||
BitNodeMultipliers.CompanyWorkExpGain,
|
|
||||||
defExp:
|
|
||||||
companyPosition.defenseExpGain *
|
|
||||||
company.expMultiplier *
|
|
||||||
worker.mults.defense_exp *
|
|
||||||
BitNodeMultipliers.CompanyWorkExpGain,
|
|
||||||
dexExp:
|
|
||||||
companyPosition.dexterityExpGain *
|
|
||||||
company.expMultiplier *
|
|
||||||
worker.mults.dexterity_exp *
|
|
||||||
BitNodeMultipliers.CompanyWorkExpGain,
|
|
||||||
agiExp:
|
|
||||||
companyPosition.agilityExpGain *
|
|
||||||
company.expMultiplier *
|
|
||||||
worker.mults.agility_exp *
|
|
||||||
BitNodeMultipliers.CompanyWorkExpGain,
|
|
||||||
chaExp:
|
|
||||||
companyPosition.charismaExpGain *
|
|
||||||
company.expMultiplier *
|
|
||||||
worker.mults.charisma_exp *
|
|
||||||
BitNodeMultipliers.CompanyWorkExpGain,
|
|
||||||
intExp: 0,
|
|
||||||
};
|
|
||||||
};
|
|
@ -1,23 +0,0 @@
|
|||||||
import { BitNodeMultipliers } from "../../BitNode/BitNodeMultipliers";
|
|
||||||
import { Crime } from "src/Crime/Crime";
|
|
||||||
import { newWorkStats, scaleWorkStats, WorkStats } from "../WorkStats";
|
|
||||||
import { Player } from "@player";
|
|
||||||
|
|
||||||
export const calculateCrimeWorkStats = (crime: Crime): WorkStats => {
|
|
||||||
const gains = scaleWorkStats(
|
|
||||||
newWorkStats({
|
|
||||||
money: crime.money * Player.mults.crime_money,
|
|
||||||
hackExp: crime.hacking_exp * 2 * Player.mults.hacking_exp,
|
|
||||||
strExp: crime.strength_exp * 2 * Player.mults.strength_exp,
|
|
||||||
defExp: crime.defense_exp * 2 * Player.mults.defense_exp,
|
|
||||||
dexExp: crime.dexterity_exp * 2 * Player.mults.dexterity_exp,
|
|
||||||
agiExp: crime.agility_exp * 2 * Player.mults.agility_exp,
|
|
||||||
chaExp: crime.charisma_exp * 2 * Player.mults.charisma_exp,
|
|
||||||
intExp: crime.intelligence_exp * 2,
|
|
||||||
}),
|
|
||||||
BitNodeMultipliers.CrimeExpGain,
|
|
||||||
false,
|
|
||||||
);
|
|
||||||
gains.money *= BitNodeMultipliers.CrimeMoney;
|
|
||||||
return gains;
|
|
||||||
};
|
|
@ -1,55 +0,0 @@
|
|||||||
import { Person } from "../../PersonObjects/Person";
|
|
||||||
import { BitNodeMultipliers } from "../../BitNode/BitNodeMultipliers";
|
|
||||||
import { CONSTANTS } from "../../Constants";
|
|
||||||
import { FactionWorkType } from "../data/FactionWorkType";
|
|
||||||
import { newWorkStats, WorkStats } from "../WorkStats";
|
|
||||||
import {
|
|
||||||
getFactionFieldWorkRepGain,
|
|
||||||
getFactionSecurityWorkRepGain,
|
|
||||||
getHackingWorkRepGain,
|
|
||||||
} from "../../PersonObjects/formulas/reputation";
|
|
||||||
|
|
||||||
const gameCPS = 1000 / CONSTANTS._idleSpeed; // 5 cycles per second
|
|
||||||
|
|
||||||
export const FactionWorkStats: Record<FactionWorkType, WorkStats> = {
|
|
||||||
[FactionWorkType.HACKING]: newWorkStats({ hackExp: 15 }),
|
|
||||||
[FactionWorkType.FIELD]: newWorkStats({
|
|
||||||
hackExp: 10,
|
|
||||||
strExp: 10,
|
|
||||||
defExp: 10,
|
|
||||||
dexExp: 10,
|
|
||||||
agiExp: 10,
|
|
||||||
chaExp: 10,
|
|
||||||
}),
|
|
||||||
[FactionWorkType.SECURITY]: newWorkStats({
|
|
||||||
hackExp: 5,
|
|
||||||
strExp: 15,
|
|
||||||
defExp: 15,
|
|
||||||
dexExp: 15,
|
|
||||||
agiExp: 15,
|
|
||||||
}),
|
|
||||||
};
|
|
||||||
|
|
||||||
export const calculateFactionRep = (person: Person, tpe: FactionWorkType, favor: number): number => {
|
|
||||||
const repFormulas = {
|
|
||||||
[FactionWorkType.HACKING]: getHackingWorkRepGain,
|
|
||||||
[FactionWorkType.FIELD]: getFactionFieldWorkRepGain,
|
|
||||||
[FactionWorkType.SECURITY]: getFactionSecurityWorkRepGain,
|
|
||||||
};
|
|
||||||
return repFormulas[tpe](person, favor);
|
|
||||||
};
|
|
||||||
|
|
||||||
export function calculateFactionExp(person: Person, tpe: FactionWorkType): WorkStats {
|
|
||||||
const baseStats = FactionWorkStats[tpe];
|
|
||||||
return {
|
|
||||||
money: 0,
|
|
||||||
reputation: 0,
|
|
||||||
hackExp: (baseStats.hackExp * person.mults.hacking_exp * BitNodeMultipliers.FactionWorkExpGain) / gameCPS,
|
|
||||||
strExp: (baseStats.strExp * person.mults.strength_exp * BitNodeMultipliers.FactionWorkExpGain) / gameCPS,
|
|
||||||
defExp: (baseStats.defExp * person.mults.defense_exp * BitNodeMultipliers.FactionWorkExpGain) / gameCPS,
|
|
||||||
dexExp: (baseStats.dexExp * person.mults.dexterity_exp * BitNodeMultipliers.FactionWorkExpGain) / gameCPS,
|
|
||||||
agiExp: (baseStats.agiExp * person.mults.agility_exp * BitNodeMultipliers.FactionWorkExpGain) / gameCPS,
|
|
||||||
chaExp: (baseStats.chaExp * person.mults.charisma_exp * BitNodeMultipliers.FactionWorkExpGain) / gameCPS,
|
|
||||||
intExp: 0,
|
|
||||||
};
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user