2022-04-01 21:45:12 +02:00
|
|
|
import { FactionNames } from "../Faction/data/FactionNames";
|
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";
|
2021-10-08 09:16:51 +02:00
|
|
|
import { StaneksGiftEvents } from "./StaneksGiftEvents";
|
2022-07-15 01:00:10 +02:00
|
|
|
import { Generic_fromJSON, Generic_toJSON, IReviverValue, 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 {
|
2022-04-01 21:45:12 +02:00
|
|
|
return StanekConstants.BaseSize + BitNodeMultipliers.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
|
|
|
}
|
|
|
|
|
2021-11-17 16:59:15 +01:00
|
|
|
charge(player: IPlayer, 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
|
|
|
|
2022-03-19 09:09:59 +01:00
|
|
|
const cotmg = Factions[FactionNames.ChurchOfTheMachineGod];
|
2022-07-15 00:43:33 +02:00
|
|
|
cotmg.playerReputation += (player.mults.faction_rep * (Math.pow(threads, 0.95) * (cotmg.favor + 100))) / 1000;
|
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-10-08 09:16:51 +02:00
|
|
|
this.storedCycles += numCycles;
|
2021-12-03 21:45:39 +01:00
|
|
|
this.storedCycles -= 10;
|
2021-10-08 09:16:51 +02:00
|
|
|
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
|
|
|
}
|
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);
|
|
|
|
}
|
|
|
|
|
|
|
|
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) => {
|
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
|
|
|
}
|
|
|
|
|
2021-09-25 23:21:50 +02:00
|
|
|
updateMults(p: IPlayer): void {
|
2022-05-19 00:32:37 +02:00
|
|
|
// applyEntropy also reapplies all augmentations and source files
|
|
|
|
// This wraps up the reset nicely
|
|
|
|
p.applyEntropy(p.entropy);
|
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:
|
2022-07-15 00:43:33 +02:00
|
|
|
p.mults.hacking_chance *= power;
|
2021-09-25 23:21:50 +02:00
|
|
|
break;
|
|
|
|
case FragmentType.HackingSpeed:
|
2022-07-15 00:43:33 +02:00
|
|
|
p.mults.hacking_speed *= power;
|
2021-09-25 23:21:50 +02:00
|
|
|
break;
|
|
|
|
case FragmentType.HackingMoney:
|
2022-07-15 00:43:33 +02:00
|
|
|
p.mults.hacking_money *= power;
|
2021-09-25 23:21:50 +02:00
|
|
|
break;
|
|
|
|
case FragmentType.HackingGrow:
|
2022-07-15 00:43:33 +02:00
|
|
|
p.mults.hacking_grow *= power;
|
2021-09-25 23:21:50 +02:00
|
|
|
break;
|
|
|
|
case FragmentType.Hacking:
|
2022-07-15 00:43:33 +02:00
|
|
|
p.mults.hacking *= power;
|
|
|
|
p.mults.hacking_exp *= power;
|
2021-09-25 23:21:50 +02:00
|
|
|
break;
|
|
|
|
case FragmentType.Strength:
|
2022-07-15 00:43:33 +02:00
|
|
|
p.mults.strength *= power;
|
|
|
|
p.mults.strength_exp *= power;
|
2021-09-25 23:21:50 +02:00
|
|
|
break;
|
|
|
|
case FragmentType.Defense:
|
2022-07-15 00:43:33 +02:00
|
|
|
p.mults.defense *= power;
|
|
|
|
p.mults.defense_exp *= power;
|
2021-09-25 23:21:50 +02:00
|
|
|
break;
|
|
|
|
case FragmentType.Dexterity:
|
2022-07-15 00:43:33 +02:00
|
|
|
p.mults.dexterity *= power;
|
|
|
|
p.mults.dexterity_exp *= power;
|
2021-09-25 23:21:50 +02:00
|
|
|
break;
|
|
|
|
case FragmentType.Agility:
|
2022-07-15 00:43:33 +02:00
|
|
|
p.mults.agility *= power;
|
|
|
|
p.mults.agility_exp *= power;
|
2021-09-25 23:21:50 +02:00
|
|
|
break;
|
|
|
|
case FragmentType.Charisma:
|
2022-07-15 00:43:33 +02:00
|
|
|
p.mults.charisma *= power;
|
|
|
|
p.mults.charisma_exp *= power;
|
2021-09-25 23:21:50 +02:00
|
|
|
break;
|
|
|
|
case FragmentType.HacknetMoney:
|
2022-07-15 00:43:33 +02:00
|
|
|
p.mults.hacknet_node_money *= power;
|
2021-09-25 23:21:50 +02:00
|
|
|
break;
|
|
|
|
case FragmentType.HacknetCost:
|
2022-07-15 00:43:33 +02:00
|
|
|
p.mults.hacknet_node_purchase_cost /= power;
|
|
|
|
p.mults.hacknet_node_ram_cost /= power;
|
|
|
|
p.mults.hacknet_node_core_cost /= power;
|
|
|
|
p.mults.hacknet_node_level_cost /= power;
|
2021-09-25 23:21:50 +02:00
|
|
|
break;
|
|
|
|
case FragmentType.Rep:
|
2022-07-15 00:43:33 +02:00
|
|
|
p.mults.company_rep *= power;
|
|
|
|
p.mults.faction_rep *= power;
|
2021-09-25 23:21:50 +02:00
|
|
|
break;
|
|
|
|
case FragmentType.WorkMoney:
|
2022-07-15 00:43:33 +02:00
|
|
|
p.mults.work_money *= power;
|
2021-09-25 23:21:50 +02:00
|
|
|
break;
|
|
|
|
case FragmentType.Crime:
|
2022-07-15 00:43:33 +02:00
|
|
|
p.mults.crime_success *= power;
|
|
|
|
p.mults.crime_money *= power;
|
2021-09-25 23:21:50 +02:00
|
|
|
break;
|
|
|
|
case FragmentType.Bladeburner:
|
2022-07-15 00:43:33 +02:00
|
|
|
p.mults.bladeburner_max_stamina *= power;
|
|
|
|
p.mults.bladeburner_stamina_gain *= power;
|
|
|
|
p.mults.bladeburner_analysis *= power;
|
|
|
|
p.mults.bladeburner_success_chance *= power;
|
2021-09-25 23:21:50 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2021-10-13 07:24:30 +02:00
|
|
|
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.
|
|
|
|
*/
|
2022-07-15 01:00:10 +02:00
|
|
|
toJSON(): IReviverValue {
|
2021-09-25 23:21:50 +02:00
|
|
|
return Generic_toJSON("StaneksGift", this);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Initializes Staneks Gift from a JSON save state
|
|
|
|
*/
|
2022-07-15 01:00:10 +02:00
|
|
|
static fromJSON(value: IReviverValue): StaneksGift {
|
2021-09-25 23:21:50 +02:00
|
|
|
return Generic_fromJSON(StaneksGift, value.data);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Reviver.constructors.StaneksGift = StaneksGift;
|