moved all math.floor(value) logic to baseclass
This commit is contained in:
parent
9ba7e70de4
commit
14e1b646a9
25 changed files with 209 additions and 184 deletions
|
@ -52,7 +52,7 @@ body, html {
|
|||
#resource-container-job .resource {
|
||||
background-color: #fcf;
|
||||
}
|
||||
#resource-container-consumable .resource {
|
||||
#resource-container-purchasable .resource {
|
||||
background-color: #cfc;
|
||||
}
|
||||
#resource-container-infrastructure .resource {
|
||||
|
|
|
@ -105,12 +105,12 @@ class GameConfig {
|
|||
const state = new GameState(this);
|
||||
|
||||
// create player organization
|
||||
state.addResource(ResourceKey.followers, new Follower());
|
||||
state.addResource(new Follower());
|
||||
|
||||
// create world religions
|
||||
state.addResource(
|
||||
ResourceKey.christianity,
|
||||
new Religion(
|
||||
ResourceKey.christianity,
|
||||
'Christianity',
|
||||
'christian',
|
||||
'christians',
|
||||
|
@ -120,8 +120,8 @@ class GameConfig {
|
|||
);
|
||||
|
||||
state.addResource(
|
||||
ResourceKey.islam,
|
||||
new Religion(
|
||||
ResourceKey.islam,
|
||||
'Islam',
|
||||
'muslim',
|
||||
'muslims',
|
||||
|
@ -131,8 +131,8 @@ class GameConfig {
|
|||
);
|
||||
|
||||
state.addResource(
|
||||
ResourceKey.hinduism,
|
||||
new Religion(
|
||||
ResourceKey.hinduism,
|
||||
'Hinduism',
|
||||
'hindu',
|
||||
'hindus',
|
||||
|
@ -142,8 +142,8 @@ class GameConfig {
|
|||
);
|
||||
|
||||
state.addResource(
|
||||
ResourceKey.buddhism,
|
||||
new Religion(
|
||||
ResourceKey.buddhism,
|
||||
'Buddhism',
|
||||
'buddhist',
|
||||
'buddhists',
|
||||
|
@ -153,8 +153,8 @@ class GameConfig {
|
|||
);
|
||||
|
||||
state.addResource(
|
||||
ResourceKey.sikhism,
|
||||
new Religion(
|
||||
ResourceKey.sikhism,
|
||||
'Sikhism',
|
||||
'sikh',
|
||||
'sikhs',
|
||||
|
@ -164,8 +164,8 @@ class GameConfig {
|
|||
);
|
||||
|
||||
state.addResource(
|
||||
ResourceKey.judaism,
|
||||
new Religion(
|
||||
ResourceKey.judaism,
|
||||
'Judaism',
|
||||
'jew',
|
||||
'jews',
|
||||
|
@ -175,8 +175,8 @@ class GameConfig {
|
|||
);
|
||||
|
||||
state.addResource(
|
||||
ResourceKey.other,
|
||||
new Religion(
|
||||
ResourceKey.other,
|
||||
'Other',
|
||||
'person from other faiths',
|
||||
'people from other faiths',
|
||||
|
@ -186,8 +186,8 @@ class GameConfig {
|
|||
);
|
||||
|
||||
state.addResource(
|
||||
ResourceKey.atheism,
|
||||
new Religion(
|
||||
ResourceKey.atheism,
|
||||
'Non-Religious',
|
||||
'atheist',
|
||||
'atheists',
|
||||
|
@ -197,24 +197,24 @@ class GameConfig {
|
|||
);
|
||||
|
||||
// add jobs
|
||||
state.addResource(ResourceKey.pastors, new Pastor());
|
||||
state.addResource(ResourceKey.compoundManagers, new CompoundManager());
|
||||
state.addResource(new Pastor());
|
||||
state.addResource(new CompoundManager());
|
||||
|
||||
// add resources
|
||||
state.addResource(ResourceKey.money, new Money(3.5));
|
||||
state.addResource(ResourceKey.cryptoCurrency, new CryptoCurrency(this));
|
||||
state.addResource(ResourceKey.tents, new Tent(this));
|
||||
state.addResource(ResourceKey.houses, new House(this));
|
||||
state.addResource(ResourceKey.churches, new Church(this));
|
||||
state.addResource(ResourceKey.compounds, new Compound(this));
|
||||
state.addResource(ResourceKey.megaChurches, new Megachurch(this));
|
||||
state.addResource(new Money(3.5));
|
||||
state.addResource(new CryptoCurrency(this));
|
||||
state.addResource(new Tent(this));
|
||||
state.addResource(new House(this));
|
||||
state.addResource(new Church(this));
|
||||
state.addResource(new Compound(this));
|
||||
state.addResource(new Megachurch(this));
|
||||
|
||||
// add research
|
||||
state.addResource(ResourceKey.buildingPermit, new BuildingPermit(this));
|
||||
state.addResource(new BuildingPermit(this));
|
||||
|
||||
// add passive resources
|
||||
state.addResource(ResourceKey.credibility, new Credibility(this));
|
||||
state.addResource(ResourceKey.cryptoMarket, new CryptoMarket(this));
|
||||
state.addResource(new Credibility(this));
|
||||
state.addResource(new CryptoMarket(this));
|
||||
|
||||
return state;
|
||||
}
|
||||
|
|
|
@ -26,9 +26,9 @@ class GameState {
|
|||
return this._resourceKeys;
|
||||
}
|
||||
|
||||
public addResource(key: ResourceKey, resource: IResource): void {
|
||||
this._resourceKeys.push(key);
|
||||
this._resources[key] = resource;
|
||||
public addResource(resource: IResource): void {
|
||||
this._resourceKeys.push(resource.resourceKey);
|
||||
this._resources[resource.resourceKey] = resource;
|
||||
}
|
||||
|
||||
public advance(time: number): void {
|
||||
|
@ -161,16 +161,7 @@ class GameState {
|
|||
if (resource === undefined) continue;
|
||||
const saveRes = saveObj.resources[rkey];
|
||||
if (saveRes !== undefined) {
|
||||
// @ts-expect-error writing read-only value from save data
|
||||
resource.value = saveRes.value;
|
||||
// @ts-expect-error writing read-only cost from save data
|
||||
resource.cost = saveRes.cost;
|
||||
if (
|
||||
saveRes.config !== undefined &&
|
||||
resource.restoreConfig !== undefined
|
||||
) {
|
||||
resource.restoreConfig(saveRes.config);
|
||||
}
|
||||
resource.restoreConfig(saveRes);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
/// <reference path="./Research.ts" />
|
||||
|
||||
class BuildingPermit extends Research {
|
||||
public readonly resourceKey = ResourceKey.buildingPermit;
|
||||
|
||||
constructor(config: GameConfig) {
|
||||
super(
|
||||
'Building Permit',
|
||||
|
@ -11,12 +13,12 @@ class BuildingPermit extends Research {
|
|||
this.cost.money = config.cfgInitialCost.buildingPermit;
|
||||
}
|
||||
|
||||
public isUnlocked(state: GameState): boolean {
|
||||
public isUnlocked = (state: GameState): boolean => {
|
||||
if (this._isUnlocked) return true;
|
||||
const compounds = state.resource.compounds;
|
||||
if (compounds !== undefined && compounds.value > 0) {
|
||||
this._isUnlocked = true;
|
||||
}
|
||||
return this._isUnlocked;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
/// <reference path="./Infrastructure.ts" />
|
||||
|
||||
class Church extends Infrastructure {
|
||||
public readonly resourceKey = ResourceKey.churches;
|
||||
|
||||
constructor(config: GameConfig) {
|
||||
super(
|
||||
'Churches',
|
||||
|
@ -17,13 +19,11 @@ class Church extends Infrastructure {
|
|||
this._costMultiplier.money = config.cfgCostMultiplier.churches;
|
||||
}
|
||||
|
||||
public max: (state: GameState) => number = (state) =>
|
||||
Math.floor(
|
||||
(state.resource.compounds?.value ?? 0) *
|
||||
(state.config.cfgCapacity.compounds?.churches ?? 0)
|
||||
);
|
||||
public max = (state: GameState): number =>
|
||||
(state.resource.compounds?.value ?? 0) *
|
||||
(state.config.cfgCapacity.compounds?.churches ?? 0);
|
||||
|
||||
public inc: (state: GameState) => number = (state) => {
|
||||
public inc = (state: GameState): number => {
|
||||
// compound managers
|
||||
return (
|
||||
(state.resource.compoundManagers?.value ?? 0) *
|
||||
|
@ -31,12 +31,12 @@ class Church extends Infrastructure {
|
|||
);
|
||||
};
|
||||
|
||||
public isUnlocked(state: GameState): boolean {
|
||||
public isUnlocked = (state: GameState): boolean => {
|
||||
if (this._isUnlocked) return true;
|
||||
const compounds = state.resource.compounds;
|
||||
if (compounds !== undefined && compounds.value > 0) {
|
||||
this._isUnlocked = true;
|
||||
}
|
||||
return this._isUnlocked;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
/// <reference path="./Infrastructure.ts" />
|
||||
|
||||
class Compound extends Infrastructure {
|
||||
public readonly resourceKey = ResourceKey.compounds;
|
||||
|
||||
constructor(config: GameConfig) {
|
||||
super(
|
||||
'Compounds',
|
||||
|
@ -13,7 +15,7 @@ class Compound extends Infrastructure {
|
|||
this._costMultiplier.money = config.cfgCostMultiplier.compounds;
|
||||
}
|
||||
|
||||
public isUnlocked(state: GameState): boolean {
|
||||
public isUnlocked = (state: GameState): boolean => {
|
||||
if (this._isUnlocked) return true;
|
||||
const tents = state.resource.tents;
|
||||
if (
|
||||
|
@ -23,5 +25,5 @@ class Compound extends Infrastructure {
|
|||
this._isUnlocked = true;
|
||||
}
|
||||
return this._isUnlocked;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
/// <reference path="./Job.ts" />
|
||||
|
||||
class CompoundManager extends Job {
|
||||
public readonly resourceKey = ResourceKey.compoundManagers;
|
||||
|
||||
constructor() {
|
||||
super(
|
||||
'Compound Managers',
|
||||
|
@ -10,16 +12,16 @@ class CompoundManager extends Job {
|
|||
);
|
||||
}
|
||||
|
||||
public max: (state: GameState) => number = (state) => {
|
||||
public max = (state: GameState): number => {
|
||||
return (
|
||||
Math.floor(state.resource.compounds?.value ?? 0) *
|
||||
(state.resource.compounds?.value ?? 0) *
|
||||
(state.config.cfgCapacity.compounds?.compoundManagers ?? 0)
|
||||
);
|
||||
};
|
||||
|
||||
public isUnlocked(state: GameState): boolean {
|
||||
public isUnlocked = (state: GameState): boolean => {
|
||||
if (this._isUnlocked) return true;
|
||||
this._isUnlocked = state.resource.compounds?.isUnlocked(state) === true;
|
||||
return this._isUnlocked;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
/// <reference path="./Passive.ts" />
|
||||
|
||||
class Credibility extends Passive {
|
||||
public readonly resourceKey = ResourceKey.credibility;
|
||||
|
||||
constructor(config: GameConfig) {
|
||||
super(
|
||||
'Credibility',
|
||||
|
@ -8,7 +10,7 @@ class Credibility extends Passive {
|
|||
'credibilities',
|
||||
'Affects your ability to retain followers and collect tithes.'
|
||||
);
|
||||
this.value = config.cfgPassiveMax;
|
||||
this.rawValue = config.cfgPassiveMax;
|
||||
}
|
||||
|
||||
public static ratio(state: GameState): number {
|
||||
|
@ -22,9 +24,8 @@ class Credibility extends Passive {
|
|||
: cred.value / cred.max(state);
|
||||
}
|
||||
|
||||
public max: (state: GameState) => number = (state) =>
|
||||
state.config.cfgPassiveMax;
|
||||
public max = (state: GameState): number => state.config.cfgPassiveMax;
|
||||
|
||||
public inc: (state: GameState) => number = (state) =>
|
||||
public inc = (state: GameState): number =>
|
||||
state.config.cfgCredibilityRestoreRate;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
/// <reference path="./Purchasable.ts" />
|
||||
|
||||
class CryptoCurrency extends Purchasable {
|
||||
public readonly resourceKey = ResourceKey.cryptoCurrency;
|
||||
|
||||
constructor(config: GameConfig) {
|
||||
super(
|
||||
'FaithCoin',
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
/// <reference path="./Hidden.ts" />
|
||||
|
||||
class CryptoMarket extends Hidden {
|
||||
public readonly resourceKey = ResourceKey.cryptoMarket;
|
||||
|
||||
private _adjustmentTime = 0;
|
||||
|
||||
constructor(config: GameConfig) {
|
||||
|
@ -9,7 +11,7 @@ class CryptoMarket extends Hidden {
|
|||
'crypto markets',
|
||||
'How much money a single FaithCoin is worth'
|
||||
);
|
||||
this.value = config.cfgInitialCost.cryptoCurrency ?? 0;
|
||||
this.rawValue = config.cfgInitialCost.cryptoCurrency ?? 0;
|
||||
}
|
||||
|
||||
public max = (state: GameState): number =>
|
||||
|
|
|
@ -1,14 +1,15 @@
|
|||
/// <reference path="./IResource.ts" />
|
||||
/// <reference path="./Resource.ts" />
|
||||
/// <reference path="./Job.ts" />
|
||||
|
||||
class Follower implements IResource {
|
||||
class Follower extends Resource {
|
||||
public readonly resourceType = ResourceType.religion;
|
||||
public readonly resourceKey = ResourceKey.followers;
|
||||
|
||||
public readonly label = 'Your Followers';
|
||||
public readonly singularName = 'follower';
|
||||
public readonly pluralName = 'followers';
|
||||
public readonly description = 'In you they trust.';
|
||||
public readonly valueInWholeNumbers = true;
|
||||
public value = 0;
|
||||
|
||||
public userActions: ResourceAction[] = [
|
||||
{
|
||||
|
@ -21,25 +22,24 @@ class Follower implements IResource {
|
|||
},
|
||||
];
|
||||
|
||||
private _timeSinceLastLost = 0;
|
||||
private _lastRecruitmentLog = 0;
|
||||
private _followerSources: ResourceNumber = {};
|
||||
private _followerDests: ResourceNumber = {};
|
||||
private _timeSinceLastQuit = 0;
|
||||
private _quitTracker: ResourceNumber = {};
|
||||
|
||||
public max(state: GameState): number {
|
||||
public max = (state: GameState): number => {
|
||||
let max = state.config.cfgInitialMax.followers ?? 0;
|
||||
max +=
|
||||
Math.floor(state.resource.tents?.value ?? 0) *
|
||||
(state.resource.tents?.value ?? 0) *
|
||||
(state.config.cfgCapacity.tents?.followers ?? 0);
|
||||
max +=
|
||||
Math.floor(state.resource.houses?.value ?? 0) *
|
||||
(state.resource.houses?.value ?? 0) *
|
||||
(state.config.cfgCapacity.houses?.followers ?? 0);
|
||||
return max;
|
||||
}
|
||||
};
|
||||
|
||||
public inc(state: GameState): number {
|
||||
public inc = (state: GameState): number => {
|
||||
let inc = 0;
|
||||
|
||||
// pastor recruiting
|
||||
|
@ -52,12 +52,12 @@ class Follower implements IResource {
|
|||
if (creds?.max !== undefined) inc *= creds.value / creds.max(state);*/
|
||||
|
||||
return inc;
|
||||
}
|
||||
};
|
||||
|
||||
public addValue(amount: number, state: GameState): void {
|
||||
public addValue = (amount: number, state: GameState): void => {
|
||||
const oldValue = this.value;
|
||||
this.value += amount;
|
||||
const diff = Math.floor(this.value) - Math.floor(oldValue);
|
||||
this.rawValue += amount;
|
||||
const diff = this.value - oldValue;
|
||||
|
||||
if (diff > 0) {
|
||||
// gained followers must come from other faiths
|
||||
|
@ -80,13 +80,11 @@ class Follower implements IResource {
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
public isUnlocked(_state: GameState): boolean {
|
||||
return true;
|
||||
}
|
||||
public isUnlocked = (): boolean => true;
|
||||
|
||||
public advanceAction(time: number, state: GameState): void {
|
||||
public advanceAction = (time: number, state: GameState): void => {
|
||||
// chance for some followers to quit their jobs if money === 0
|
||||
const money = state.resource.money;
|
||||
const totalJobs = Job.totalJobs(state);
|
||||
|
@ -190,7 +188,7 @@ class Follower implements IResource {
|
|||
}
|
||||
this._lastRecruitmentLog = state.now;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private _recruitFollower(state: GameState): void {
|
||||
// don't exceed max
|
||||
|
|
|
@ -1,21 +1,18 @@
|
|||
/// <reference path="./IResource.ts" />
|
||||
/// <reference path="./Resource.ts" />
|
||||
|
||||
abstract class Hidden implements IResource {
|
||||
abstract class Hidden extends Resource {
|
||||
public readonly resourceType = ResourceType.passive;
|
||||
public readonly label = undefined;
|
||||
|
||||
public readonly valueInWholeNumbers = false;
|
||||
public value = 0;
|
||||
|
||||
constructor(
|
||||
public readonly singularName: string,
|
||||
public readonly pluralName: string,
|
||||
public readonly description: string
|
||||
) {}
|
||||
|
||||
public addValue(amount: number, _state: GameState): void {
|
||||
this.value += amount;
|
||||
) {
|
||||
super();
|
||||
}
|
||||
|
||||
public isUnlocked(_state: GameState): boolean {
|
||||
return true;
|
||||
}
|
||||
public isUnlocked = (): boolean => true;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
/// <reference path="./Infrastructure.ts" />
|
||||
|
||||
class House extends Infrastructure {
|
||||
public readonly resourceKey = ResourceKey.houses;
|
||||
|
||||
constructor(config: GameConfig) {
|
||||
super(
|
||||
'Houses',
|
||||
|
@ -15,13 +17,11 @@ class House extends Infrastructure {
|
|||
this._costMultiplier.money = config.cfgCostMultiplier.houses;
|
||||
}
|
||||
|
||||
public max: (state: GameState) => number = (state) =>
|
||||
Math.floor(
|
||||
(state.resource.compounds?.value ?? 0) *
|
||||
(state.config.cfgCapacity.compounds?.houses ?? 0)
|
||||
);
|
||||
public max = (state: GameState): number =>
|
||||
(state.resource.compounds?.value ?? 0) *
|
||||
(state.config.cfgCapacity.compounds?.houses ?? 0);
|
||||
|
||||
public inc: (state: GameState) => number = (state) => {
|
||||
public inc = (state: GameState): number => {
|
||||
// compound managers
|
||||
return (
|
||||
(state.resource.compoundManagers?.value ?? 0) *
|
||||
|
@ -29,12 +29,12 @@ class House extends Infrastructure {
|
|||
);
|
||||
};
|
||||
|
||||
public isUnlocked(state: GameState): boolean {
|
||||
public isUnlocked = (state: GameState): boolean => {
|
||||
if (this._isUnlocked) return true;
|
||||
const compounds = state.resource.compounds;
|
||||
if (compounds !== undefined && compounds.value > 0) {
|
||||
this._isUnlocked = true;
|
||||
}
|
||||
return this._isUnlocked;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -2,13 +2,14 @@
|
|||
|
||||
interface IResource {
|
||||
readonly resourceType: ResourceType;
|
||||
readonly resourceKey: ResourceKey;
|
||||
|
||||
readonly label?: string;
|
||||
readonly singularName: string;
|
||||
readonly pluralName: string;
|
||||
readonly description: string;
|
||||
readonly valueInWholeNumbers: boolean;
|
||||
|
||||
readonly value: number;
|
||||
readonly cost?: ResourceNumber;
|
||||
|
||||
max?: (state: GameState) => number;
|
||||
|
@ -19,6 +20,8 @@ interface IResource {
|
|||
addValue: (amount: number, state: GameState) => void;
|
||||
isUnlocked: (state: GameState) => boolean;
|
||||
|
||||
restoreConfig: (config: ResourceConfig) => void;
|
||||
emitConfig?: () => ResourceConfigValues;
|
||||
restoreConfig?: (config: ResourceConfigValues) => void;
|
||||
|
||||
get value(): number;
|
||||
}
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
/// <reference path="./IResource.ts" />
|
||||
/// <reference path="./Resource.ts" />
|
||||
|
||||
abstract class Job implements IResource {
|
||||
abstract class Job extends Resource {
|
||||
public readonly resourceType = ResourceType.job;
|
||||
|
||||
public readonly valueInWholeNumbers = true;
|
||||
public value = 0;
|
||||
public readonly cost: ResourceNumber = {};
|
||||
|
||||
public max?: (state: GameState) => number = undefined;
|
||||
|
@ -39,7 +39,9 @@ abstract class Job implements IResource {
|
|||
public readonly singularName: string,
|
||||
public readonly pluralName: string,
|
||||
public readonly description: string
|
||||
) {}
|
||||
) {
|
||||
super();
|
||||
}
|
||||
|
||||
public static jobResources(state: GameState): ResourceKey[] {
|
||||
return state.resources.filter((rkey) => {
|
||||
|
@ -74,20 +76,15 @@ abstract class Job implements IResource {
|
|||
return followers - hired;
|
||||
}
|
||||
|
||||
public addValue(amount: number): void {
|
||||
this.value += amount;
|
||||
if (this.value < 0) this.value = 0;
|
||||
}
|
||||
|
||||
public isUnlocked(_state: GameState): boolean {
|
||||
public isUnlocked: (_state: GameState) => boolean = () => {
|
||||
return this._isUnlocked;
|
||||
}
|
||||
};
|
||||
|
||||
public advanceAction(_time: number, state: GameState): void {
|
||||
// if we're out of followers then the jobs also vacate
|
||||
const avail = Job.availableJobs(state);
|
||||
if (avail < 0 && this.value > 0) {
|
||||
this.addValue(avail);
|
||||
this.addValue(avail, state);
|
||||
}
|
||||
|
||||
return;
|
||||
|
@ -110,7 +107,7 @@ abstract class Job implements IResource {
|
|||
this.value < this.max(state) &&
|
||||
state.deductCost(this.cost)
|
||||
) {
|
||||
this.addValue(1);
|
||||
this.addValue(1, state);
|
||||
state.log(this._hireLog(1, state));
|
||||
for (const key in this._costMultiplier) {
|
||||
const rkey = <ResourceKey>key;
|
||||
|
@ -122,7 +119,7 @@ abstract class Job implements IResource {
|
|||
|
||||
private _demoteFollower(state: GameState): void {
|
||||
if (this.value <= 0) return;
|
||||
this.addValue(-1);
|
||||
this.addValue(-1, state);
|
||||
state.log(this._hireLog(-1, state));
|
||||
for (const key in this._costMultiplier) {
|
||||
const rkey = <ResourceKey>key;
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
/// <reference path="./Infrastructure.ts" />
|
||||
|
||||
class Megachurch extends Infrastructure {
|
||||
public readonly resourceKey = ResourceKey.megaChurches;
|
||||
|
||||
constructor(config: GameConfig) {
|
||||
super(
|
||||
'Megachurches',
|
||||
|
@ -15,15 +17,15 @@ class Megachurch extends Infrastructure {
|
|||
this._costMultiplier.money = config.cfgCostMultiplier.megaChurches;
|
||||
}
|
||||
|
||||
public max: (state: GameState) => number = (state) =>
|
||||
public max = (state: GameState): number =>
|
||||
state.config.cfgInitialMax.megaChurches ?? 0;
|
||||
|
||||
public isUnlocked(state: GameState): boolean {
|
||||
public isUnlocked = (state: GameState): boolean => {
|
||||
if (this._isUnlocked) return true;
|
||||
const permit = state.resource.buildingPermit;
|
||||
if (permit !== undefined && permit.value > 0) {
|
||||
this._isUnlocked = true;
|
||||
}
|
||||
return this._isUnlocked;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
/// <reference path="./Purchasable.ts" />
|
||||
/// <reference path="./Resource.ts" />
|
||||
|
||||
class Money extends Resource {
|
||||
public readonly resourceType = ResourceType.purchasable;
|
||||
public readonly resourceKey = ResourceKey.money;
|
||||
|
||||
class Money implements IResource {
|
||||
public readonly resourceType = ResourceType.consumable;
|
||||
public readonly label = 'Money';
|
||||
public readonly singularName = '${}';
|
||||
public readonly pluralName = '${}';
|
||||
|
@ -23,15 +25,14 @@ class Money implements IResource {
|
|||
|
||||
private _lastCollectionTime = 0;
|
||||
|
||||
constructor(public value: number) {}
|
||||
|
||||
public isUnlocked = (_state: GameState): boolean => true;
|
||||
|
||||
public addValue(amount: number, _state: GameState): void {
|
||||
this.value += amount;
|
||||
public constructor(initialValue: number) {
|
||||
super();
|
||||
this.rawValue = initialValue;
|
||||
}
|
||||
|
||||
public max: (state: GameState) => number = (state: GameState) => {
|
||||
public isUnlocked = (_: GameState): boolean => true;
|
||||
|
||||
public max = (state: GameState): number => {
|
||||
let max = state.config.cfgInitialMax.money ?? 0;
|
||||
max +=
|
||||
(state.resource.compounds?.value ?? 0) *
|
||||
|
@ -39,20 +40,20 @@ class Money implements IResource {
|
|||
return max;
|
||||
};
|
||||
|
||||
public inc: (state: GameState) => number = (state) => {
|
||||
public inc = (state: GameState): number => {
|
||||
let inc = 0;
|
||||
|
||||
// tithings
|
||||
inc +=
|
||||
(Math.floor(state.resource.pastors?.value ?? 0) *
|
||||
Math.floor(state.resource.followers?.value ?? 0) *
|
||||
((state.resource.pastors?.value ?? 0) *
|
||||
(state.resource.followers?.value ?? 0) *
|
||||
(state.config.cfgTitheAmount ?? 0) *
|
||||
Credibility.ratio(state)) /
|
||||
state.config.cfgTimeBetweenTithes;
|
||||
|
||||
// salaries
|
||||
inc -=
|
||||
Math.floor(state.resource.compoundManagers?.value ?? 0) *
|
||||
(state.resource.compoundManagers?.value ?? 0) *
|
||||
(state.config.cfgSalary.compoundManagers ?? 0);
|
||||
|
||||
return inc;
|
||||
|
@ -92,11 +93,9 @@ class Money implements IResource {
|
|||
if (followers !== undefined) {
|
||||
state.log(
|
||||
`You collected $${formatNumber(amount)} from ${formatNumber(
|
||||
Math.floor(followers.value)
|
||||
followers.value
|
||||
)} ${
|
||||
Math.floor(followers.value) > 1
|
||||
? followers.pluralName
|
||||
: followers.singularName
|
||||
followers.value > 1 ? followers.pluralName : followers.singularName
|
||||
}.`
|
||||
);
|
||||
} else {
|
||||
|
|
|
@ -1,22 +1,18 @@
|
|||
/// <reference path="./IResource.ts" />
|
||||
/// <reference path="./Resource.ts" />
|
||||
|
||||
abstract class Passive implements IResource {
|
||||
abstract class Passive extends Resource {
|
||||
public readonly resourceType = ResourceType.passive;
|
||||
|
||||
public readonly valueInWholeNumbers = false;
|
||||
public value = 0;
|
||||
|
||||
constructor(
|
||||
public readonly label: string,
|
||||
public readonly singularName: string,
|
||||
public readonly pluralName: string,
|
||||
public readonly description: string
|
||||
) {}
|
||||
|
||||
public addValue(amount: number, _state: GameState): void {
|
||||
this.value += amount;
|
||||
) {
|
||||
super();
|
||||
}
|
||||
|
||||
public isUnlocked(_state: GameState): boolean {
|
||||
return true;
|
||||
}
|
||||
public isUnlocked = (): boolean => true;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
/// <reference path="./Job.ts" />
|
||||
|
||||
class Pastor extends Job {
|
||||
public readonly resourceKey = ResourceKey.pastors;
|
||||
|
||||
constructor() {
|
||||
super(
|
||||
'Pastors',
|
||||
|
@ -10,19 +12,19 @@ class Pastor extends Job {
|
|||
);
|
||||
}
|
||||
|
||||
public max: (state: GameState) => number = (state) => {
|
||||
public max = (state: GameState): number => {
|
||||
let max =
|
||||
Math.floor(state.resource.churches?.value ?? 0) *
|
||||
(state.resource.churches?.value ?? 0) *
|
||||
(state.config.cfgCapacity.churches?.pastors ?? 0);
|
||||
max +=
|
||||
Math.floor(state.resource.megaChurches?.value ?? 0) *
|
||||
(state.resource.megaChurches?.value ?? 0) *
|
||||
(state.config.cfgCapacity.megaChurches?.pastors ?? 0);
|
||||
return Math.floor(max);
|
||||
return max;
|
||||
};
|
||||
|
||||
public isUnlocked(state: GameState): boolean {
|
||||
public isUnlocked = (state: GameState): boolean => {
|
||||
if (this._isUnlocked) return true;
|
||||
this._isUnlocked = state.resource.churches?.isUnlocked(state) === true;
|
||||
return this._isUnlocked;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
/// <reference path="./IResource.ts" />
|
||||
/// <reference path="./Resource.ts" />
|
||||
|
||||
abstract class Purchasable extends Resource {
|
||||
public readonly resourceType: ResourceType = ResourceType.purchasable;
|
||||
|
||||
abstract class Purchasable implements IResource {
|
||||
public readonly resourceType: ResourceType = ResourceType.consumable;
|
||||
public valueInWholeNumbers = true;
|
||||
public value = 0;
|
||||
public readonly cost: ResourceNumber = {};
|
||||
public cost: ResourceNumber = {};
|
||||
|
||||
public inc?: (state: GameState) => number = undefined;
|
||||
public max?: (_state: GameState) => number = undefined;
|
||||
public max?: (state: GameState) => number = undefined;
|
||||
|
||||
public userActions: ResourceAction[] = [
|
||||
{
|
||||
|
@ -37,6 +37,7 @@ abstract class Purchasable implements IResource {
|
|||
private readonly _sellButtonText = 'Sell',
|
||||
private readonly _sellDescription = `Sell a ${singularName}.`
|
||||
) {
|
||||
super();
|
||||
if (canSell) {
|
||||
this.userActions.push({
|
||||
name: this._sellButtonText,
|
||||
|
@ -49,28 +50,25 @@ abstract class Purchasable implements IResource {
|
|||
}
|
||||
}
|
||||
|
||||
public addValue(amount: number, _state: GameState): void {
|
||||
this.value += amount;
|
||||
}
|
||||
|
||||
public isUnlocked(state: GameState): boolean {
|
||||
public isUnlocked = (state: GameState): boolean => {
|
||||
if (!this._isUnlocked && state.isPurchasable(this.cost)) {
|
||||
this._isUnlocked = true;
|
||||
}
|
||||
return this._isUnlocked;
|
||||
}
|
||||
};
|
||||
|
||||
public advanceAction(_time: number, _state: GameState): void {
|
||||
return;
|
||||
}
|
||||
|
||||
public emitConfig: () => ResourceConfigValues = () => {
|
||||
public emitConfig = (): ResourceConfigValues => {
|
||||
return { isUnlocked: this._isUnlocked };
|
||||
};
|
||||
|
||||
public restoreConfig: (config: ResourceConfigValues) => void = (config) => {
|
||||
if (typeof config.isUnlocked === 'boolean') {
|
||||
this._isUnlocked = config.isUnlocked;
|
||||
public restoreConfig = (config: ResourceConfig): void => {
|
||||
this.rawValue = config.value;
|
||||
if (config.cost !== undefined) this.cost = config.cost;
|
||||
if (
|
||||
config.config !== undefined &&
|
||||
typeof config.config.isUnlocked === 'boolean'
|
||||
) {
|
||||
this._isUnlocked = config.config.isUnlocked;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -88,7 +86,7 @@ abstract class Purchasable implements IResource {
|
|||
private _purchase(state: GameState): void {
|
||||
if (this.max !== undefined && this.value >= this.max(state)) return;
|
||||
if (state.deductCost(this.cost)) {
|
||||
this.value += 1;
|
||||
this.addValue(1, state);
|
||||
state.log(this._purchaseLog(1, state));
|
||||
for (const key in this._costMultiplier) {
|
||||
const rkey = <ResourceKey>key;
|
||||
|
@ -118,7 +116,7 @@ abstract class Purchasable implements IResource {
|
|||
costBack[rkey] = cost * -1 * multiplier;
|
||||
state.deductCost(costBack);
|
||||
}
|
||||
this.value -= 1;
|
||||
this.addValue(1, state);
|
||||
state.log(this._purchaseLog(-1, state));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,22 +1,20 @@
|
|||
/// <reference path="./IResource.ts" />
|
||||
/// <reference path="./Resource.ts" />
|
||||
|
||||
class Religion implements IResource {
|
||||
class Religion extends Resource {
|
||||
public readonly resourceType = ResourceType.religion;
|
||||
public readonly valueInWholeNumbers = true;
|
||||
|
||||
constructor(
|
||||
public readonly resourceKey: ResourceKey,
|
||||
public readonly label: string,
|
||||
public readonly singularName: string,
|
||||
public readonly pluralName: string,
|
||||
public readonly description: string,
|
||||
public value: number
|
||||
) {}
|
||||
|
||||
public addValue(amount: number, _state: GameState): void {
|
||||
this.value += amount;
|
||||
initialValue: number
|
||||
) {
|
||||
super();
|
||||
this.rawValue = initialValue;
|
||||
}
|
||||
|
||||
public isUnlocked(_state: GameState): boolean {
|
||||
return true;
|
||||
}
|
||||
public isUnlocked = (): boolean => true;
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
abstract class Research extends Purchasable {
|
||||
public readonly resourceType = ResourceType.research;
|
||||
|
||||
public inc = undefined;
|
||||
|
||||
constructor(
|
||||
|
@ -19,8 +20,7 @@ abstract class Research extends Purchasable {
|
|||
'Learn',
|
||||
'Complete this research.'
|
||||
);
|
||||
this.value = 0;
|
||||
}
|
||||
|
||||
public max: (state: GameState) => number = (_state) => 1;
|
||||
public max = (_: GameState): number => 1;
|
||||
}
|
||||
|
|
31
src/model/resource/Resource.ts
Normal file
31
src/model/resource/Resource.ts
Normal file
|
@ -0,0 +1,31 @@
|
|||
/// <reference path="./IResource.ts" />
|
||||
|
||||
abstract class Resource implements IResource {
|
||||
public cost?: ResourceNumber = undefined;
|
||||
|
||||
protected rawValue = 0;
|
||||
|
||||
public abstract readonly resourceType: ResourceType;
|
||||
public abstract readonly resourceKey: ResourceKey;
|
||||
|
||||
public abstract readonly label?: string;
|
||||
public abstract readonly singularName: string;
|
||||
public abstract readonly pluralName: string;
|
||||
public abstract readonly description: string;
|
||||
public abstract valueInWholeNumbers: boolean;
|
||||
|
||||
public abstract isUnlocked: (state: GameState) => boolean;
|
||||
|
||||
public get value(): number {
|
||||
return this.valueInWholeNumbers ? Math.floor(this.rawValue) : this.rawValue;
|
||||
}
|
||||
|
||||
public addValue = (amount: number, _: GameState): void => {
|
||||
this.rawValue += amount;
|
||||
};
|
||||
|
||||
public restoreConfig = (config: ResourceConfig): void => {
|
||||
this.rawValue = config.value;
|
||||
this.cost = config.cost;
|
||||
};
|
||||
}
|
|
@ -3,7 +3,7 @@
|
|||
enum ResourceType {
|
||||
religion = 'religion',
|
||||
job = 'job',
|
||||
consumable = 'consumable',
|
||||
purchasable = 'purchasable',
|
||||
infrastructure = 'infrastructure',
|
||||
research = 'research',
|
||||
passive = 'passive',
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
/// <reference path="./Infrastructure.ts" />
|
||||
|
||||
class Tent extends Infrastructure {
|
||||
public readonly resourceKey = ResourceKey.tents;
|
||||
|
||||
constructor(config: GameConfig) {
|
||||
super(
|
||||
'Tents',
|
||||
|
@ -15,16 +17,16 @@ class Tent extends Infrastructure {
|
|||
this._costMultiplier.money = config.cfgCostMultiplier.tents;
|
||||
}
|
||||
|
||||
public max: (state: GameState) => number = (state) => {
|
||||
public max = (state: GameState): number => {
|
||||
// ten extra tents per compound
|
||||
let max = state.config.cfgInitialMax.tents ?? 0;
|
||||
max +=
|
||||
(state.resource.compounds?.value ?? 0) *
|
||||
(state.config.cfgCapacity.compounds?.tents ?? 0);
|
||||
return Math.floor(max);
|
||||
return max;
|
||||
};
|
||||
|
||||
public inc: (state: GameState) => number = (state) =>
|
||||
public inc = (state: GameState): number =>
|
||||
// compound managers
|
||||
(state.resource.compoundManagers?.value ?? 0) *
|
||||
(state.config.cfgBuySpeed.compoundManagers?.tents ?? 0);
|
||||
|
|
Reference in a new issue