pastor auto recruitment
This commit is contained in:
parent
a4ffd985ef
commit
3ada821430
|
@ -39,6 +39,9 @@ body, html {
|
||||||
padding: 0.25em 0.5em;
|
padding: 0.25em 0.5em;
|
||||||
margin: 0 0.5em 0.5em 0;
|
margin: 0 0.5em 0.5em 0;
|
||||||
}
|
}
|
||||||
|
.resource.locked {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
#resource-container-religion .resource {
|
#resource-container-religion .resource {
|
||||||
background-color: #ccf;
|
background-color: #ccf;
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,8 @@ class Pastor extends Job {
|
||||||
private _timeSinceLastTithe: number = 0;
|
private _timeSinceLastTithe: number = 0;
|
||||||
|
|
||||||
constructor () {
|
constructor () {
|
||||||
super('Pastors', 'Leaders of the faith.');
|
super('Pastors',
|
||||||
|
'Collect tithings for you and recruit new members from other faiths automatically.');
|
||||||
}
|
}
|
||||||
|
|
||||||
public max (state: GameState): number {
|
public max (state: GameState): number {
|
||||||
|
|
|
@ -8,12 +8,13 @@ class PlayerOrg implements IResource {
|
||||||
public readonly clickText: string = 'Recruit';
|
public readonly clickText: string = 'Recruit';
|
||||||
public readonly clickDescription: string = 'Gather new followers.';
|
public readonly clickDescription: string = 'Gather new followers.';
|
||||||
public value: number = 0;
|
public value: number = 0;
|
||||||
public readonly cost: { [key: string]: number } = { };
|
public readonly cost: null = null;
|
||||||
|
|
||||||
public readonly inc: null = null;
|
private _timeSinceLastLost: number = 0;
|
||||||
|
|
||||||
private _lastLostTime: number = 0;
|
|
||||||
private _baseMax: number = 5;
|
private _baseMax: number = 5;
|
||||||
|
private _lastRecruitmentLog: number = 0;
|
||||||
|
private _followerSources: { [key: string]: number } = { };
|
||||||
|
private _followerDests: { [key: string]: number } = { };
|
||||||
|
|
||||||
public max (state: GameState): number {
|
public max (state: GameState): number {
|
||||||
let max: number = this._baseMax;
|
let max: number = this._baseMax;
|
||||||
|
@ -22,6 +23,20 @@ class PlayerOrg implements IResource {
|
||||||
return max;
|
return max;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public inc (state: GameState): number {
|
||||||
|
let inc: number = 0;
|
||||||
|
|
||||||
|
// pastor recruiting
|
||||||
|
const pastors: number = state.getResource('pstor').value;
|
||||||
|
inc += pastors * state.config.cfgPastorRecruitRate;
|
||||||
|
|
||||||
|
// credibility adjustment
|
||||||
|
const creds: IResource = state.getResource('creds');
|
||||||
|
inc *= creds.value / creds.max(state);
|
||||||
|
|
||||||
|
return inc;
|
||||||
|
}
|
||||||
|
|
||||||
public clickAction (state: GameState): void {
|
public clickAction (state: GameState): void {
|
||||||
// don't exceed max
|
// don't exceed max
|
||||||
if (this.value >= this.max(state)) {
|
if (this.value >= this.max(state)) {
|
||||||
|
@ -33,23 +48,39 @@ class PlayerOrg implements IResource {
|
||||||
const creds: IResource = state.getResource('creds');
|
const creds: IResource = state.getResource('creds');
|
||||||
const ratio: number = Math.ceil(creds.value) / creds.max(state);
|
const ratio: number = Math.ceil(creds.value) / creds.max(state);
|
||||||
if (Math.random() > ratio) {
|
if (Math.random() > ratio) {
|
||||||
state.log('Your recruiting efforts failed.');
|
state.log('Your recruitment efforts failed.');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const source: [string, IResource] = this._getRandomReligion(state);
|
this.addValue(1, state);
|
||||||
this.cost[source[0]] = 1;
|
|
||||||
if (state.deductCost(this.cost)) {
|
|
||||||
this.value++;
|
|
||||||
delete this.cost[source[0]];
|
|
||||||
state.log(`You converted one new follower from ${source[1].name}!`);
|
|
||||||
} else {
|
|
||||||
state.log('Your recruiting efforts failed.');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public addValue (amount: number, state: GameState): void {
|
public addValue (amount: number, state: GameState): void {
|
||||||
|
const oldValue: number = this.value;
|
||||||
this.value += amount;
|
this.value += amount;
|
||||||
|
const diff: number = Math.floor(this.value) - Math.floor(oldValue);
|
||||||
|
|
||||||
|
if (diff > 0) {
|
||||||
|
// gained followers must come from other faiths
|
||||||
|
for (let i: number = 0; i < diff; i++) {
|
||||||
|
const source: [string, IResource] = this._getRandomReligion(state);
|
||||||
|
source[1].addValue(-1, state);
|
||||||
|
const curFollowers: number = this._followerSources[source[0]];
|
||||||
|
this._followerSources[source[0]] = curFollowers
|
||||||
|
? curFollowers + 1
|
||||||
|
: 1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// lost followers must return to other faiths
|
||||||
|
for (let i: number = 0; i < diff * -1; i++) {
|
||||||
|
const dest: [string, IResource] = this._getRandomReligion(state);
|
||||||
|
dest[1].addValue(1, state);
|
||||||
|
const curFollowers: number = this._followerDests[dest[0]];
|
||||||
|
this._followerDests[dest[0]] = curFollowers
|
||||||
|
? curFollowers + 1
|
||||||
|
: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public isUnlocked (state: GameState): boolean {
|
public isUnlocked (state: GameState): boolean {
|
||||||
|
@ -58,19 +89,48 @@ class PlayerOrg implements IResource {
|
||||||
|
|
||||||
public advanceAction (time: number, state: GameState): void {
|
public advanceAction (time: number, state: GameState): void {
|
||||||
// chance to lose some followers every 10s if credibility < 100%
|
// chance to lose some followers every 10s if credibility < 100%
|
||||||
if (state.now - this._lastLostTime > 10000) {
|
this._timeSinceLastLost += time;
|
||||||
|
if (this._timeSinceLastLost > 10000) {
|
||||||
if (this.value > 0) {
|
if (this.value > 0) {
|
||||||
const creds: IResource = state.getResource('creds');
|
const creds: IResource = state.getResource('creds');
|
||||||
const ratio: number = Math.ceil(creds.value) / creds.max(state);
|
const ratio: number = Math.ceil(creds.value) / creds.max(state);
|
||||||
if (Math.random() > ratio) {
|
if (Math.random() > ratio) {
|
||||||
const lost: number = Math.ceil(this.value / 25 * (1 - ratio));
|
const lost: number = Math.ceil(this.value / 25 * (1 - ratio));
|
||||||
this.addValue(lost * -1, state);
|
this.addValue(lost * -1, state);
|
||||||
const dest: [string, IResource] = this._getRandomReligion(state);
|
|
||||||
dest[1].addValue(lost, state);
|
|
||||||
state.log(`You lost ${lost} followers to ${dest[1].name}.`);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this._lastLostTime = state.now;
|
this._timeSinceLastLost = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// log lost and gained followers every 10s
|
||||||
|
if (state.now - this._lastRecruitmentLog > 10000
|
||||||
|
&& (Object.keys(this._followerSources).length > 0
|
||||||
|
|| Object.keys(this._followerDests).length > 0)) {
|
||||||
|
if (Object.keys(this._followerDests).length > 0) {
|
||||||
|
let msg: string;
|
||||||
|
for (const rkey of Object.keys(this._followerDests)) {
|
||||||
|
if (msg === undefined) msg = 'You lost ';
|
||||||
|
else msg += ' and ';
|
||||||
|
const religion: IResource = state.getResource(rkey);
|
||||||
|
msg +=
|
||||||
|
`${state.formatNumber(this._followerDests[rkey])} followers to ${religion.name}`;
|
||||||
|
delete this._followerDests[rkey];
|
||||||
|
}
|
||||||
|
state.log(msg);
|
||||||
|
}
|
||||||
|
if (Object.keys(this._followerSources).length > 0) {
|
||||||
|
let msg: string;
|
||||||
|
for (const rkey of Object.keys(this._followerSources)) {
|
||||||
|
if (msg === undefined) msg = 'You gained ';
|
||||||
|
else msg += ' and ';
|
||||||
|
const religion: IResource = state.getResource(rkey);
|
||||||
|
msg +=
|
||||||
|
`${state.formatNumber(this._followerSources[rkey])} followers from ${religion.name}`;
|
||||||
|
delete this._followerSources[rkey];
|
||||||
|
}
|
||||||
|
state.log(msg);
|
||||||
|
}
|
||||||
|
this._lastRecruitmentLog = state.now;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@ class DebugRenderer implements IRenderer {
|
||||||
private _handleClick: boolean = true;
|
private _handleClick: boolean = true;
|
||||||
|
|
||||||
public render (state: GameState): void {
|
public render (state: GameState): void {
|
||||||
|
const rkeys: string[] = state.getResources();
|
||||||
if (!this._initialized) {
|
if (!this._initialized) {
|
||||||
const container: HTMLElement =
|
const container: HTMLElement =
|
||||||
document.getElementById('irreligious-game');
|
document.getElementById('irreligious-game');
|
||||||
|
@ -36,48 +37,53 @@ class DebugRenderer implements IRenderer {
|
||||||
resDiv.appendChild(el);
|
resDiv.appendChild(el);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// create containers for each resource
|
||||||
|
for (const rkey of rkeys) {
|
||||||
|
const resource: IResource = state.getResource(rkey);
|
||||||
|
const resContainer: HTMLElement =
|
||||||
|
document.getElementById(
|
||||||
|
`resource-container-${resource.resourceType}`);
|
||||||
|
const el: HTMLElement = document.createElement('div');
|
||||||
|
el.className = 'resource locked';
|
||||||
|
el.id = `resource-details-${rkey}`;
|
||||||
|
let content: string = `
|
||||||
|
<span class='resource-title'
|
||||||
|
title='${this._escape(resource.description)}'>
|
||||||
|
${this._escape(resource.name
|
||||||
|
? resource.name
|
||||||
|
: rkey)}</span><br>
|
||||||
|
<span class='resource-value'></span>
|
||||||
|
<span class='resource-max'></span>
|
||||||
|
<span class='resource-inc'></span>
|
||||||
|
`;
|
||||||
|
if (resource.clickText !== null) {
|
||||||
|
content += `<br>
|
||||||
|
<button class='resource-btn'
|
||||||
|
title='${this._escape(resource.clickDescription)}'>
|
||||||
|
${this._escape(resource.clickText)}</button>`;
|
||||||
|
}
|
||||||
|
if (resource.cost !== null
|
||||||
|
&& Object.keys(resource.cost).length !== 0) {
|
||||||
|
content += "<br>Cost: <span class='resource-cost'></span>";
|
||||||
|
}
|
||||||
|
el.innerHTML = content;
|
||||||
|
resContainer.appendChild(el);
|
||||||
|
if (resource.clickAction !== null) {
|
||||||
|
const btn: Element =
|
||||||
|
el.getElementsByClassName('resource-btn')[0];
|
||||||
|
btn.addEventListener('click', (): void =>
|
||||||
|
state.performClick(rkey));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
const rkeys: string[] = state.getResources();
|
|
||||||
for (const rkey of rkeys) {
|
for (const rkey of rkeys) {
|
||||||
const resource: IResource = state.getResource(rkey);
|
const resource: IResource = state.getResource(rkey);
|
||||||
const container: HTMLElement = document
|
const container: HTMLElement = document
|
||||||
.getElementById(`resource-container-${resource.resourceType}`);
|
.getElementById(`resource-container-${resource.resourceType}`);
|
||||||
if (resource.isUnlocked(state)) {
|
if (resource.isUnlocked(state)) {
|
||||||
let el: HTMLElement = document
|
const el: HTMLElement = document
|
||||||
.getElementById(`resource-details-${rkey}`);
|
.getElementById(`resource-details-${rkey}`);
|
||||||
if (el === null) {
|
if (el.className !== 'resource') el.className = 'resource';
|
||||||
el = document.createElement('div');
|
|
||||||
el.className = 'resource';
|
|
||||||
el.id = `resource-details-${rkey}`;
|
|
||||||
let content: string = `
|
|
||||||
<span class='resource-title'
|
|
||||||
title='${this._escape(resource.description)}'>
|
|
||||||
${this._escape(resource.name
|
|
||||||
? resource.name
|
|
||||||
: rkey)}</span><br>
|
|
||||||
<span class='resource-value'></span>
|
|
||||||
<span class='resource-max'></span>
|
|
||||||
<span class='resource-inc'></span>
|
|
||||||
`;
|
|
||||||
if (resource.clickText !== null) {
|
|
||||||
content += `<br>
|
|
||||||
<button class='resource-btn'
|
|
||||||
title='${this._escape(resource.clickDescription)}'>
|
|
||||||
${this._escape(resource.clickText)}</button>`;
|
|
||||||
}
|
|
||||||
if (resource.cost !== null
|
|
||||||
&& Object.keys(resource.cost).length !== 0) {
|
|
||||||
content += "<br>Cost: <span class='resource-cost'></span>";
|
|
||||||
}
|
|
||||||
el.innerHTML = content;
|
|
||||||
container.appendChild(el);
|
|
||||||
if (resource.clickAction !== null) {
|
|
||||||
const btn: Element =
|
|
||||||
el.getElementsByClassName('resource-btn')[0];
|
|
||||||
btn.addEventListener('click', (): void =>
|
|
||||||
state.performClick(rkey));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const elV: Element =
|
const elV: Element =
|
||||||
el.getElementsByClassName('resource-value')[0];
|
el.getElementsByClassName('resource-value')[0];
|
||||||
const elT: Element =
|
const elT: Element =
|
||||||
|
|
Reference in New Issue