Convert crime to new work model

This commit is contained in:
Olivier Gagnon
2022-07-07 02:00:23 -04:00
parent 7d263e4223
commit 3ee7d593d0
12 changed files with 238 additions and 292 deletions
+5 -18
View File
@@ -32,6 +32,7 @@ import { ISkillProgress } from "./formulas/skill";
import { PlayerAchievement } from "../Achievements/Achievements";
import { IPerson } from "./IPerson";
import { WorkType, ClassType, CrimeType } from "../utils/WorkType";
import { Work } from "src/Work/Work";
export interface IPlayer extends IPerson {
bitNodeN: number;
@@ -124,15 +125,13 @@ export interface IPlayer extends IPerson {
bladeburner_analysis_mult: number;
bladeburner_success_chance_mult: number;
currentWork: Work | null;
createProgramReqLvl: number;
factionWorkType: string;
createProgramName: string;
timeWorkedCreateProgram: number;
graftAugmentationName: string;
timeWorkedGraftAugmentation: number;
crimeType: CrimeType;
committingCrimeThruSingFn: boolean;
singFnCrimeWorkerScript: WorkerScript | null;
timeNeededToCompleteWork: number;
focus: boolean;
className: ClassType;
@@ -163,6 +162,9 @@ export interface IPlayer extends IPerson {
entropy: number;
// Methods
startNEWWork(w: Work): void;
processNEWWork(cycles: number): void;
finishNEWWork(cancelled: boolean): void;
work(numCycles: number): boolean;
workPartTime(numCycles: number): boolean;
workForFaction(numCycles: number): boolean;
@@ -213,19 +215,6 @@ export interface IPlayer extends IPerson {
startFactionWork(faction: Faction): void;
startClass(costMult: number, expMult: number, className: ClassType): void;
startCorporation(corpName: string, additionalShares?: number): void;
startCrime(
router: IRouter,
crimeType: CrimeType,
hackExp: number,
strExp: number,
defExp: number,
dexExp: number,
agiExp: number,
chaExp: number,
money: number,
time: number,
singParams: any,
): void;
startFactionFieldWork(faction: Faction): void;
startFactionHackWork(faction: Faction): void;
startFactionSecurityWork(faction: Faction): void;
@@ -251,7 +240,6 @@ export interface IPlayer extends IPerson {
finishWork(cancelled: boolean, sing?: boolean): string;
cancelationPenalty(): number;
finishWorkPartTime(sing?: boolean): string;
finishCrime(cancelled: boolean): string;
finishCreateProgramWork(cancelled: boolean): string;
resetMultipliers(): void;
prestigeAugmentation(): void;
@@ -270,7 +258,6 @@ export interface IPlayer extends IPerson {
hospitalize(): void;
createProgramWork(numCycles: number): boolean;
takeClass(numCycles: number): boolean;
commitCrime(numCycles: number): boolean;
checkForFactionInvitations(): Faction[];
setBitNodeNumber(n: number): void;
getMult(name: string): number;
+11 -25
View File
@@ -4,6 +4,7 @@ import * as corporationMethods from "./PlayerObjectCorporationMethods";
import * as gangMethods from "./PlayerObjectGangMethods";
import * as generalMethods from "./PlayerObjectGeneralMethods";
import * as serverMethods from "./PlayerObjectServerMethods";
import * as workMethods from "./PlayerObjectWorkMethods";
import { IMap } from "../../types";
import { Sleeve } from "../Sleeve/Sleeve";
@@ -40,6 +41,7 @@ import { getRandomInt } from "../../utils/helpers/getRandomInt";
import { ITaskTracker } from "../ITaskTracker";
import { CONSTANTS } from "../../Constants";
import { WorkType, ClassType, CrimeType, PlayerFactionWorkType } from "../../utils/WorkType";
import { Work } from "src/Work/Work";
export class PlayerObject implements IPlayer {
// Class members
@@ -136,15 +138,13 @@ export class PlayerObject implements IPlayer {
bladeburner_analysis_mult: number;
bladeburner_success_chance_mult: number;
currentWork: Work | null;
createProgramReqLvl: number;
factionWorkType: PlayerFactionWorkType;
createProgramName: string;
timeWorkedCreateProgram: number;
graftAugmentationName: string;
timeWorkedGraftAugmentation: number;
crimeType: CrimeType;
committingCrimeThruSingFn: boolean;
singFnCrimeWorkerScript: WorkerScript | null;
timeNeededToCompleteWork: number;
focus: boolean;
className: ClassType;
@@ -175,6 +175,9 @@ export class PlayerObject implements IPlayer {
entropy: number;
// Methods
startNEWWork: (w: Work) => void;
processNEWWork: (cycles: number) => void;
finishNEWWork: (cancelled: boolean) => void;
work: (numCycles: number) => boolean;
workPartTime: (numCycles: number) => boolean;
workForFaction: (numCycles: number) => boolean;
@@ -234,19 +237,6 @@ export class PlayerObject implements IPlayer {
startFactionWork: (faction: Faction) => void;
startClass: (costMult: number, expMult: number, className: ClassType) => void;
startCorporation: (corpName: string, additionalShares?: number) => void;
startCrime: (
router: IRouter,
crimeType: CrimeType,
hackExp: number,
strExp: number,
defExp: number,
dexExp: number,
agiExp: number,
chaExp: number,
money: number,
time: number,
singParams: any,
) => void;
startFactionFieldWork: (faction: Faction) => void;
startFactionHackWork: (faction: Faction) => void;
startFactionSecurityWork: (faction: Faction) => void;
@@ -276,7 +266,6 @@ export class PlayerObject implements IPlayer {
finishWork: (cancelled: boolean, sing?: boolean) => string;
cancelationPenalty: () => number;
finishWorkPartTime: (sing?: boolean) => string;
finishCrime: (cancelled: boolean) => string;
finishCreateProgramWork: (cancelled: boolean) => string;
resetMultipliers: () => void;
prestigeAugmentation: () => void;
@@ -296,7 +285,6 @@ export class PlayerObject implements IPlayer {
hospitalize: () => void;
createProgramWork: (numCycles: number) => boolean;
takeClass: (numCycles: number) => boolean;
commitCrime: (numCycles: number) => boolean;
checkForFactionInvitations: () => Faction[];
setBitNodeNumber: (n: number) => void;
getMult: (name: string) => number;
@@ -435,8 +423,6 @@ export class PlayerObject implements IPlayer {
this.className = ClassType.None;
this.crimeType = CrimeType.None;
this.timeWorked = 0; //in m;
this.timeWorkedCreateProgram = 0;
this.timeNeededToCompleteWork = 0;
@@ -495,6 +481,8 @@ export class PlayerObject implements IPlayer {
this.achievements = [];
this.terminalCommandHistory = [];
this.currentWork = null;
// Let's get a hash of some semi-random stuff so we have something unique.
this.identifier = cyrb53(
"I-" +
@@ -532,6 +520,9 @@ export class PlayerObject implements IPlayer {
this.processWorkEarnings = generalMethods.processWorkEarnings;
this.startWork = generalMethods.startWork;
this.cancelationPenalty = generalMethods.cancelationPenalty;
this.startNEWWork = workMethods.start;
this.processNEWWork = workMethods.process;
this.finishNEWWork = workMethods.finish;
this.work = generalMethods.work;
this.finishWork = generalMethods.finishWork;
this.startWorkPartTime = generalMethods.startWorkPartTime;
@@ -563,9 +554,6 @@ export class PlayerObject implements IPlayer {
this.startClass = generalMethods.startClass;
this.takeClass = generalMethods.takeClass;
this.finishClass = generalMethods.finishClass;
this.startCrime = generalMethods.startCrime;
this.commitCrime = generalMethods.commitCrime;
this.finishCrime = generalMethods.finishCrime;
this.singularityStopWork = generalMethods.singularityStopWork;
this.takeDamage = generalMethods.takeDamage;
this.regenerateHp = generalMethods.regenerateHp;
@@ -623,8 +611,6 @@ export class PlayerObject implements IPlayer {
this.getUpgradeHomeCoresCost = serverMethods.getUpgradeHomeCoresCost;
this.createHacknetServer = serverMethods.createHacknetServer;
this.factionWorkType = PlayerFactionWorkType.None;
this.committingCrimeThruSingFn = false;
this.singFnCrimeWorkerScript = null;
this.getMult = generalMethods.getMult;
this.setMult = generalMethods.setMult;
@@ -146,7 +146,6 @@ export function prestigeAugmentation(this: PlayerObject): void {
this.currentWorkFactionDescription = "";
this.createProgramName = "";
this.className = ClassType.None;
this.crimeType = CrimeType.None;
this.workHackExpGainRate = 0;
this.workStrExpGainRate = 0;
@@ -615,10 +614,6 @@ export function process(this: IPlayer, router: IRouter, numCycles = 1): void {
if (this.takeClass(numCycles)) {
router.toCity();
}
} else if (this.workType === WorkType.Crime) {
if (this.commitCrime(numCycles)) {
router.toLocation(Locations[LocationName.Slums]);
}
} else if (this.workType === WorkType.CompanyPartTime) {
if (this.workPartTime(numCycles)) {
router.toCity();
@@ -1330,10 +1325,7 @@ export function finishCreateProgramWork(this: IPlayer, cancelled: boolean): stri
if (!cancelled) {
//Complete case
this.gainIntelligenceExp((CONSTANTS.IntelligenceProgramBaseExpGain * this.timeWorked) / 1000);
const lines = [
`You've finished creating ${programName}!`,
"The new program can be found on your home computer.",
];
const lines = [`You've finished creating ${programName}!`, "The new program can be found on your home computer."];
dialogBoxCreate(lines.join("<br>"));
message = lines.join(" ");
@@ -1501,196 +1493,6 @@ export function finishClass(this: IPlayer, sing = false): string {
return "";
}
//The EXP and $ gains are hardcoded. Time is in ms
export function startCrime(
this: IPlayer,
router: IRouter,
crimeType: CrimeType,
hackExp: number,
strExp: number,
defExp: number,
dexExp: number,
agiExp: number,
chaExp: number,
money: number,
time: number,
workerscript: WorkerScript | null = null,
): void {
this.crimeType = crimeType;
this.resetWorkStatus();
this.isWorking = true;
this.focus = true;
this.workType = WorkType.Crime;
if (workerscript !== null) {
this.committingCrimeThruSingFn = true;
this.singFnCrimeWorkerScript = workerscript;
}
this.workHackExpGained = hackExp * this.hacking_exp_mult * BitNodeMultipliers.CrimeExpGain;
this.workStrExpGained = strExp * this.strength_exp_mult * BitNodeMultipliers.CrimeExpGain;
this.workDefExpGained = defExp * this.defense_exp_mult * BitNodeMultipliers.CrimeExpGain;
this.workDexExpGained = dexExp * this.dexterity_exp_mult * BitNodeMultipliers.CrimeExpGain;
this.workAgiExpGained = agiExp * this.agility_exp_mult * BitNodeMultipliers.CrimeExpGain;
this.workChaExpGained = chaExp * this.charisma_exp_mult * BitNodeMultipliers.CrimeExpGain;
this.workMoneyGained = money * this.crime_money_mult * BitNodeMultipliers.CrimeMoney;
this.timeNeededToCompleteWork = time;
router.toWork();
}
export function commitCrime(this: IPlayer, numCycles: number): boolean {
this.timeWorked += CONSTANTS._idleSpeed * numCycles;
if (this.timeWorked >= this.timeNeededToCompleteWork) {
this.finishCrime(false);
return true;
}
return false;
}
export function finishCrime(this: IPlayer, cancelled: boolean): string {
//Determine crime success/failure
if (!cancelled) {
if (determineCrimeSuccess(this, this.crimeType)) {
//Handle Karma and crime statistics
let crime = null;
for (const i of Object.keys(Crimes)) {
if (Crimes[i].type == this.crimeType) {
crime = Crimes[i];
break;
}
}
if (crime == null) {
dialogBoxCreate(
`ERR: Unrecognized crime type (${this.crimeType}). This is probably a bug please contact the developer`,
);
return "";
}
this.gainMoney(this.workMoneyGained, "crime");
this.karma -= crime.karma;
this.numPeopleKilled += crime.kills;
if (crime.intelligence_exp > 0) {
this.gainIntelligenceExp(crime.intelligence_exp);
}
//On a crime success, gain 2x exp
this.workHackExpGained *= 2;
this.workStrExpGained *= 2;
this.workDefExpGained *= 2;
this.workDexExpGained *= 2;
this.workAgiExpGained *= 2;
this.workChaExpGained *= 2;
const ws = this.singFnCrimeWorkerScript;
if (this.committingCrimeThruSingFn && ws !== null) {
if (ws.disableLogs.ALL == null && ws.disableLogs.commitCrime == null) {
ws.scriptRef.log(
"SUCCESS: Crime successful! Gained " +
numeralWrapper.formatMoney(this.workMoneyGained) +
", " +
numeralWrapper.formatExp(this.workHackExpGained) +
" hack 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, " +
numeralWrapper.formatExp(this.workChaExpGained) +
" cha exp.",
);
}
} else {
dialogBoxCreate(
<>
Crime successful!
<br />
<br />
You gained:
<br />
<Money money={this.workMoneyGained} />
<br />
{numeralWrapper.formatExp(this.workHackExpGained)} hacking experience <br />
{numeralWrapper.formatExp(this.workStrExpGained)} strength experience
<br />
{numeralWrapper.formatExp(this.workDefExpGained)} defense experience
<br />
{numeralWrapper.formatExp(this.workDexExpGained)} dexterity experience
<br />
{numeralWrapper.formatExp(this.workAgiExpGained)} agility experience
<br />
{numeralWrapper.formatExp(this.workChaExpGained)} charisma experience
</>,
);
}
} else {
//Exp halved on failure
this.workHackExpGained /= 2;
this.workStrExpGained /= 2;
this.workDefExpGained /= 2;
this.workDexExpGained /= 2;
this.workAgiExpGained /= 2;
this.workChaExpGained /= 2;
const ws = this.singFnCrimeWorkerScript;
if (this.committingCrimeThruSingFn && ws !== null) {
if (ws.disableLogs.ALL == null && ws.disableLogs.commitCrime == null) {
ws.scriptRef.log(
"FAIL: Crime failed! Gained " +
numeralWrapper.formatExp(this.workHackExpGained) +
" hack 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, " +
numeralWrapper.formatExp(this.workChaExpGained) +
" cha exp.",
);
}
} else {
dialogBoxCreate(
<>
Crime failed!
<br />
<br />
You gained:
<br />
{numeralWrapper.formatExp(this.workHackExpGained)} hacking experience <br />
{numeralWrapper.formatExp(this.workStrExpGained)} strength experience
<br />
{numeralWrapper.formatExp(this.workDefExpGained)} defense experience
<br />
{numeralWrapper.formatExp(this.workDexExpGained)} dexterity experience
<br />
{numeralWrapper.formatExp(this.workAgiExpGained)} agility experience
<br />
{numeralWrapper.formatExp(this.workChaExpGained)} charisma experience
</>,
);
}
}
this.gainHackingExp(this.workHackExpGained);
this.gainStrengthExp(this.workStrExpGained);
this.gainDefenseExp(this.workDefExpGained);
this.gainDexterityExp(this.workDexExpGained);
this.gainAgilityExp(this.workAgiExpGained);
this.gainCharismaExp(this.workChaExpGained);
}
this.committingCrimeThruSingFn = false;
this.singFnCrimeWorkerScript = null;
this.isWorking = false;
this.crimeType = CrimeType.None;
this.resetWorkStatus();
return "";
}
//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 {
@@ -1714,9 +1516,6 @@ export function singularityStopWork(this: IPlayer): string {
case WorkType.CreateProgram:
res = this.finishCreateProgramWork(true);
break;
case WorkType.Crime:
res = this.finishCrime(true);
break;
case WorkType.GraftAugmentation:
res = this.finishGraftAugmentationWork(true, true);
break;
@@ -0,0 +1,21 @@
import { Work } from "../../Work/Work";
import { IPlayer } from "../IPlayer";
export function start(this: IPlayer, w: Work): void {
if (this.currentWork !== null) {
this.currentWork.finish(this, true);
}
this.currentWork = w;
}
export function process(this: IPlayer, cycles = 1): void {
if (this.currentWork === null) return;
const finished = this.currentWork.process(this, cycles);
if (finished) {
this.finishNEWWork(false);
}
}
export function finish(this: IPlayer, cancelled: boolean): void {
if (this.currentWork === null) return;
this.currentWork.finish(this, cancelled);
this.currentWork = null;
}