bitburner-src/src/CotMG/StaneksGift.ts

258 lines
8.7 KiB
TypeScript
Raw Normal View History

import { Player } from "@player";
import { AugmentationName, FactionName } from "@enums";
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";
2022-09-20 09:15:00 +02:00
import { BaseGift } from "./BaseGift";
2021-09-25 23:21:50 +02:00
import { Factions } from "../Faction/Factions";
import { CalculateEffect } from "./formulas/effect";
2021-10-08 09:16:51 +02:00
import { StaneksGiftEvents } from "./StaneksGiftEvents";
import { Generic_fromJSON, Generic_toJSON, IReviverValue, constructorsForReviver } from "../utils/JSONReviver";
2021-10-08 09:16:51 +02:00
import { StanekConstants } from "./data/Constants";
import { currentNodeMults } from "../BitNode/BitNodeMultipliers";
import { defaultMultipliers, mergeMultipliers, Multipliers, scaleMultipliers } from "../PersonObjects/Multipliers";
import { Augmentations } from "../Augmentation/Augmentations";
2023-05-16 05:01:19 +02:00
import { getKeyList } from "../utils/helpers/getKeyList";
2021-09-25 23:21:50 +02:00
2022-09-20 09:15:00 +02:00
export class StaneksGift extends BaseGift {
isBonusCharging = false;
justCharged = true;
2021-10-08 09:16:51 +02:00
storedCycles = 0;
2022-09-20 09:15:00 +02:00
constructor() {
super();
}
2021-09-25 23:21:50 +02:00
2021-10-08 09:16:51 +02:00
baseSize(): number {
return StanekConstants.BaseSize + currentNodeMults.StaneksGiftExtraSize + Player.sourceFileLvl(13);
2021-10-08 09:16:51 +02:00
}
2021-09-25 23:21:50 +02:00
width(): number {
2022-04-01 21:45:12 +02:00
return Math.max(2, Math.min(Math.floor(this.baseSize() / 2 + 1), StanekConstants.MaxSize));
2021-09-25 23:21:50 +02:00
}
height(): number {
2022-04-01 21:45:12 +02:00
return Math.max(3, Math.min(Math.floor(this.baseSize() / 2 + 0.6), StanekConstants.MaxSize));
2021-09-25 23:21:50 +02:00
}
2022-09-18 03:09:15 +02:00
charge(af: ActiveFragment, threads: number): void {
2022-04-01 21:45:12 +02:00
if (threads > af.highestCharge) {
af.numCharge = (af.highestCharge * af.numCharge) / threads + 1;
af.highestCharge = threads;
} else {
af.numCharge += threads / af.highestCharge;
}
2021-10-07 07:36:59 +02:00
const cotmg = Factions[FactionName.ChurchOfTheMachineGod];
2022-09-18 03:09:15 +02:00
cotmg.playerReputation += (Player.mults.faction_rep * (Math.pow(threads, 0.95) * (cotmg.favor + 100))) / 1000;
this.justCharged = true;
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 >= 5;
2021-10-08 09:16:51 +02:00
}
2022-09-18 03:09:15 +02:00
process(numCycles = 1): void {
if (!Player.hasAugmentation(AugmentationName.StaneksGift1)) return;
2021-10-08 09:16:51 +02:00
this.storedCycles += numCycles;
const usedCycles = this.isBonusCharging ? 5 : 1;
this.isBonusCharging = false;
this.storedCycles = Math.max(0, this.storedCycles - usedCycles);
// Only update multipliers (slow) if there was charging done since last process tick.
if (this.justCharged) {
Player.applyEntropy(Player.entropy);
this.justCharged = false;
}
2021-10-08 09:16:51 +02:00
StaneksGiftEvents.emit();
2021-10-07 07:36:59 +02:00
}
effect(fragment: ActiveFragment): number {
2022-10-09 07:25:31 +02:00
// Find all the neighboring cells
const cells = fragment.neighbors();
// find the neighboring active fragments.
2021-09-25 23:21:50 +02:00
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
2022-10-09 07:25:31 +02:00
let neighbors = maybeFragments.filter((v: ActiveFragment | undefined): v is ActiveFragment => !!v);
2021-09-25 23:21:50 +02:00
2022-10-09 07:25:31 +02:00
neighbors = neighbors.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
2022-10-09 07:25:31 +02:00
neighbors = neighbors.filter((v, i, s) => s.indexOf(v) === i);
for (const neighboor of neighbors) {
2021-10-07 07:36:59 +02:00
boost *= neighboor.fragment().power;
2021-09-25 23:21:50 +02:00
}
2022-04-01 21:45:12 +02:00
return CalculateEffect(fragment.highestCharge, 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);
}
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) => {
2022-04-01 21:45:12 +02:00
f.highestCharge = 0;
2021-11-14 04:44:17 +01:00
f.numCharge = 0;
});
2021-10-17 03:38:03 +02:00
}
calculateMults(): Multipliers {
const mults = defaultMultipliers();
2021-09-25 23:21:50 +02:00
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:
mults.hacking_chance *= power;
2021-09-25 23:21:50 +02:00
break;
case FragmentType.HackingSpeed:
mults.hacking_speed *= power;
2021-09-25 23:21:50 +02:00
break;
case FragmentType.HackingMoney:
mults.hacking_money *= power;
2021-09-25 23:21:50 +02:00
break;
case FragmentType.HackingGrow:
mults.hacking_grow *= power;
2021-09-25 23:21:50 +02:00
break;
case FragmentType.Hacking:
mults.hacking *= power;
mults.hacking_exp *= power;
2021-09-25 23:21:50 +02:00
break;
case FragmentType.Strength:
mults.strength *= power;
mults.strength_exp *= power;
2021-09-25 23:21:50 +02:00
break;
case FragmentType.Defense:
mults.defense *= power;
mults.defense_exp *= power;
2021-09-25 23:21:50 +02:00
break;
case FragmentType.Dexterity:
mults.dexterity *= power;
mults.dexterity_exp *= power;
2021-09-25 23:21:50 +02:00
break;
case FragmentType.Agility:
mults.agility *= power;
mults.agility_exp *= power;
2021-09-25 23:21:50 +02:00
break;
case FragmentType.Charisma:
mults.charisma *= power;
mults.charisma_exp *= power;
2021-09-25 23:21:50 +02:00
break;
case FragmentType.HacknetMoney:
mults.hacknet_node_money *= power;
2021-09-25 23:21:50 +02:00
break;
case FragmentType.HacknetCost:
mults.hacknet_node_purchase_cost /= power;
mults.hacknet_node_ram_cost /= power;
mults.hacknet_node_core_cost /= power;
mults.hacknet_node_level_cost /= power;
2021-09-25 23:21:50 +02:00
break;
case FragmentType.Rep:
mults.company_rep *= power;
mults.faction_rep *= power;
2021-09-25 23:21:50 +02:00
break;
case FragmentType.WorkMoney:
mults.work_money *= power;
2021-09-25 23:21:50 +02:00
break;
case FragmentType.Crime:
mults.crime_success *= power;
mults.crime_money *= power;
2021-09-25 23:21:50 +02:00
break;
case FragmentType.Bladeburner:
mults.bladeburner_max_stamina *= power;
mults.bladeburner_stamina_gain *= power;
mults.bladeburner_analysis *= power;
mults.bladeburner_success_chance *= power;
2021-09-25 23:21:50 +02:00
break;
}
}
return mults;
}
2022-09-18 03:09:15 +02:00
updateMults(): void {
const mults = this.calculateMults();
2022-09-18 03:09:15 +02:00
Player.mults = mergeMultipliers(Player.mults, mults);
Player.updateSkillLevels();
const zoeAmt = Player.sleeves.reduce((n, sleeve) => n + (sleeve.hasAugmentation(AugmentationName.ZOE) ? 1 : 0), 0);
2022-09-23 21:00:20 +02:00
if (zoeAmt === 0) return;
// Less powerful for each copy.
2022-09-23 21:00:20 +02:00
const scaling = 3 / (zoeAmt + 2);
const sleeveMults = scaleMultipliers(mults, scaling);
2022-09-18 03:09:15 +02:00
for (const sleeve of Player.sleeves) {
if (!sleeve.hasAugmentation(AugmentationName.ZOE)) continue;
sleeve.resetMultipliers();
//reapplying augmentation's multiplier
for (let i = 0; i < sleeve.augmentations.length; ++i) {
const aug = Augmentations[sleeve.augmentations[i].name];
sleeve.applyAugmentation(aug);
}
//applying stanek multiplier
sleeve.mults = mergeMultipliers(sleeve.mults, sleeveMults);
sleeve.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
}
static includedProperties = getKeyList(StaneksGift, { removedKeys: ["justCharged"] });
/** Serialize Staneks Gift to a JSON save state. */
2022-07-15 01:00:10 +02:00
toJSON(): IReviverValue {
return Generic_toJSON("StaneksGift", this, StaneksGift.includedProperties);
2021-09-25 23:21:50 +02:00
}
/** Initializes Staneks Gift from a JSON save state */
2022-07-15 01:00:10 +02:00
static fromJSON(value: IReviverValue): StaneksGift {
return Generic_fromJSON(StaneksGift, value.data, StaneksGift.includedProperties);
2021-09-25 23:21:50 +02:00
}
}
constructorsForReviver.StaneksGift = StaneksGift;