mirror of
https://github.com/bitburner-official/bitburner-src.git
synced 2024-12-22 22:22:26 +01:00
convert faction work to new work system
This commit is contained in:
parent
e86a42716c
commit
f7805c4a51
@ -19,6 +19,7 @@ import { dialogBoxCreate } from "../ui/React/DialogBox";
|
||||
import { InvitationEvent } from "./ui/InvitationModal";
|
||||
import { FactionNames } from "./data/FactionNames";
|
||||
import { SFC32RNG } from "../Casino/RNG";
|
||||
import { isFactionWork } from "../Work/FactionWork";
|
||||
|
||||
export function inviteToFaction(faction: Faction): void {
|
||||
Player.receiveInvite(faction.name);
|
||||
@ -113,7 +114,7 @@ export function purchaseAugmentation(aug: Augmentation, fac: Faction, sing = fal
|
||||
|
||||
export function processPassiveFactionRepGain(numCycles: number): void {
|
||||
for (const name of Object.keys(Factions)) {
|
||||
if (name === Player.currentWorkFactionName) continue;
|
||||
if (isFactionWork(Player.currentWork) && name === Player.currentWork.factionName) continue;
|
||||
if (!Factions.hasOwnProperty(name)) continue;
|
||||
const faction = Factions[name];
|
||||
if (!faction.isMember) continue;
|
||||
|
@ -1,6 +0,0 @@
|
||||
export enum FactionWorkType {
|
||||
Field,
|
||||
Hacking,
|
||||
None,
|
||||
Security,
|
||||
}
|
@ -21,6 +21,8 @@ import { Typography, Button } from "@mui/material";
|
||||
import { CovenantPurchasesRoot } from "../../PersonObjects/Sleeve/ui/CovenantPurchasesRoot";
|
||||
import { FactionNames } from "../data/FactionNames";
|
||||
import { GangButton } from "./GangButton";
|
||||
import { FactionWork } from "../../Work/FactionWork";
|
||||
import { FactionWorkType } from "../../Work/data/FactionWorkType";
|
||||
|
||||
type IProps = {
|
||||
faction: Faction;
|
||||
@ -67,17 +69,35 @@ function MainPage({ faction, rerender, onAugmentations }: IMainProps): React.Rea
|
||||
}
|
||||
|
||||
function startFieldWork(faction: Faction): void {
|
||||
player.startFactionFieldWork(faction);
|
||||
player.startNEWWork(
|
||||
new FactionWork({
|
||||
singularity: false,
|
||||
faction: faction.name,
|
||||
factionWorkType: FactionWorkType.HACKING,
|
||||
}),
|
||||
);
|
||||
startWork();
|
||||
}
|
||||
|
||||
function startHackingContracts(faction: Faction): void {
|
||||
player.startFactionHackWork(faction);
|
||||
player.startNEWWork(
|
||||
new FactionWork({
|
||||
singularity: false,
|
||||
faction: faction.name,
|
||||
factionWorkType: FactionWorkType.HACKING,
|
||||
}),
|
||||
);
|
||||
startWork();
|
||||
}
|
||||
|
||||
function startSecurityWork(faction: Faction): void {
|
||||
player.startFactionSecurityWork(faction);
|
||||
player.startNEWWork(
|
||||
new FactionWork({
|
||||
singularity: false,
|
||||
faction: faction.name,
|
||||
factionWorkType: FactionWorkType.HACKING,
|
||||
}),
|
||||
);
|
||||
startWork();
|
||||
}
|
||||
|
||||
|
@ -2399,8 +2399,6 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
|
||||
crime_success_mult: Player.crime_success_mult,
|
||||
isWorking: Player.isWorking,
|
||||
workType: Player.workType,
|
||||
currentWorkFactionName: Player.currentWorkFactionName,
|
||||
currentWorkFactionDescription: Player.currentWorkFactionDescription,
|
||||
workHackExpGainRate: Player.workHackExpGainRate,
|
||||
workStrExpGainRate: Player.workStrExpGainRate,
|
||||
workDefExpGainRate: Player.workDefExpGainRate,
|
||||
|
@ -52,6 +52,8 @@ import { FactionNames } from "../Faction/data/FactionNames";
|
||||
import { WorkType } from "../utils/WorkType";
|
||||
import { ClassWork, ClassType } from "../Work/ClassWork";
|
||||
import { CreateProgramWork, isCreateProgramWork } from "../Work/CreateProgramWork";
|
||||
import { FactionWork } from "../Work/FactionWork";
|
||||
import { FactionWorkType } from "../Work/data/FactionWorkType";
|
||||
|
||||
export function NetscriptSingularity(player: IPlayer, workerScript: WorkerScript): InternalAPI<ISingularity> {
|
||||
const getAugmentation = function (_ctx: NetscriptContext, name: string): Augmentation {
|
||||
@ -1033,7 +1035,13 @@ export function NetscriptSingularity(player: IPlayer, workerScript: WorkerScript
|
||||
_ctx.log(() => `Faction '${faction.name}' do not need help with hacking contracts.`);
|
||||
return false;
|
||||
}
|
||||
player.startFactionHackWork(faction);
|
||||
player.startNEWWork(
|
||||
new FactionWork({
|
||||
singularity: true,
|
||||
factionWorkType: FactionWorkType.HACKING,
|
||||
faction: faction.name,
|
||||
}),
|
||||
);
|
||||
if (focus) {
|
||||
player.startFocusing();
|
||||
Router.toWork();
|
||||
@ -1050,7 +1058,13 @@ export function NetscriptSingularity(player: IPlayer, workerScript: WorkerScript
|
||||
_ctx.log(() => `Faction '${faction.name}' do not need help with field missions.`);
|
||||
return false;
|
||||
}
|
||||
player.startFactionFieldWork(faction);
|
||||
player.startNEWWork(
|
||||
new FactionWork({
|
||||
singularity: true,
|
||||
factionWorkType: FactionWorkType.FIELD,
|
||||
faction: faction.name,
|
||||
}),
|
||||
);
|
||||
if (focus) {
|
||||
player.startFocusing();
|
||||
Router.toWork();
|
||||
@ -1067,7 +1081,13 @@ export function NetscriptSingularity(player: IPlayer, workerScript: WorkerScript
|
||||
_ctx.log(() => `Faction '${faction.name}' do not need help with security work.`);
|
||||
return false;
|
||||
}
|
||||
player.startFactionSecurityWork(faction);
|
||||
player.startNEWWork(
|
||||
new FactionWork({
|
||||
singularity: true,
|
||||
factionWorkType: FactionWorkType.SECURITY,
|
||||
faction: faction.name,
|
||||
}),
|
||||
);
|
||||
if (focus) {
|
||||
player.startFocusing();
|
||||
Router.toWork();
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { IPlayer } from "../PersonObjects/IPlayer";
|
||||
import { FactionWorkType } from "../Faction/FactionWorkTypeEnum";
|
||||
import { SleeveTaskType } from "../PersonObjects/Sleeve/SleeveTaskTypesEnum";
|
||||
import { findSleevePurchasableAugs } from "../PersonObjects/Sleeve/SleeveHelpers";
|
||||
import { StaticAugmentations } from "../Augmentation/StaticAugmentations";
|
||||
@ -15,6 +14,7 @@ import {
|
||||
} from "../ScriptEditor/NetscriptDefinitions";
|
||||
import { checkEnum } from "../utils/helpers/checkEnum";
|
||||
import { InternalAPI, NetscriptContext } from "../Netscript/APIWrapper";
|
||||
import { FactionWorkType } from "../Work/data/FactionWorkType";
|
||||
|
||||
export function NetscriptSleeve(player: IPlayer): InternalAPI<ISleeve> {
|
||||
const checkSleeveAPIAccess = function (ctx: NetscriptContext): void {
|
||||
|
@ -125,14 +125,11 @@ export interface IPlayer extends IPerson {
|
||||
bladeburner_success_chance_mult: number;
|
||||
|
||||
currentWork: Work | null;
|
||||
factionWorkType: string;
|
||||
timeNeededToCompleteWork: number;
|
||||
focus: boolean;
|
||||
currentWorkFactionName: string;
|
||||
workType: WorkType;
|
||||
workCostMult: number;
|
||||
workExpMult: number;
|
||||
currentWorkFactionDescription: string;
|
||||
timeWorked: number;
|
||||
workMoneyGained: number;
|
||||
workMoneyGainRate: number;
|
||||
@ -160,7 +157,6 @@ export interface IPlayer extends IPerson {
|
||||
finishNEWWork(cancelled: boolean): void;
|
||||
work(numCycles: number): boolean;
|
||||
workPartTime(numCycles: number): boolean;
|
||||
workForFaction(numCycles: number): boolean;
|
||||
applyForAgentJob(sing?: boolean): boolean;
|
||||
applyForBusinessConsultantJob(sing?: boolean): boolean;
|
||||
applyForBusinessJob(sing?: boolean): boolean;
|
||||
@ -205,11 +201,7 @@ export interface IPlayer extends IPerson {
|
||||
setMoney(amt: number): void;
|
||||
singularityStopWork(): string;
|
||||
startBladeburner(p: any): void;
|
||||
startFactionWork(faction: Faction): void;
|
||||
startCorporation(corpName: string, additionalShares?: number): void;
|
||||
startFactionFieldWork(faction: Faction): void;
|
||||
startFactionHackWork(faction: Faction): void;
|
||||
startFactionSecurityWork(faction: Faction): void;
|
||||
startFocusing(): void;
|
||||
startGang(facName: string, isHacking: boolean): void;
|
||||
startWork(companyName: string): void;
|
||||
@ -226,7 +218,6 @@ export interface IPlayer extends IPerson {
|
||||
updateSkillLevels(): void;
|
||||
gainCodingContractReward(reward: ICodingContractReward, difficulty?: number): string;
|
||||
stopFocusing(): void;
|
||||
finishFactionWork(cancelled: boolean, sing?: boolean): string;
|
||||
finishWork(cancelled: boolean, sing?: boolean): string;
|
||||
cancelationPenalty(): number;
|
||||
finishWorkPartTime(sing?: boolean): string;
|
||||
|
@ -39,7 +39,7 @@ import { cyrb53 } from "../../utils/StringHelperFunctions";
|
||||
import { getRandomInt } from "../../utils/helpers/getRandomInt";
|
||||
import { ITaskTracker } from "../ITaskTracker";
|
||||
import { CONSTANTS } from "../../Constants";
|
||||
import { WorkType, PlayerFactionWorkType } from "../../utils/WorkType";
|
||||
import { WorkType } from "../../utils/WorkType";
|
||||
import { Work } from "src/Work/Work";
|
||||
|
||||
export class PlayerObject implements IPlayer {
|
||||
@ -138,14 +138,11 @@ export class PlayerObject implements IPlayer {
|
||||
bladeburner_success_chance_mult: number;
|
||||
|
||||
currentWork: Work | null;
|
||||
factionWorkType: PlayerFactionWorkType;
|
||||
timeNeededToCompleteWork: number;
|
||||
focus: boolean;
|
||||
currentWorkFactionName: string;
|
||||
workType: WorkType;
|
||||
workCostMult: number;
|
||||
workExpMult: number;
|
||||
currentWorkFactionDescription: string;
|
||||
timeWorked: number;
|
||||
workMoneyGained: number;
|
||||
workMoneyGainRate: number;
|
||||
@ -173,7 +170,6 @@ export class PlayerObject implements IPlayer {
|
||||
finishNEWWork: (cancelled: boolean) => void;
|
||||
work: (numCycles: number) => boolean;
|
||||
workPartTime: (numCycles: number) => boolean;
|
||||
workForFaction: (numCycles: number) => boolean;
|
||||
applyForAgentJob: (sing?: boolean) => boolean;
|
||||
applyForBusinessConsultantJob: (sing?: boolean) => boolean;
|
||||
applyForBusinessJob: (sing?: boolean) => boolean;
|
||||
@ -227,11 +223,7 @@ export class PlayerObject implements IPlayer {
|
||||
setMoney: (amt: number) => void;
|
||||
singularityStopWork: () => string;
|
||||
startBladeburner: (p: any) => void;
|
||||
startFactionWork: (faction: Faction) => void;
|
||||
startCorporation: (corpName: string, additionalShares?: number) => void;
|
||||
startFactionFieldWork: (faction: Faction) => void;
|
||||
startFactionHackWork: (faction: Faction) => void;
|
||||
startFactionSecurityWork: (faction: Faction) => void;
|
||||
startFocusing: () => void;
|
||||
startGang: (facName: string, isHacking: boolean) => void;
|
||||
startWork: (companyName: string) => void;
|
||||
@ -252,7 +244,6 @@ export class PlayerObject implements IPlayer {
|
||||
updateSkillLevels: () => void;
|
||||
gainCodingContractReward: (reward: ICodingContractReward, difficulty?: number) => string;
|
||||
stopFocusing: () => void;
|
||||
finishFactionWork: (cancelled: boolean, sing?: boolean) => string;
|
||||
finishWork: (cancelled: boolean, sing?: boolean) => string;
|
||||
cancelationPenalty: () => number;
|
||||
finishWorkPartTime: (sing?: boolean) => string;
|
||||
@ -377,9 +368,6 @@ export class PlayerObject implements IPlayer {
|
||||
this.workCostMult = 1;
|
||||
this.workExpMult = 1;
|
||||
|
||||
this.currentWorkFactionName = "";
|
||||
this.currentWorkFactionDescription = "";
|
||||
|
||||
this.workHackExpGainRate = 0;
|
||||
this.workStrExpGainRate = 0;
|
||||
this.workDefExpGainRate = 0;
|
||||
@ -505,12 +493,6 @@ export class PlayerObject implements IPlayer {
|
||||
this.finishWorkPartTime = generalMethods.finishWorkPartTime;
|
||||
this.startFocusing = generalMethods.startFocusing;
|
||||
this.stopFocusing = generalMethods.stopFocusing;
|
||||
this.startFactionWork = generalMethods.startFactionWork;
|
||||
this.startFactionHackWork = generalMethods.startFactionHackWork;
|
||||
this.startFactionFieldWork = generalMethods.startFactionFieldWork;
|
||||
this.startFactionSecurityWork = generalMethods.startFactionSecurityWork;
|
||||
this.workForFaction = generalMethods.workForFaction;
|
||||
this.finishFactionWork = generalMethods.finishFactionWork;
|
||||
this.getWorkMoneyGain = generalMethods.getWorkMoneyGain;
|
||||
this.getWorkHackExpGain = generalMethods.getWorkHackExpGain;
|
||||
this.getWorkStrExpGain = generalMethods.getWorkStrExpGain;
|
||||
@ -576,7 +558,6 @@ export class PlayerObject implements IPlayer {
|
||||
this.getUpgradeHomeRamCost = serverMethods.getUpgradeHomeRamCost;
|
||||
this.getUpgradeHomeCoresCost = serverMethods.getUpgradeHomeCoresCost;
|
||||
this.createHacknetServer = serverMethods.createHacknetServer;
|
||||
this.factionWorkType = PlayerFactionWorkType.None;
|
||||
|
||||
this.getMult = generalMethods.getMult;
|
||||
this.setMult = generalMethods.setMult;
|
||||
|
@ -29,11 +29,6 @@ import {
|
||||
ISkillProgress,
|
||||
} from "../formulas/skill";
|
||||
import { calculateIntelligenceBonus } from "../formulas/intelligence";
|
||||
import {
|
||||
getHackingWorkRepGain,
|
||||
getFactionSecurityWorkRepGain,
|
||||
getFactionFieldWorkRepGain,
|
||||
} from "../formulas/reputation";
|
||||
import { GetServer, AddToAllServers, createUniqueRandomIp } from "../../Server/AllServers";
|
||||
import { Server } from "../../Server/Server";
|
||||
import { safetlyCreateUniqueServer } from "../../Server/ServerHelpers";
|
||||
@ -64,7 +59,7 @@ import { ITaskTracker } from "../ITaskTracker";
|
||||
import { IPerson } from "../IPerson";
|
||||
import { Player } from "../../Player";
|
||||
|
||||
import { WorkType, PlayerFactionWorkType } from "../../utils/WorkType";
|
||||
import { WorkType } from "../../utils/WorkType";
|
||||
|
||||
export function init(this: IPlayer): void {
|
||||
/* Initialize Player's home computer */
|
||||
@ -137,8 +132,6 @@ export function prestigeAugmentation(this: PlayerObject): void {
|
||||
}
|
||||
|
||||
this.isWorking = false;
|
||||
this.currentWorkFactionName = "";
|
||||
this.currentWorkFactionDescription = "";
|
||||
|
||||
this.workHackExpGainRate = 0;
|
||||
this.workStrExpGainRate = 0;
|
||||
@ -509,8 +502,7 @@ export function queryStatFromString(this: IPlayer, str: string): number {
|
||||
/******* Working functions *******/
|
||||
export function resetWorkStatus(this: IPlayer, generalType?: WorkType, group?: string, workType?: string): void {
|
||||
if (this.workType !== WorkType.Faction && generalType === this.workType && group === this.companyName) return;
|
||||
if (generalType === this.workType && group === this.currentWorkFactionName && workType === this.factionWorkType)
|
||||
return;
|
||||
if (generalType === this.workType) return;
|
||||
if (this.isWorking) this.singularityStopWork();
|
||||
this.workHackExpGainRate = 0;
|
||||
this.workStrExpGainRate = 0;
|
||||
@ -533,8 +525,6 @@ export function resetWorkStatus(this: IPlayer, generalType?: WorkType, group?: s
|
||||
|
||||
this.timeWorked = 0;
|
||||
|
||||
this.currentWorkFactionName = "";
|
||||
this.currentWorkFactionDescription = "";
|
||||
this.workType = WorkType.None;
|
||||
}
|
||||
|
||||
@ -590,11 +580,7 @@ export function startWork(this: IPlayer, companyName: string): void {
|
||||
export function process(this: IPlayer, router: IRouter, numCycles = 1): void {
|
||||
// Working
|
||||
if (this.isWorking) {
|
||||
if (this.workType === WorkType.Faction) {
|
||||
if (this.workForFaction(numCycles)) {
|
||||
router.toFaction(Factions[this.currentWorkFactionName]);
|
||||
}
|
||||
} else if (this.workType === WorkType.CompanyPartTime) {
|
||||
if (this.workType === WorkType.CompanyPartTime) {
|
||||
if (this.workPartTime(numCycles)) {
|
||||
router.toCity();
|
||||
}
|
||||
@ -855,165 +841,6 @@ export function stopFocusing(this: IPlayer): void {
|
||||
this.focus = false;
|
||||
}
|
||||
|
||||
/* Working for Faction */
|
||||
export function startFactionWork(this: IPlayer, faction: Faction): void {
|
||||
//Update reputation gain rate to account for faction favor
|
||||
let favorMult = 1 + faction.favor / 100;
|
||||
if (isNaN(favorMult)) {
|
||||
favorMult = 1;
|
||||
}
|
||||
this.workRepGainRate *= favorMult;
|
||||
this.workRepGainRate *= BitNodeMultipliers.FactionWorkRepGain;
|
||||
|
||||
this.isWorking = true;
|
||||
this.workType = WorkType.Faction;
|
||||
this.currentWorkFactionName = faction.name;
|
||||
|
||||
this.timeNeededToCompleteWork = CONSTANTS.MillisecondsPer20Hours;
|
||||
}
|
||||
|
||||
export function startFactionHackWork(this: IPlayer, faction: Faction): void {
|
||||
this.resetWorkStatus(WorkType.Faction, faction.name, PlayerFactionWorkType.Hacking);
|
||||
|
||||
this.workHackExpGainRate = 0.15 * this.hacking_exp_mult * BitNodeMultipliers.FactionWorkExpGain;
|
||||
this.workRepGainRate = getHackingWorkRepGain(this, faction);
|
||||
|
||||
this.factionWorkType = PlayerFactionWorkType.Hacking;
|
||||
this.currentWorkFactionDescription = "carrying out hacking contracts";
|
||||
|
||||
this.startFactionWork(faction);
|
||||
}
|
||||
|
||||
export function startFactionFieldWork(this: IPlayer, faction: Faction): void {
|
||||
this.resetWorkStatus(WorkType.Faction, faction.name, PlayerFactionWorkType.Field);
|
||||
|
||||
this.workHackExpGainRate = 0.1 * this.hacking_exp_mult * BitNodeMultipliers.FactionWorkExpGain;
|
||||
this.workStrExpGainRate = 0.1 * this.strength_exp_mult * BitNodeMultipliers.FactionWorkExpGain;
|
||||
this.workDefExpGainRate = 0.1 * this.defense_exp_mult * BitNodeMultipliers.FactionWorkExpGain;
|
||||
this.workDexExpGainRate = 0.1 * this.dexterity_exp_mult * BitNodeMultipliers.FactionWorkExpGain;
|
||||
this.workAgiExpGainRate = 0.1 * this.agility_exp_mult * BitNodeMultipliers.FactionWorkExpGain;
|
||||
this.workChaExpGainRate = 0.1 * this.charisma_exp_mult * BitNodeMultipliers.FactionWorkExpGain;
|
||||
this.workRepGainRate = getFactionFieldWorkRepGain(this, faction);
|
||||
|
||||
this.factionWorkType = PlayerFactionWorkType.Field;
|
||||
this.currentWorkFactionDescription = "carrying out field missions";
|
||||
|
||||
this.startFactionWork(faction);
|
||||
}
|
||||
|
||||
export function startFactionSecurityWork(this: IPlayer, faction: Faction): void {
|
||||
this.resetWorkStatus(WorkType.Faction, faction.name, PlayerFactionWorkType.Security);
|
||||
|
||||
this.workHackExpGainRate = 0.05 * this.hacking_exp_mult * BitNodeMultipliers.FactionWorkExpGain;
|
||||
this.workStrExpGainRate = 0.15 * this.strength_exp_mult * BitNodeMultipliers.FactionWorkExpGain;
|
||||
this.workDefExpGainRate = 0.15 * this.defense_exp_mult * BitNodeMultipliers.FactionWorkExpGain;
|
||||
this.workDexExpGainRate = 0.15 * this.dexterity_exp_mult * BitNodeMultipliers.FactionWorkExpGain;
|
||||
this.workAgiExpGainRate = 0.15 * this.agility_exp_mult * BitNodeMultipliers.FactionWorkExpGain;
|
||||
this.workChaExpGainRate = 0.0 * this.charisma_exp_mult * BitNodeMultipliers.FactionWorkExpGain;
|
||||
this.workRepGainRate = getFactionSecurityWorkRepGain(this, faction);
|
||||
|
||||
this.factionWorkType = PlayerFactionWorkType.Security;
|
||||
this.currentWorkFactionDescription = "performing security detail";
|
||||
|
||||
this.startFactionWork(faction);
|
||||
}
|
||||
|
||||
export function workForFaction(this: IPlayer, numCycles: number): boolean {
|
||||
const faction = Factions[this.currentWorkFactionName];
|
||||
|
||||
if (!faction) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//Constantly update the rep gain rate
|
||||
switch (this.factionWorkType) {
|
||||
case PlayerFactionWorkType.Hacking:
|
||||
this.workRepGainRate = getHackingWorkRepGain(this, faction);
|
||||
break;
|
||||
case PlayerFactionWorkType.Field:
|
||||
this.workRepGainRate = getFactionFieldWorkRepGain(this, faction);
|
||||
break;
|
||||
case PlayerFactionWorkType.Security:
|
||||
this.workRepGainRate = getFactionSecurityWorkRepGain(this, faction);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
this.workRepGainRate *= BitNodeMultipliers.FactionWorkRepGain;
|
||||
|
||||
//Cap the number of cycles being processed to whatever would put you at limit (20 hours)
|
||||
let overMax = false;
|
||||
if (this.timeWorked + CONSTANTS._idleSpeed * numCycles >= CONSTANTS.MillisecondsPer20Hours) {
|
||||
overMax = true;
|
||||
numCycles = Math.round((CONSTANTS.MillisecondsPer20Hours - this.timeWorked) / CONSTANTS._idleSpeed);
|
||||
}
|
||||
this.timeWorked += CONSTANTS._idleSpeed * numCycles;
|
||||
|
||||
this.processWorkEarnings(numCycles);
|
||||
|
||||
//If timeWorked == 20 hours, then finish. You can only work for the faction for 20 hours
|
||||
if (overMax || this.timeWorked >= CONSTANTS.MillisecondsPer20Hours) {
|
||||
this.finishFactionWork(false);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
export function finishFactionWork(this: IPlayer, cancelled: boolean, sing = false): string {
|
||||
const faction = Factions[this.currentWorkFactionName];
|
||||
faction.playerReputation += this.workRepGained;
|
||||
|
||||
this.updateSkillLevels();
|
||||
let res = "";
|
||||
|
||||
if (!sing) {
|
||||
dialogBoxCreate(
|
||||
<>
|
||||
You worked for your faction {faction.name} for a total of {convertTimeMsToTimeElapsedString(this.timeWorked)}{" "}
|
||||
<br />
|
||||
<br />
|
||||
You earned a total of: <br />
|
||||
<Money money={this.workMoneyGained} />
|
||||
<br />
|
||||
<Reputation reputation={this.workRepGained} /> reputation for the faction <br />
|
||||
{numeralWrapper.formatExp(this.workHackExpGained)} hacking exp <br />
|
||||
{numeralWrapper.formatExp(this.workStrExpGained)} strength exp <br />
|
||||
{numeralWrapper.formatExp(this.workDefExpGained)} defense exp <br />
|
||||
{numeralWrapper.formatExp(this.workDexExpGained)} dexterity exp <br />
|
||||
{numeralWrapper.formatExp(this.workAgiExpGained)} agility exp <br />
|
||||
{numeralWrapper.formatExp(this.workChaExpGained)} charisma exp
|
||||
<br />
|
||||
</>,
|
||||
);
|
||||
} else {
|
||||
res =
|
||||
"You worked for your faction " +
|
||||
faction.name +
|
||||
" for a total of " +
|
||||
convertTimeMsToTimeElapsedString(this.timeWorked) +
|
||||
". " +
|
||||
"You earned " +
|
||||
numeralWrapper.formatReputation(this.workRepGained) +
|
||||
" rep, " +
|
||||
numeralWrapper.formatExp(this.workHackExpGained) +
|
||||
" hacking exp, " +
|
||||
numeralWrapper.formatExp(this.workStrExpGained) +
|
||||
" str exp, " +
|
||||
numeralWrapper.formatExp(this.workDefExpGained) +
|
||||
" def exp, " +
|
||||
numeralWrapper.formatExp(this.workDexExpGained) +
|
||||
" dex exp, " +
|
||||
numeralWrapper.formatExp(this.workAgiExpGained) +
|
||||
" agi exp, and " +
|
||||
numeralWrapper.formatExp(this.workChaExpGained) +
|
||||
" cha exp.";
|
||||
}
|
||||
|
||||
this.isWorking = false;
|
||||
this.resetWorkStatus();
|
||||
return res;
|
||||
}
|
||||
|
||||
//Money gained per game cycle
|
||||
export function getWorkMoneyGain(this: IPlayer): number {
|
||||
// If player has SF-11, calculate salary multiplier from favor
|
||||
@ -1220,26 +1047,6 @@ export function getWorkRepGain(this: IPlayer): number {
|
||||
return jobPerformance * this.company_rep_mult * favorMult;
|
||||
}
|
||||
|
||||
// export function getFactionSecurityWorkRepGain(this: IPlayer) {
|
||||
// var t = 0.9 * (this.hacking / CONSTANTS.MaxSkillLevel +
|
||||
// this.strength / CONSTANTS.MaxSkillLevel +
|
||||
// this.defense / CONSTANTS.MaxSkillLevel +
|
||||
// this.dexterity / CONSTANTS.MaxSkillLevel +
|
||||
// this.agility / CONSTANTS.MaxSkillLevel) / 4.5;
|
||||
// return t * this.faction_rep_mult;
|
||||
// }
|
||||
|
||||
// export function getFactionFieldWorkRepGain(this: IPlayer) {
|
||||
// var t = 0.9 * (this.hacking / CONSTANTS.MaxSkillLevel +
|
||||
// this.strength / CONSTANTS.MaxSkillLevel +
|
||||
// this.defense / CONSTANTS.MaxSkillLevel +
|
||||
// this.dexterity / CONSTANTS.MaxSkillLevel +
|
||||
// this.agility / CONSTANTS.MaxSkillLevel +
|
||||
// this.charisma / CONSTANTS.MaxSkillLevel +
|
||||
// this.intelligence / CONSTANTS.MaxSkillLevel) / 5.5;
|
||||
// return t * this.faction_rep_mult;
|
||||
// }
|
||||
|
||||
//Cancels the player's current "work" assignment and gives the proper rewards
|
||||
//Used only for Singularity functions, so no popups are created
|
||||
export function singularityStopWork(this: IPlayer): string {
|
||||
@ -1257,9 +1064,6 @@ export function singularityStopWork(this: IPlayer): string {
|
||||
case WorkType.CompanyPartTime:
|
||||
res = this.finishWorkPartTime(true);
|
||||
break;
|
||||
case WorkType.Faction:
|
||||
res = this.finishFactionWork(true, true);
|
||||
break;
|
||||
default:
|
||||
console.error(`Unrecognized work type (${this.workType})`);
|
||||
return "";
|
||||
|
@ -28,7 +28,6 @@ import { CONSTANTS } from "../../Constants";
|
||||
|
||||
import { Faction } from "../../Faction/Faction";
|
||||
import { Factions } from "../../Faction/Factions";
|
||||
import { FactionWorkType } from "../../Faction/FactionWorkTypeEnum";
|
||||
|
||||
import { CityName } from "../../Locations/data/CityNames";
|
||||
import { LocationName } from "../../Locations/data/LocationNames";
|
||||
@ -37,6 +36,7 @@ import { Generic_fromJSON, Generic_toJSON, Reviver } from "../../utils/JSONReviv
|
||||
import { BladeburnerConstants } from "../../Bladeburner/data/Constants";
|
||||
import { numeralWrapper } from "../../ui/numeralFormat";
|
||||
import { capitalizeFirstLetter, capitalizeEachWord } from "../../utils/StringHelperFunctions";
|
||||
import { FactionWorkType } from "../../Work/data/FactionWorkType";
|
||||
|
||||
export class Sleeve extends Person {
|
||||
/**
|
||||
@ -94,7 +94,7 @@ export class Sleeve extends Person {
|
||||
/**
|
||||
* Keeps track of what type of work sleeve is doing for faction, if applicable
|
||||
*/
|
||||
factionWorkType: FactionWorkType = FactionWorkType.None;
|
||||
factionWorkType: FactionWorkType = FactionWorkType.HACKING;
|
||||
|
||||
/**
|
||||
* Records experience gain rate for the current task
|
||||
@ -444,11 +444,11 @@ export class Sleeve extends Person {
|
||||
}
|
||||
|
||||
switch (this.factionWorkType) {
|
||||
case FactionWorkType.Hacking:
|
||||
case FactionWorkType.HACKING:
|
||||
return this.getFactionHackingWorkRepGain() * (this.shock / 100) * favorMult;
|
||||
case FactionWorkType.Field:
|
||||
case FactionWorkType.FIELD:
|
||||
return this.getFactionFieldWorkRepGain() * (this.shock / 100) * favorMult;
|
||||
case FactionWorkType.Security:
|
||||
case FactionWorkType.SECURITY:
|
||||
return this.getFactionSecurityWorkRepGain() * (this.shock / 100) * favorMult;
|
||||
default:
|
||||
console.warn(`Invalid Sleeve.factionWorkType property in Sleeve.getRepGain(): ${this.factionWorkType}`);
|
||||
@ -660,7 +660,7 @@ export class Sleeve extends Person {
|
||||
this.currentTask = SleeveTaskType.Idle;
|
||||
this.currentTaskTime = 0;
|
||||
this.currentTaskMaxTime = 0;
|
||||
this.factionWorkType = FactionWorkType.None;
|
||||
this.factionWorkType = FactionWorkType.HACKING;
|
||||
this.crimeType = "";
|
||||
this.currentTaskLocation = "";
|
||||
this.gymStatType = "";
|
||||
@ -969,13 +969,13 @@ export class Sleeve extends Person {
|
||||
if (!factionInfo.offerHackingWork) {
|
||||
return false;
|
||||
}
|
||||
this.factionWorkType = FactionWorkType.Hacking;
|
||||
this.factionWorkType = FactionWorkType.HACKING;
|
||||
this.gainRatesForTask.hack = 0.15 * this.hacking_exp_mult * BitNodeMultipliers.FactionWorkExpGain;
|
||||
} else if (sanitizedWorkType.includes("field")) {
|
||||
if (!factionInfo.offerFieldWork) {
|
||||
return false;
|
||||
}
|
||||
this.factionWorkType = FactionWorkType.Field;
|
||||
this.factionWorkType = FactionWorkType.FIELD;
|
||||
this.gainRatesForTask.hack = 0.1 * this.hacking_exp_mult * BitNodeMultipliers.FactionWorkExpGain;
|
||||
this.gainRatesForTask.str = 0.1 * this.strength_exp_mult * BitNodeMultipliers.FactionWorkExpGain;
|
||||
this.gainRatesForTask.def = 0.1 * this.defense_exp_mult * BitNodeMultipliers.FactionWorkExpGain;
|
||||
@ -986,7 +986,7 @@ export class Sleeve extends Person {
|
||||
if (!factionInfo.offerSecurityWork) {
|
||||
return false;
|
||||
}
|
||||
this.factionWorkType = FactionWorkType.Security;
|
||||
this.factionWorkType = FactionWorkType.SECURITY;
|
||||
this.gainRatesForTask.hack = 0.1 * this.hacking_exp_mult * BitNodeMultipliers.FactionWorkExpGain;
|
||||
this.gainRatesForTask.str = 0.15 * this.strength_exp_mult * BitNodeMultipliers.FactionWorkExpGain;
|
||||
this.gainRatesForTask.def = 0.15 * this.defense_exp_mult * BitNodeMultipliers.FactionWorkExpGain;
|
||||
|
@ -1,8 +1,8 @@
|
||||
import { Box, Button, Paper, Tooltip, Typography } from "@mui/material";
|
||||
import React, { useState } from "react";
|
||||
import { FactionWorkType } from "../../../Work/data/FactionWorkType";
|
||||
import { CONSTANTS } from "../../../Constants";
|
||||
import { Crimes } from "../../../Crime/Crimes";
|
||||
import { FactionWorkType } from "../../../Faction/FactionWorkTypeEnum";
|
||||
import { use } from "../../../ui/Context";
|
||||
import { numeralWrapper } from "../../../ui/numeralFormat";
|
||||
import { ProgressBar } from "../../../ui/React/Progress";
|
||||
@ -75,13 +75,13 @@ export function SleeveElem(props: IProps): React.ReactElement {
|
||||
case SleeveTaskType.Faction: {
|
||||
let doing = "nothing";
|
||||
switch (props.sleeve.factionWorkType) {
|
||||
case FactionWorkType.Field:
|
||||
case FactionWorkType.FIELD:
|
||||
doing = "Field work";
|
||||
break;
|
||||
case FactionWorkType.Hacking:
|
||||
case FactionWorkType.HACKING:
|
||||
doing = "Hacking contracts";
|
||||
break;
|
||||
case FactionWorkType.Security:
|
||||
case FactionWorkType.SECURITY:
|
||||
doing = "Security work";
|
||||
break;
|
||||
}
|
||||
|
@ -6,10 +6,10 @@ import { Crimes } from "../../../Crime/Crimes";
|
||||
import { LocationName } from "../../../Locations/data/LocationNames";
|
||||
import { CityName } from "../../../Locations/data/CityNames";
|
||||
import { Factions } from "../../../Faction/Factions";
|
||||
import { FactionWorkType } from "../../../Faction/FactionWorkTypeEnum";
|
||||
import Select, { SelectChangeEvent } from "@mui/material/Select";
|
||||
import MenuItem from "@mui/material/MenuItem";
|
||||
import { FactionNames } from "../../../Faction/data/FactionNames";
|
||||
import { FactionWorkType } from "../../../Work/data/FactionWorkType";
|
||||
|
||||
const universitySelectorOptions: string[] = [
|
||||
"Study Computer Science",
|
||||
@ -254,13 +254,13 @@ function getABC(sleeve: Sleeve): [string, string, string] {
|
||||
case SleeveTaskType.Faction: {
|
||||
let workType = "";
|
||||
switch (sleeve.factionWorkType) {
|
||||
case FactionWorkType.Hacking:
|
||||
case FactionWorkType.HACKING:
|
||||
workType = "Hacking Contracts";
|
||||
break;
|
||||
case FactionWorkType.Field:
|
||||
case FactionWorkType.FIELD:
|
||||
workType = "Field Work";
|
||||
break;
|
||||
case FactionWorkType.Security:
|
||||
case FactionWorkType.SECURITY:
|
||||
workType = "Security Work";
|
||||
break;
|
||||
}
|
||||
|
2
src/ScriptEditor/NetscriptDefinitions.d.ts
vendored
2
src/ScriptEditor/NetscriptDefinitions.d.ts
vendored
@ -49,8 +49,6 @@ interface Player {
|
||||
crime_success_mult: number;
|
||||
isWorking: boolean;
|
||||
workType: string;
|
||||
currentWorkFactionName: string;
|
||||
currentWorkFactionDescription: string;
|
||||
workHackExpGainRate: number;
|
||||
workStrExpGainRate: number;
|
||||
workDefExpGainRate: number;
|
||||
|
@ -1,5 +1,5 @@
|
||||
import React from "react";
|
||||
import { Reviver, Generic_toJSON, Generic_fromJSON } from "../utils/JSONReviver";
|
||||
import { Reviver, Generic_toJSON, Generic_fromJSON, IReviverValue } from "../utils/JSONReviver";
|
||||
import { CONSTANTS } from "../Constants";
|
||||
import { LocationName } from "../Locations/data/LocationNames";
|
||||
import { numeralWrapper } from "../ui/numeralFormat";
|
||||
@ -129,14 +129,12 @@ export class ClassWork extends Work {
|
||||
classType: ClassType;
|
||||
location: LocationName;
|
||||
cyclesWorked: number;
|
||||
singularity: boolean;
|
||||
earnings = newWorkStats();
|
||||
|
||||
constructor(params?: ClassWorkParams) {
|
||||
super(WorkType.CLASS);
|
||||
super(WorkType.CLASS, params?.singularity ?? true);
|
||||
this.classType = params?.classType ?? ClassType.StudyComputerScience;
|
||||
this.location = params?.location ?? LocationName.Sector12RothmanUniversity;
|
||||
this.singularity = params?.singularity ?? false;
|
||||
this.cyclesWorked = 0;
|
||||
}
|
||||
|
||||
@ -186,15 +184,14 @@ export class ClassWork extends Work {
|
||||
/**
|
||||
* Serialize the current object to a JSON save state.
|
||||
*/
|
||||
toJSON(): any {
|
||||
toJSON(): IReviverValue {
|
||||
return Generic_toJSON("ClassWork", this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initiatizes a ClassWork object from a JSON save state.
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
||||
static fromJSON(value: any): ClassWork {
|
||||
static fromJSON(value: IReviverValue): ClassWork {
|
||||
return Generic_fromJSON(ClassWork, value.data);
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { dialogBoxCreate } from "../ui/React/DialogBox";
|
||||
import { Reviver, Generic_toJSON, Generic_fromJSON } from "../utils/JSONReviver";
|
||||
import { Reviver, Generic_toJSON, Generic_fromJSON, IReviverValue } from "../utils/JSONReviver";
|
||||
import { AugmentationNames } from "../Augmentation/data/AugmentationNames";
|
||||
import { CONSTANTS } from "../Constants";
|
||||
import { IPlayer } from "../PersonObjects/IPlayer";
|
||||
@ -20,16 +20,14 @@ export class CreateProgramWork extends Work {
|
||||
programName: string;
|
||||
// amount of cycles spent doing this task
|
||||
cyclesWorked: number;
|
||||
singularity: boolean;
|
||||
// amount of effective work completed on the program (time boosted by skills).
|
||||
unitCompleted: number;
|
||||
|
||||
constructor(params?: CreateProgramWorkParams) {
|
||||
super(WorkType.CREATE_PROGRAM);
|
||||
super(WorkType.CREATE_PROGRAM, params?.singularity ?? true);
|
||||
this.cyclesWorked = 0;
|
||||
this.unitCompleted = 0;
|
||||
this.programName = params?.programName ?? "";
|
||||
this.singularity = params?.singularity ?? false;
|
||||
|
||||
if (params?.player) {
|
||||
const player = params.player;
|
||||
@ -109,15 +107,14 @@ export class CreateProgramWork extends Work {
|
||||
/**
|
||||
* Serialize the current object to a JSON save state.
|
||||
*/
|
||||
toJSON(): any {
|
||||
toJSON(): IReviverValue {
|
||||
return Generic_toJSON("CreateProgramWork", this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initiatizes a CreateProgramWork object from a JSON save state.
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
||||
static fromJSON(value: any): CreateProgramWork {
|
||||
static fromJSON(value: IReviverValue): CreateProgramWork {
|
||||
return Generic_fromJSON(CreateProgramWork, value.data);
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
import React from "react";
|
||||
import { Reviver, Generic_toJSON, Generic_fromJSON } from "../utils/JSONReviver";
|
||||
import { Reviver, Generic_toJSON, Generic_fromJSON, IReviverValue } from "../utils/JSONReviver";
|
||||
import { Crime } from "../Crime/Crime";
|
||||
import { CONSTANTS } from "../Constants";
|
||||
import { determineCrimeSuccess } from "../Crime/CrimeHelpers";
|
||||
@ -21,12 +21,10 @@ export const isCrimeWork = (w: Work | null): w is CrimeWork => w !== null && w.t
|
||||
export class CrimeWork extends Work {
|
||||
crimeType: CrimeType;
|
||||
cyclesWorked: number;
|
||||
singularity: boolean;
|
||||
|
||||
constructor(params?: CrimeWorkParams) {
|
||||
super(WorkType.CRIME);
|
||||
super(WorkType.CRIME, params?.singularity ?? true);
|
||||
this.crimeType = params?.crimeType ?? CrimeType.Shoplift;
|
||||
this.singularity = params?.singularity ?? false;
|
||||
this.cyclesWorked = 0;
|
||||
}
|
||||
|
||||
@ -121,15 +119,14 @@ export class CrimeWork extends Work {
|
||||
/**
|
||||
* Serialize the current object to a JSON save state.
|
||||
*/
|
||||
toJSON(): any {
|
||||
toJSON(): IReviverValue {
|
||||
return Generic_toJSON("CrimeWork", this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initiatizes a CrimeWork object from a JSON save state.
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
||||
static fromJSON(value: any): CrimeWork {
|
||||
static fromJSON(value: IReviverValue): CrimeWork {
|
||||
return Generic_fromJSON(CrimeWork, value.data);
|
||||
}
|
||||
}
|
||||
|
103
src/Work/FactionWork.tsx
Normal file
103
src/Work/FactionWork.tsx
Normal file
@ -0,0 +1,103 @@
|
||||
import React from "react";
|
||||
import { Work, WorkType } from "./Work";
|
||||
import { Reviver, Generic_toJSON, Generic_fromJSON, IReviverValue } from "../utils/JSONReviver";
|
||||
import { IPlayer } from "../PersonObjects/IPlayer";
|
||||
import { FactionNames } from "../Faction/data/FactionNames";
|
||||
import { Factions } from "../Faction/Factions";
|
||||
import { Faction } from "../Faction/Faction";
|
||||
import { applyWorkStats, WorkStats } from "./WorkStats";
|
||||
import { dialogBoxCreate } from "../ui/React/DialogBox";
|
||||
import { Reputation } from "../ui/React/Reputation";
|
||||
import {
|
||||
getFactionFieldWorkRepGain,
|
||||
getFactionSecurityWorkRepGain,
|
||||
getHackingWorkRepGain,
|
||||
} from "../PersonObjects/formulas/reputation";
|
||||
import { CONSTANTS } from "../Constants";
|
||||
import { AugmentationNames } from "../Augmentation/data/AugmentationNames";
|
||||
import { calculateFactionExp } from "./formulas/Faction";
|
||||
import { FactionWorkType } from "./data/FactionWorkType";
|
||||
|
||||
interface FactionWorkParams {
|
||||
singularity: boolean;
|
||||
factionWorkType: FactionWorkType;
|
||||
faction: string;
|
||||
}
|
||||
|
||||
export const isFactionWork = (w: Work | null): w is FactionWork => w !== null && w.type === WorkType.FACTION;
|
||||
|
||||
export class FactionWork extends Work {
|
||||
factionWorkType: FactionWorkType;
|
||||
factionName: string;
|
||||
cyclesWorked: number;
|
||||
|
||||
constructor(params?: FactionWorkParams) {
|
||||
super(WorkType.FACTION, params?.singularity ?? true);
|
||||
this.factionWorkType = params?.factionWorkType ?? FactionWorkType.HACKING;
|
||||
this.factionName = params?.faction ?? FactionNames.Sector12;
|
||||
this.cyclesWorked = 0;
|
||||
}
|
||||
|
||||
getFaction(): Faction {
|
||||
const f = Factions[this.factionName];
|
||||
if (!f) throw new Error(`Faction work started with invalid / unknown faction: '${this.factionName}'`);
|
||||
return f;
|
||||
}
|
||||
|
||||
getReputationRate(player: IPlayer): number {
|
||||
const faction = this.getFaction();
|
||||
const repFormulas = {
|
||||
[FactionWorkType.HACKING]: getHackingWorkRepGain,
|
||||
[FactionWorkType.FIELD]: getFactionFieldWorkRepGain,
|
||||
[FactionWorkType.SECURITY]: getFactionSecurityWorkRepGain,
|
||||
};
|
||||
const rep = repFormulas[this.factionWorkType](player, faction);
|
||||
let focusBonus = 1;
|
||||
if (!player.hasAugmentation(AugmentationNames.NeuroreceptorManager)) {
|
||||
focusBonus = player.focus ? 1 : CONSTANTS.BaseFocusBonus;
|
||||
}
|
||||
return rep * focusBonus;
|
||||
}
|
||||
|
||||
getExpRates(player: IPlayer): WorkStats {
|
||||
return calculateFactionExp(player, this.factionWorkType);
|
||||
}
|
||||
|
||||
process(player: IPlayer, cycles: number): boolean {
|
||||
this.cyclesWorked += cycles;
|
||||
this.getFaction().playerReputation += this.getReputationRate(player) * cycles;
|
||||
|
||||
const rate = this.getExpRates(player);
|
||||
applyWorkStats(player, rate, cycles, "class");
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
finish(): void {
|
||||
if (!this.singularity) {
|
||||
dialogBoxCreate(
|
||||
<>
|
||||
You worked for {this.getFaction().name}.
|
||||
<br />
|
||||
They now have a total of <Reputation reputation={this.getFaction().playerReputation} /> reputation.
|
||||
</>,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Serialize the current object to a JSON save state.
|
||||
*/
|
||||
toJSON(): IReviverValue {
|
||||
return Generic_toJSON("FactionWork", this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initiatizes a FactionWork object from a JSON save state.
|
||||
*/
|
||||
static fromJSON(value: IReviverValue): FactionWork {
|
||||
return Generic_fromJSON(FactionWork, value.data);
|
||||
}
|
||||
}
|
||||
|
||||
Reviver.constructors.FactionWork = FactionWork;
|
@ -7,7 +7,7 @@ import { Work, WorkType } from "./Work";
|
||||
import { graftingIntBonus } from "../PersonObjects/Grafting/GraftingHelpers";
|
||||
import { applyAugmentation } from "../Augmentation/AugmentationHelpers";
|
||||
import { dialogBoxCreate } from "../ui/React/DialogBox";
|
||||
import { Reviver, Generic_toJSON, Generic_fromJSON } from "../utils/JSONReviver";
|
||||
import { Reviver, Generic_toJSON, Generic_fromJSON, IReviverValue } from "../utils/JSONReviver";
|
||||
import { GraftableAugmentation } from "../PersonObjects/Grafting/GraftableAugmentation";
|
||||
import { StaticAugmentations } from "../Augmentation/StaticAugmentations";
|
||||
|
||||
@ -15,22 +15,21 @@ export const isGraftingWork = (w: Work | null): w is GraftingWork => w !== null
|
||||
|
||||
interface GraftingWorkParams {
|
||||
augmentation: string;
|
||||
singularity: boolean;
|
||||
player: IPlayer;
|
||||
singularity: boolean;
|
||||
}
|
||||
|
||||
export class GraftingWork extends Work {
|
||||
augmentation: string;
|
||||
singularity: boolean;
|
||||
cyclesWorked: number;
|
||||
unitCompleted: number;
|
||||
|
||||
constructor(params?: GraftingWorkParams) {
|
||||
super(WorkType.GRAFTING);
|
||||
super(WorkType.GRAFTING, params?.singularity ?? true);
|
||||
this.cyclesWorked = 0;
|
||||
this.unitCompleted = 0;
|
||||
this.augmentation = params?.augmentation ?? AugmentationNames.Targeting1;
|
||||
this.singularity = params?.singularity ?? false;
|
||||
|
||||
if (params?.player) params.player.loseMoney(GraftableAugmentations[this.augmentation].cost, "augmentations");
|
||||
}
|
||||
|
||||
@ -90,15 +89,14 @@ export class GraftingWork extends Work {
|
||||
/**
|
||||
* Serialize the current object to a JSON save state.
|
||||
*/
|
||||
toJSON(): any {
|
||||
toJSON(): IReviverValue {
|
||||
return Generic_toJSON("GraftingWork", this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initiatizes a GraftingWork object from a JSON save state.
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
||||
static fromJSON(value: any): GraftingWork {
|
||||
static fromJSON(value: IReviverValue): GraftingWork {
|
||||
return Generic_fromJSON(GraftingWork, value.data);
|
||||
}
|
||||
}
|
||||
|
@ -1,15 +1,18 @@
|
||||
import { IPlayer } from "src/PersonObjects/IPlayer";
|
||||
import { IPlayer } from "../PersonObjects/IPlayer";
|
||||
import { IReviverValue } from "../utils/JSONReviver";
|
||||
|
||||
export abstract class Work {
|
||||
type: WorkType;
|
||||
singularity: boolean;
|
||||
|
||||
constructor(type: WorkType) {
|
||||
constructor(type: WorkType, singularity: boolean) {
|
||||
this.type = type;
|
||||
this.singularity = singularity;
|
||||
}
|
||||
|
||||
abstract process(player: IPlayer, cycles: number): boolean;
|
||||
abstract finish(player: IPlayer, cancelled: boolean): void;
|
||||
abstract toJSON(): any;
|
||||
abstract toJSON(): IReviverValue;
|
||||
}
|
||||
|
||||
export enum WorkType {
|
||||
@ -17,4 +20,5 @@ export enum WorkType {
|
||||
CLASS = "CLASS",
|
||||
CREATE_PROGRAM = "CREATE_PROGRAM",
|
||||
GRAFTING = "GRAFTING",
|
||||
FACTION = "FACTION",
|
||||
}
|
||||
|
@ -4,7 +4,6 @@ import { IPlayer } from "../PersonObjects/IPlayer";
|
||||
|
||||
export interface WorkStats {
|
||||
money: number;
|
||||
reputation: number;
|
||||
hackExp: number;
|
||||
strExp: number;
|
||||
defExp: number;
|
||||
@ -16,7 +15,6 @@ export interface WorkStats {
|
||||
|
||||
interface newWorkStatsParams {
|
||||
money?: number;
|
||||
reputation?: number;
|
||||
hackExp?: number;
|
||||
strExp?: number;
|
||||
defExp?: number;
|
||||
@ -29,7 +27,6 @@ interface newWorkStatsParams {
|
||||
export const newWorkStats = (params?: newWorkStatsParams): WorkStats => {
|
||||
return {
|
||||
money: params?.money ?? 0,
|
||||
reputation: params?.reputation ?? 0,
|
||||
hackExp: params?.hackExp ?? 0,
|
||||
strExp: params?.strExp ?? 0,
|
||||
defExp: params?.defExp ?? 0,
|
||||
@ -43,7 +40,6 @@ export const newWorkStats = (params?: newWorkStatsParams): WorkStats => {
|
||||
export const sumWorkStats = (w0: WorkStats, w1: WorkStats): WorkStats => {
|
||||
return {
|
||||
money: w0.money + w1.money,
|
||||
reputation: w0.reputation + w1.reputation,
|
||||
hackExp: w0.hackExp + w1.hackExp,
|
||||
strExp: w0.strExp + w1.strExp,
|
||||
defExp: w0.defExp + w1.defExp,
|
||||
@ -57,7 +53,6 @@ export const sumWorkStats = (w0: WorkStats, w1: WorkStats): WorkStats => {
|
||||
export const scaleWorkStats = (w: WorkStats, n: number): WorkStats => {
|
||||
return {
|
||||
money: w.money * n,
|
||||
reputation: w.reputation * n,
|
||||
hackExp: w.hackExp * n,
|
||||
strExp: w.strExp * n,
|
||||
defExp: w.defExp * n,
|
||||
@ -75,7 +70,6 @@ export const applyWorkStats = (player: IPlayer, workStats: WorkStats, cycles: nu
|
||||
}
|
||||
const gains = {
|
||||
money: workStats.money * cycles,
|
||||
reputation: focusBonus * workStats.reputation * cycles,
|
||||
hackExp: focusBonus * workStats.hackExp * cycles,
|
||||
strExp: focusBonus * workStats.strExp * cycles,
|
||||
defExp: focusBonus * workStats.defExp * cycles,
|
||||
|
5
src/Work/data/FactionWorkType.ts
Normal file
5
src/Work/data/FactionWorkType.ts
Normal file
@ -0,0 +1,5 @@
|
||||
export enum FactionWorkType {
|
||||
HACKING = "HACKING",
|
||||
FIELD = "FIELD",
|
||||
SECURITY = "SECURITY",
|
||||
}
|
@ -35,7 +35,6 @@ export function calculateClassEarnings(player: IPlayer, work: ClassWork): WorkSt
|
||||
const chaExp = ((classs.earnings.chaExp * location.expMult) / gameCPS) * hashMult;
|
||||
return {
|
||||
money: cost,
|
||||
reputation: 0,
|
||||
hackExp: hackExp * player.hacking_exp_mult * BitNodeMultipliers.ClassGymExpGain,
|
||||
strExp: strExp * player.strength_exp_mult * BitNodeMultipliers.ClassGymExpGain,
|
||||
defExp: defExp * player.defense_exp_mult * BitNodeMultipliers.ClassGymExpGain,
|
||||
|
40
src/Work/formulas/Faction.ts
Normal file
40
src/Work/formulas/Faction.ts
Normal file
@ -0,0 +1,40 @@
|
||||
import { BitNodeMultipliers } from "../../BitNode/BitNodeMultipliers";
|
||||
import { CONSTANTS } from "../../Constants";
|
||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||
import { FactionWorkType } from "../data/FactionWorkType";
|
||||
import { newWorkStats, WorkStats } from "../WorkStats";
|
||||
|
||||
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 calculateFactionExp(player: IPlayer, tpe: FactionWorkType): WorkStats {
|
||||
const baseStats = FactionWorkStats[tpe];
|
||||
return {
|
||||
money: 0,
|
||||
hackExp: (baseStats.hackExp * player.hacking_exp_mult * BitNodeMultipliers.FactionWorkExpGain) / gameCPS,
|
||||
strExp: (baseStats.strExp * player.strength_exp_mult * BitNodeMultipliers.FactionWorkExpGain) / gameCPS,
|
||||
defExp: (baseStats.defExp * player.defense_exp_mult * BitNodeMultipliers.FactionWorkExpGain) / gameCPS,
|
||||
dexExp: (baseStats.dexExp * player.dexterity_exp_mult * BitNodeMultipliers.FactionWorkExpGain) / gameCPS,
|
||||
agiExp: (baseStats.agiExp * player.agility_exp_mult * BitNodeMultipliers.FactionWorkExpGain) / gameCPS,
|
||||
chaExp: (baseStats.chaExp * player.charisma_exp_mult * BitNodeMultipliers.FactionWorkExpGain) / gameCPS,
|
||||
intExp: 0,
|
||||
};
|
||||
}
|
@ -303,9 +303,6 @@ const Engine: {
|
||||
} else if (Player.isWorking) {
|
||||
Player.focus = true;
|
||||
switch (Player.workType) {
|
||||
case WorkType.Faction:
|
||||
Player.workForFaction(numCyclesOffline);
|
||||
break;
|
||||
case WorkType.CompanyPartTime:
|
||||
Player.workPartTime(numCyclesOffline);
|
||||
break;
|
||||
|
@ -87,6 +87,7 @@ import { BypassWrapper } from "./React/BypassWrapper";
|
||||
import _wrap from "lodash/wrap";
|
||||
import _functions from "lodash/functions";
|
||||
import { Apr1 } from "./Apr1";
|
||||
import { isFactionWork } from "../Work/FactionWork";
|
||||
|
||||
const htmlLocation = location;
|
||||
|
||||
@ -165,7 +166,7 @@ export function GameRoot({ player, engine, terminal }: IProps): React.ReactEleme
|
||||
const setRerender = useState(0)[1];
|
||||
const [augPage, setAugPage] = useState<boolean>(false);
|
||||
const [faction, setFaction] = useState<Faction>(
|
||||
player.currentWorkFactionName ? Factions[player.currentWorkFactionName] : (undefined as unknown as Faction),
|
||||
isFactionWork(player.currentWork) ? Factions[player.currentWork.factionName] : (undefined as unknown as Faction),
|
||||
);
|
||||
if (faction === undefined && page === Page.Faction)
|
||||
throw new Error("Trying to go to a page without the proper setup");
|
||||
|
@ -31,6 +31,8 @@ import { isClassWork } from "../../Work/ClassWork";
|
||||
import { CONSTANTS } from "../../Constants";
|
||||
import { isCreateProgramWork } from "../../Work/CreateProgramWork";
|
||||
import { isGraftingWork } from "../../Work/GraftingWork";
|
||||
import { isFactionWork } from "../../Work/FactionWork";
|
||||
import { ReputationRate } from "./ReputationRate";
|
||||
|
||||
interface IProps {
|
||||
save: () => void;
|
||||
@ -172,6 +174,22 @@ function Work(): React.ReactElement {
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
if (isFactionWork(player.currentWork)) {
|
||||
const factionWork = player.currentWork;
|
||||
header = (
|
||||
<>
|
||||
Working for <strong>{factionWork.factionName}</strong>
|
||||
</>
|
||||
);
|
||||
innerText = (
|
||||
<>
|
||||
<Reputation reputation={factionWork.getFaction().playerReputation} /> rep
|
||||
<br />(
|
||||
<ReputationRate reputation={factionWork.getReputationRate(player) * (1000 / CONSTANTS._idleSpeed)} />)
|
||||
</>
|
||||
);
|
||||
}
|
||||
switch (player.workType) {
|
||||
case WorkType.CompanyPartTime:
|
||||
case WorkType.Company:
|
||||
@ -191,23 +209,6 @@ function Work(): React.ReactElement {
|
||||
</>
|
||||
);
|
||||
break;
|
||||
case WorkType.Faction:
|
||||
details = (
|
||||
<>
|
||||
{player.factionWorkType} for <strong>{player.currentWorkFactionName}</strong>
|
||||
</>
|
||||
);
|
||||
header = (
|
||||
<>
|
||||
Working for <strong>{player.currentWorkFactionName}</strong>
|
||||
</>
|
||||
);
|
||||
innerText = (
|
||||
<>
|
||||
+<Reputation reputation={player.workRepGained} /> rep
|
||||
</>
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
||||
return (
|
||||
|
@ -6,7 +6,6 @@ import React, { useEffect, useState } from "react";
|
||||
import { Companies } from "../Company/Companies";
|
||||
import { Company } from "../Company/Company";
|
||||
import { CONSTANTS } from "../Constants";
|
||||
import { Factions } from "../Faction/Factions";
|
||||
import { LocationName } from "../Locations/data/LocationNames";
|
||||
import { Locations } from "../Locations/Locations";
|
||||
import { Settings } from "../Settings/Settings";
|
||||
@ -22,9 +21,11 @@ import { StatsRow } from "./React/StatsRow";
|
||||
import { WorkType } from "../utils/WorkType";
|
||||
import { isCrimeWork } from "../Work/CrimeWork";
|
||||
import { isClassWork } from "../Work/ClassWork";
|
||||
import { WorkStats } from "../Work/WorkStats";
|
||||
import { newWorkStats, WorkStats } from "../Work/WorkStats";
|
||||
import { isCreateProgramWork } from "../Work/CreateProgramWork";
|
||||
import { isGraftingWork } from "../Work/GraftingWork";
|
||||
import { isFactionWork } from "../Work/FactionWork";
|
||||
import { FactionWorkType } from "../Work/data/FactionWorkType";
|
||||
|
||||
const CYCLES_PER_SEC = 1000 / CONSTANTS.MilliPerCycle;
|
||||
|
||||
@ -47,81 +48,69 @@ interface IWorkInfo {
|
||||
stopTooltip?: string | React.ReactElement;
|
||||
}
|
||||
|
||||
export function ExpRows(total: WorkStats, rate: WorkStats): React.ReactElement[] {
|
||||
export function ExpRows(rate: WorkStats): React.ReactElement[] {
|
||||
return [
|
||||
total.hackExp > 0 ? (
|
||||
rate.hackExp > 0 ? (
|
||||
<StatsRow
|
||||
name="Hacking Exp"
|
||||
color={Settings.theme.hack}
|
||||
data={{
|
||||
content: `${numeralWrapper.formatExp(total.hackExp)} (${numeralWrapper.formatExp(
|
||||
rate.hackExp * CYCLES_PER_SEC,
|
||||
)} / sec)`,
|
||||
content: `${numeralWrapper.formatExp(rate.hackExp * CYCLES_PER_SEC)} / sec`,
|
||||
}}
|
||||
/>
|
||||
) : (
|
||||
<></>
|
||||
),
|
||||
total.strExp > 0 ? (
|
||||
rate.strExp > 0 ? (
|
||||
<StatsRow
|
||||
name="Strength Exp"
|
||||
color={Settings.theme.combat}
|
||||
data={{
|
||||
content: `${numeralWrapper.formatExp(total.strExp)} (${numeralWrapper.formatExp(
|
||||
rate.strExp * CYCLES_PER_SEC,
|
||||
)} / sec)`,
|
||||
content: `${numeralWrapper.formatExp(rate.strExp * CYCLES_PER_SEC)} / sec`,
|
||||
}}
|
||||
/>
|
||||
) : (
|
||||
<></>
|
||||
),
|
||||
total.defExp > 0 ? (
|
||||
rate.defExp > 0 ? (
|
||||
<StatsRow
|
||||
name="Defense Exp"
|
||||
color={Settings.theme.combat}
|
||||
data={{
|
||||
content: `${numeralWrapper.formatExp(total.defExp)} (${numeralWrapper.formatExp(
|
||||
rate.defExp * CYCLES_PER_SEC,
|
||||
)} / sec)`,
|
||||
content: `${numeralWrapper.formatExp(rate.defExp * CYCLES_PER_SEC)} / sec`,
|
||||
}}
|
||||
/>
|
||||
) : (
|
||||
<></>
|
||||
),
|
||||
total.dexExp > 0 ? (
|
||||
rate.dexExp > 0 ? (
|
||||
<StatsRow
|
||||
name="Dexterity Exp"
|
||||
color={Settings.theme.combat}
|
||||
data={{
|
||||
content: `${numeralWrapper.formatExp(total.dexExp)} (${numeralWrapper.formatExp(
|
||||
rate.dexExp * CYCLES_PER_SEC,
|
||||
)} / sec)`,
|
||||
content: `${numeralWrapper.formatExp(rate.dexExp * CYCLES_PER_SEC)} / sec`,
|
||||
}}
|
||||
/>
|
||||
) : (
|
||||
<></>
|
||||
),
|
||||
total.agiExp > 0 ? (
|
||||
rate.agiExp > 0 ? (
|
||||
<StatsRow
|
||||
name="Agility Exp"
|
||||
color={Settings.theme.combat}
|
||||
data={{
|
||||
content: `${numeralWrapper.formatExp(total.agiExp)} (${numeralWrapper.formatExp(
|
||||
rate.agiExp * CYCLES_PER_SEC,
|
||||
)} / sec)`,
|
||||
content: `${numeralWrapper.formatExp(rate.agiExp * CYCLES_PER_SEC)} / sec`,
|
||||
}}
|
||||
/>
|
||||
) : (
|
||||
<></>
|
||||
),
|
||||
total.chaExp > 0 ? (
|
||||
rate.chaExp > 0 ? (
|
||||
<StatsRow
|
||||
name="Charisma Exp"
|
||||
color={Settings.theme.cha}
|
||||
data={{
|
||||
content: `${numeralWrapper.formatExp(total.chaExp)} (${numeralWrapper.formatExp(
|
||||
rate.chaExp * CYCLES_PER_SEC,
|
||||
)} / sec)`,
|
||||
content: `${numeralWrapper.formatExp(rate.chaExp * CYCLES_PER_SEC)} / sec`,
|
||||
}}
|
||||
/>
|
||||
) : (
|
||||
@ -276,7 +265,7 @@ export function WorkInProgressRoot(): React.ReactElement {
|
||||
}
|
||||
|
||||
const rates = classWork.calculateRates(player);
|
||||
expGains = ExpRows(classWork.earnings, rates);
|
||||
expGains = ExpRows(rates);
|
||||
workInfo = {
|
||||
buttons: {
|
||||
cancel: cancel,
|
||||
@ -373,18 +362,16 @@ export function WorkInProgressRoot(): React.ReactElement {
|
||||
),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
switch (player.workType) {
|
||||
case WorkType.Faction: {
|
||||
const faction = Factions[player.currentWorkFactionName];
|
||||
if (isFactionWork(player.currentWork)) {
|
||||
const faction = player.currentWork.getFaction();
|
||||
if (!faction) {
|
||||
workInfo = {
|
||||
buttons: {
|
||||
cancel: () => router.toFactions(),
|
||||
},
|
||||
title:
|
||||
`You have not joined ${player.currentWorkFactionName || "(Faction not found)"} at this time,` +
|
||||
`You have not joined ${player.currentWork.factionName || "(Faction not found)"} at this time,` +
|
||||
" please try again if you think this should have worked",
|
||||
|
||||
stopText: "Back to Factions",
|
||||
@ -393,13 +380,21 @@ export function WorkInProgressRoot(): React.ReactElement {
|
||||
|
||||
function cancel(): void {
|
||||
router.toFaction(faction);
|
||||
player.finishFactionWork(true);
|
||||
player.finishNEWWork(true);
|
||||
}
|
||||
function unfocus(): void {
|
||||
router.toFaction(faction);
|
||||
player.stopFocusing();
|
||||
}
|
||||
|
||||
const description = {
|
||||
[FactionWorkType.HACKING]: "carrying out hacking contracts",
|
||||
[FactionWorkType.FIELD]: "carrying out field missions",
|
||||
[FactionWorkType.SECURITY]: "performing security detail",
|
||||
};
|
||||
|
||||
const exp = player.currentWork.getExpRates(player);
|
||||
|
||||
workInfo = {
|
||||
buttons: {
|
||||
cancel: cancel,
|
||||
@ -407,44 +402,27 @@ export function WorkInProgressRoot(): React.ReactElement {
|
||||
},
|
||||
title: (
|
||||
<>
|
||||
You are currently {player.currentWorkFactionDescription} for your faction <b>{faction.name}</b>
|
||||
You are currently {description[player.currentWork.factionWorkType]} for <b>{faction.name}</b>
|
||||
</>
|
||||
),
|
||||
|
||||
description: (
|
||||
<>
|
||||
Current Faction Reputation: <Reputation reputation={faction.playerReputation} />
|
||||
Current Faction Reputation: <Reputation reputation={faction.playerReputation} /> (
|
||||
<ReputationRate reputation={player.currentWork.getReputationRate(player) * CYCLES_PER_SEC} />)
|
||||
</>
|
||||
),
|
||||
gains: [
|
||||
player.workMoneyGained > 0 ? (
|
||||
<StatsRow name="Money" color={Settings.theme.money}>
|
||||
<Typography>
|
||||
<Money money={player.workMoneyGained} /> (
|
||||
<MoneyRate money={player.workMoneyGainRate * CYCLES_PER_SEC} />)
|
||||
</Typography>
|
||||
</StatsRow>
|
||||
) : (
|
||||
<></>
|
||||
),
|
||||
<StatsRow name="Faction Reputation" color={Settings.theme.rep}>
|
||||
<Typography>
|
||||
<Reputation reputation={player.workRepGained} /> (
|
||||
<ReputationRate reputation={player.workRepGainRate * CYCLES_PER_SEC} />)
|
||||
</Typography>
|
||||
</StatsRow>,
|
||||
...expGains,
|
||||
],
|
||||
gains: ExpRows(exp),
|
||||
progress: {
|
||||
elapsed: player.timeWorked,
|
||||
elapsed: player.currentWork.cyclesWorked * CONSTANTS._idleSpeed,
|
||||
},
|
||||
|
||||
stopText: "Stop Faction work",
|
||||
};
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
switch (player.workType) {
|
||||
case WorkType.Company: {
|
||||
const comp = Companies[player.companyName];
|
||||
if (comp == null || !(comp instanceof Company)) {
|
||||
|
@ -9,29 +9,6 @@ export enum WorkType {
|
||||
GraftAugmentation = "Grafting an Augmentation",
|
||||
}
|
||||
|
||||
export enum PlayerFactionWorkType {
|
||||
None = "",
|
||||
Hacking = "Faction Hacking Work",
|
||||
Field = "Faction Field Work",
|
||||
Security = "Faction Security Work",
|
||||
}
|
||||
|
||||
export enum ClassType {
|
||||
None = "",
|
||||
StudyComputerScience = "studying Computer Science",
|
||||
DataStructures = "taking a Data Structures course",
|
||||
Networks = "taking a Networks course",
|
||||
Algorithms = "taking an Algorithms course",
|
||||
|
||||
Management = "taking a Management course",
|
||||
Leadership = "taking a Leadership course",
|
||||
|
||||
GymStrength = "training your strength at a gym",
|
||||
GymDefense = "training your defense at a gym",
|
||||
GymDexterity = "training your dexterity at a gym",
|
||||
GymAgility = "training your agility at a gym",
|
||||
}
|
||||
|
||||
export enum CrimeType {
|
||||
None = "",
|
||||
Shoplift = "shoplift",
|
||||
|
Loading…
Reference in New Issue
Block a user