bitburner-src/src/Corporation/Material.ts

144 lines
5.0 KiB
TypeScript
Raw Normal View History

import { CorpMaterialName } from "@nsdefs";
import { Generic_fromJSON, Generic_toJSON, IReviverValue, constructorsForReviver } from "../utils/JSONReviver";
import { materialNames } from "./data/Constants";
2021-08-31 19:04:33 +02:00
import { Export } from "./Export";
import { MaterialInfo } from "./MaterialInfo";
interface IConstructorParams {
name: CorpMaterialName;
}
export class Material {
2021-09-05 01:09:30 +02:00
// Name of material
name: CorpMaterialName;
2021-09-05 01:09:30 +02:00
// Amount of material owned
stored = 0;
2021-09-05 01:09:30 +02:00
// Material's "quality". Unbounded
quality = 1;
2021-09-05 01:09:30 +02:00
// How much demand the Material has in the market, and the range of possible
// values for this "demand"
demand = 0;
demandRange: number[] = [0, 0];
2021-09-05 01:09:30 +02:00
// How much competition there is for this Material in the market, and the range
// of possible values for this "competition"
competition = 0;
competitionRange: number[] = [0, 0];
2021-09-05 01:09:30 +02:00
// Maximum volatility of this Materials stats
maxVolatility = 0;
2021-09-05 01:09:30 +02:00
// Markup. Determines how high of a price you can charge on the material
// compared to the market price without suffering loss in # of sales
// Quality is divided by this to determine markup limits
// e,g, If mku is 10 and quality is 100 then you can markup prices by 100/10 = 10
markup = 0;
2021-09-05 01:09:30 +02:00
// How much of this material is being bought, sold, imported and produced every second
buyAmount = 0;
actualSellAmount = 0;
productionAmount = 0;
importAmount = 0;
2021-09-05 01:09:30 +02:00
// Exports of this material to another warehouse/industry
exports: Export[] = [];
2021-09-05 01:09:30 +02:00
// Total amount of this material exported in the last cycle
exportedLastCycle = 0;
2021-09-05 01:09:30 +02:00
// Cost / sec to buy this material. AKA Market Price
marketPrice = 0;
// Average price paid for the material (accounted as marketPrice for produced/imported materials)
averagePrice = 0;
/** null if there is no limit set on production. 0 actually limits production to 0. */
productionLimit: number | null = null;
// Player inputs for sell price and amount.
desiredSellAmount: string | number = 0;
desiredSellPrice: string | number = "";
2021-09-05 01:09:30 +02:00
// Flags that signal whether automatic sale pricing through Market TA is enabled
marketTa1 = false;
marketTa2 = false;
2023-06-04 06:13:26 +02:00
uiMarketPrice = 0;
// Determines the maximum amount of this material that can be sold in one market cycle
maxSellPerCycle = 0;
constructor(params?: IConstructorParams) {
this.name = params?.name ?? materialNames[0];
this.demand = MaterialInfo[this.name].demandBase;
this.demandRange = MaterialInfo[this.name].demandRange;
this.competition = MaterialInfo[this.name].competitionBase;
this.competitionRange = MaterialInfo[this.name].competitionRange;
this.marketPrice = MaterialInfo[this.name].baseCost;
this.maxVolatility = MaterialInfo[this.name].maxVolatility;
this.markup = MaterialInfo[this.name].baseMarkup;
2021-09-05 01:09:30 +02:00
}
getMarkupLimit(): number {
return this.quality / this.markup;
2021-09-05 01:09:30 +02:00
}
// Process change in demand, competition, and buy cost of this material
processMarket(): void {
// The price will change in accordance with demand and competition.
// e.g. If demand goes up, then so does price. If competition goes up, price goes down
const priceVolatility: number = (Math.random() * this.maxVolatility) / 300;
2021-09-05 01:09:30 +02:00
const priceChange: number = 1 + priceVolatility;
//This 1st random check determines whether competition increases or decreases
const compVolatility: number = (Math.random() * this.maxVolatility) / 100;
2021-09-05 01:09:30 +02:00
const compChange: number = 1 + compVolatility;
if (Math.random() < 0.5) {
this.competition *= compChange;
if (this.competition > this.competitionRange[1]) {
this.competition = this.competitionRange[1];
2021-09-05 01:09:30 +02:00
}
this.marketPrice *= 1 / priceChange; // Competition increases, so price goes down
2021-09-05 01:09:30 +02:00
} else {
this.competition *= 1 / compChange;
if (this.competition < this.competitionRange[0]) {
this.competition = this.competitionRange[0];
2021-09-05 01:09:30 +02:00
}
this.marketPrice *= priceChange; // Competition decreases, so price goes up
}
2021-05-01 09:17:31 +02:00
2021-09-05 01:09:30 +02:00
// This 2nd random check determines whether demand increases or decreases
const dmdVolatility: number = (Math.random() * this.maxVolatility) / 100;
2021-09-05 01:09:30 +02:00
const dmdChange: number = 1 + dmdVolatility;
if (Math.random() < 0.5) {
this.demand *= dmdChange;
if (this.demand > this.demandRange[1]) {
this.demand = this.demandRange[1];
2021-09-05 01:09:30 +02:00
}
this.marketPrice *= priceChange; // Demand increases, so price goes up
2021-09-05 01:09:30 +02:00
} else {
this.demand *= 1 / dmdChange;
if (this.demand < this.demandRange[0]) {
this.demand = this.demandRange[0];
2021-09-05 01:09:30 +02:00
}
this.marketPrice *= 1 / priceChange;
2021-05-01 09:17:31 +02:00
}
2021-09-05 01:09:30 +02:00
}
// Serialize the current object to a JSON save state.
2022-07-15 01:00:10 +02:00
toJSON(): IReviverValue {
2021-09-05 01:09:30 +02:00
return Generic_toJSON("Material", this);
}
2022-10-09 07:25:31 +02:00
// Initializes a Material object from a JSON save state.
2022-07-15 01:00:10 +02:00
static fromJSON(value: IReviverValue): Material {
2023-05-27 07:53:06 +02:00
const material = Generic_fromJSON(Material, value.data);
if (isNaN(material.quality)) material.quality = 1;
return material;
2021-09-05 01:09:30 +02:00
}
}
constructorsForReviver.Material = Material;