This repository has been archived on 2022-01-16. You can view files and clone it, but cannot push or open issues or pull requests.
irreligious/src/model/resource/Purchasable.ts

121 lines
3.5 KiB
TypeScript

/// <reference path="./Resource.ts" />
abstract class Purchasable extends Resource {
public readonly resourceType: ResourceType = ResourceType.purchasable;
public valueInWholeNumbers = true;
public max?: (state: GameState) => number = undefined;
public inc?: (state: GameState) => ResourceNumber = undefined;
public userActions: ResourceAction[] = [
{
name: this._purchaseButtonText,
description: this._purchaseDescription,
isEnabled: (state: GameState): boolean =>
(this.max === undefined || this.value < this.max(state)) &&
state.isPurchasable(this.cost(state)),
performAction: (state: GameState): void => {
this._purchase(state);
},
},
];
protected readonly _baseCost: ResourceNumber = {};
protected readonly _costMultiplier: ResourceNumber = {};
protected _isUnlocked = false;
constructor(
public readonly label: string,
public readonly singularName: string,
public readonly pluralName: string,
public readonly description: string,
canSell = false,
private readonly _purchaseButtonText = 'Purchase',
private readonly _purchaseDescription = `Buy a ${singularName}.`,
private readonly _sellButtonText = 'Sell',
private readonly _sellDescription = `Sell a ${singularName}.`
) {
super();
if (canSell) {
this.userActions.push({
name: this._sellButtonText,
description: this._sellDescription,
isEnabled: (_state: GameState): boolean => this.value > 0,
performAction: (state: GameState): void => {
this._sell(state);
},
});
}
}
public cost = (_: GameState): ResourceNumber => {
if (this.value <= 0) return this._baseCost;
const actualCost: ResourceNumber = {};
for (const key in this._baseCost) {
const rkey = <ResourceKey>key;
const baseCost = this._baseCost[rkey] ?? 0;
const multiplier = this._costMultiplier[rkey] ?? 1;
actualCost[rkey] = baseCost * Math.pow(multiplier, this.value);
}
return actualCost;
};
public isUnlocked = (state: GameState): boolean => {
if (!this._isUnlocked && state.isPurchasable(this.cost(state))) {
this._isUnlocked = true;
}
return this._isUnlocked;
};
public emitConfig = (): ResourceConfigValues => {
return { isUnlocked: this._isUnlocked };
};
public restoreConfig = (config: ResourceConfig): void => {
this.rawValue = config.value;
if (
config.config !== undefined &&
typeof config.config.isUnlocked === 'boolean'
) {
this._isUnlocked = config.config.isUnlocked;
}
};
protected _purchaseLog(amount: number, _state: GameState): string {
let verb = 'purchased';
if (amount < 0) {
verb = 'sold';
amount *= -1;
}
return `You ${verb} ${amount} ${
amount > 1 ? this.pluralName : this.singularName
}.`;
}
private _purchase(state: GameState): void {
if (this.max !== undefined && this.value >= this.max(state)) return;
if (state.deductCost(this.cost(state))) {
this.addValue(1, state);
state.log(this._purchaseLog(1, state));
}
}
private _sell(state: GameState): void {
if (this.value <= 0) return;
this.addValue(-1, state);
state.log(this._purchaseLog(-1, state));
const costBack: ResourceNumber = {};
for (const key in this.cost(state)) {
const rkey = <ResourceKey>key;
const cost = this.cost(state)[rkey];
if (cost === undefined) continue;
costBack[rkey] = cost * state.config.cfgSellCostBackMultiplier * -1;
}
state.deductCost(costBack);
}
}