bitburner-src/src/CotMG/StaneksGift.ts

236 lines
7.4 KiB
TypeScript
Raw Normal View History

2021-10-07 07:36:59 +02:00
import { Fragment } from "./Fragment";
2021-09-25 23:21:50 +02:00
import { ActiveFragment } from "./ActiveFragment";
import { FragmentType } from "./FragmentType";
import { IStaneksGift } from "./IStaneksGift";
import { IPlayer } from "../PersonObjects/IPlayer";
import { Factions } from "../Faction/Factions";
import { CalculateEffect } from "./formulas/effect";
import { CalculateCharge } from "./formulas/charge";
2021-10-08 09:16:51 +02:00
import { StaneksGiftEvents } from "./StaneksGiftEvents";
2021-09-25 23:21:50 +02:00
import { Generic_fromJSON, Generic_toJSON, Reviver } from "../utils/JSONReviver";
2021-10-08 09:16:51 +02:00
import { CONSTANTS } from "../Constants";
import { StanekConstants } from "./data/Constants";
import { BitNodeMultipliers } from "../BitNode/BitNodeMultipliers";
import { Player } from "../Player";
2021-10-17 03:38:03 +02:00
import { AugmentationNames } from "../Augmentation/data/AugmentationNames";
2021-09-25 23:21:50 +02:00
export class StaneksGift implements IStaneksGift {
2021-10-08 09:16:51 +02:00
storedCycles = 0;
2021-09-25 23:21:50 +02:00
fragments: ActiveFragment[] = [];
2021-10-08 09:16:51 +02:00
baseSize(): number {
return StanekConstants.BaseSize + BitNodeMultipliers.StaneksGiftExtraSize + Player.sourceFileLvl(13);
}
2021-09-25 23:21:50 +02:00
width(): number {
2021-10-08 09:16:51 +02:00
return Math.floor(this.baseSize() / 2 + 1);
2021-09-25 23:21:50 +02:00
}
height(): number {
2021-10-08 09:16:51 +02:00
return Math.floor(this.baseSize() / 2 + 0.6);
2021-09-25 23:21:50 +02:00
}
2021-11-14 05:45:26 +01:00
charge(af: ActiveFragment, threads: number): void {
2021-11-14 04:44:17 +01:00
af.avgCharge = (af.numCharge * af.avgCharge + threads) / (af.numCharge + 1);
af.numCharge++;
2021-10-07 07:36:59 +02:00
2021-11-15 20:41:34 +01:00
Factions["Church of the Machine God"].playerReputation += Math.log(threads + 1) / Math.log(2);
2021-10-07 07:36:59 +02:00
}
2021-09-25 23:21:50 +02:00
2021-10-08 09:16:51 +02:00
inBonus(): boolean {
return (this.storedCycles * CONSTANTS._idleSpeed) / 1000 > 1;
}
process(p: IPlayer, numCycles = 1): void {
2021-10-17 03:38:03 +02:00
if (!p.hasAugmentation(AugmentationNames.StaneksGift1)) return;
2021-11-14 04:44:17 +01:00
this.fragments.filter((f) => f.fragment().type !== FragmentType.Booster).forEach((f) => f.cool());
2021-10-08 09:16:51 +02:00
this.storedCycles += numCycles;
this.storedCycles -= 5;
this.storedCycles = Math.max(0, this.storedCycles);
2021-10-07 07:36:59 +02:00
this.updateMults(p);
2021-10-08 09:16:51 +02:00
StaneksGiftEvents.emit();
2021-10-07 07:36:59 +02:00
}
effect(fragment: ActiveFragment): number {
// Find all the neighbooring cells
const cells = fragment.neighboors();
2021-09-25 23:21:50 +02:00
// find the neighbooring active fragments.
const maybeFragments = cells.map((n) => this.fragmentAt(n[0], n[1]));
2021-10-18 00:59:37 +02:00
// Filter out undefined with typescript "Type guard". Whatever
let neighboors = maybeFragments.filter((v: ActiveFragment | undefined): v is ActiveFragment => !!v);
2021-09-25 23:21:50 +02:00
2021-10-07 07:36:59 +02:00
neighboors = neighboors.filter((fragment) => fragment.fragment().type === FragmentType.Booster);
2021-09-25 23:21:50 +02:00
let boost = 1;
2021-11-14 04:44:17 +01:00
neighboors = neighboors.filter((v, i, s) => s.indexOf(v) === i);
2021-09-25 23:21:50 +02:00
for (const neighboor of neighboors) {
2021-10-07 07:36:59 +02:00
boost *= neighboor.fragment().power;
2021-09-25 23:21:50 +02:00
}
2021-11-14 04:44:17 +01:00
return CalculateEffect(fragment.avgCharge, fragment.numCharge, fragment.fragment().power, boost);
2021-09-25 23:21:50 +02:00
}
2021-11-14 05:45:26 +01:00
canPlace(rootX: number, rootY: number, rotation: number, fragment: Fragment): boolean {
if (rootX < 0 || rootY < 0) return false;
if (rootX + fragment.width(rotation) > this.width()) return false;
if (rootY + fragment.height(rotation) > this.height()) return false;
2021-09-25 23:21:50 +02:00
if (this.count(fragment) >= fragment.limit) return false;
2021-11-14 05:45:26 +01:00
const newFrag = new ActiveFragment({ x: rootX, y: rootY, rotation: rotation, fragment: fragment });
2021-09-25 23:21:50 +02:00
for (const aFrag of this.fragments) {
if (aFrag.collide(newFrag)) return false;
}
return true;
}
2021-11-14 05:45:26 +01:00
place(rootX: number, rootY: number, rotation: number, fragment: Fragment): boolean {
if (!this.canPlace(rootX, rootY, rotation, fragment)) return false;
this.fragments.push(new ActiveFragment({ x: rootX, y: rootY, rotation: rotation, fragment: fragment }));
2021-09-25 23:21:50 +02:00
return true;
}
2021-10-18 00:59:37 +02:00
findFragment(rootX: number, rootY: number): ActiveFragment | undefined {
return this.fragments.find((f) => f.x === rootX && f.y === rootY);
}
fragmentAt(worldX: number, worldY: number): ActiveFragment | undefined {
2021-09-25 23:21:50 +02:00
for (const aFrag of this.fragments) {
if (aFrag.fullAt(worldX, worldY)) {
return aFrag;
}
}
2021-10-18 00:59:37 +02:00
return undefined;
2021-09-25 23:21:50 +02:00
}
count(fragment: Fragment): number {
let amt = 0;
for (const aFrag of this.fragments) {
if (aFrag.fragment().id === fragment.id) amt++;
}
return amt;
}
2021-11-14 05:45:26 +01:00
delete(rootX: number, rootY: number): boolean {
2021-09-25 23:21:50 +02:00
for (let i = 0; i < this.fragments.length; i++) {
2021-11-14 05:45:26 +01:00
if (this.fragments[i].x === rootX && this.fragments[i].y === rootY) {
2021-09-25 23:21:50 +02:00
this.fragments.splice(i, 1);
return true;
}
}
return false;
}
clear(): void {
this.fragments = [];
}
2021-10-17 03:38:03 +02:00
clearCharge(): void {
2021-11-14 04:44:17 +01:00
this.fragments.forEach((f) => {
f.avgCharge = 0;
f.numCharge = 0;
});
2021-10-17 03:38:03 +02:00
}
2021-09-25 23:21:50 +02:00
updateMults(p: IPlayer): void {
p.reapplyAllAugmentations(true);
p.reapplyAllSourceFiles();
for (const aFrag of this.fragments) {
const fragment = aFrag.fragment();
2021-10-07 07:36:59 +02:00
const power = this.effect(aFrag);
2021-09-25 23:21:50 +02:00
switch (fragment.type) {
case FragmentType.HackingChance:
p.hacking_chance_mult *= power;
break;
case FragmentType.HackingSpeed:
p.hacking_speed_mult *= power;
break;
case FragmentType.HackingMoney:
p.hacking_money_mult *= power;
break;
case FragmentType.HackingGrow:
p.hacking_grow_mult *= power;
break;
case FragmentType.Hacking:
p.hacking_mult *= power;
p.hacking_exp_mult *= power;
break;
case FragmentType.Strength:
p.strength_mult *= power;
p.strength_exp_mult *= power;
break;
case FragmentType.Defense:
p.defense_mult *= power;
p.defense_exp_mult *= power;
break;
case FragmentType.Dexterity:
p.dexterity_mult *= power;
p.dexterity_exp_mult *= power;
break;
case FragmentType.Agility:
p.agility_mult *= power;
p.agility_exp_mult *= power;
break;
case FragmentType.Charisma:
p.charisma_mult *= power;
p.charisma_exp_mult *= power;
break;
case FragmentType.HacknetMoney:
p.hacknet_node_money_mult *= power;
break;
case FragmentType.HacknetCost:
p.hacknet_node_purchase_cost_mult *= power;
p.hacknet_node_ram_cost_mult *= power;
p.hacknet_node_core_cost_mult *= power;
p.hacknet_node_level_cost_mult *= power;
break;
case FragmentType.Rep:
p.company_rep_mult *= power;
p.faction_rep_mult *= power;
break;
case FragmentType.WorkMoney:
p.work_money_mult *= power;
break;
case FragmentType.Crime:
p.crime_success_mult *= power;
p.crime_money_mult *= power;
break;
case FragmentType.Bladeburner:
p.bladeburner_max_stamina_mult *= power;
p.bladeburner_stamina_gain_mult *= power;
p.bladeburner_analysis_mult *= power;
p.bladeburner_success_chance_mult *= power;
break;
}
}
p.updateSkillLevels();
2021-09-25 23:21:50 +02:00
}
2021-10-08 09:16:51 +02:00
prestigeAugmentation(): void {
2021-10-17 03:38:03 +02:00
this.clearCharge();
2021-10-08 09:16:51 +02:00
}
prestigeSourceFile(): void {
this.clear();
2021-10-17 03:38:03 +02:00
this.storedCycles = 0;
2021-10-08 09:16:51 +02:00
}
2021-09-25 23:21:50 +02:00
/**
* Serialize Staneks Gift to a JSON save state.
*/
toJSON(): any {
return Generic_toJSON("StaneksGift", this);
}
/**
* Initializes Staneks Gift from a JSON save state
*/
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
static fromJSON(value: any): StaneksGift {
return Generic_fromJSON(StaneksGift, value.data);
}
}
Reviver.constructors.StaneksGift = StaneksGift;