2024-10-21 17:35:32 +02:00
|
|
|
import { produce } from 'immer';
|
|
|
|
|
2024-11-04 18:10:26 +01:00
|
|
|
import { getBuilding, getProduction, getStorage, getUnitSource } from './utils';
|
2024-10-21 17:35:32 +02:00
|
|
|
import village, { type VillageState } from "./village";
|
2024-10-25 19:03:32 +02:00
|
|
|
import type { ProductionType } from './types';
|
2024-10-21 17:35:32 +02:00
|
|
|
|
|
|
|
|
|
|
|
let lastFrame: number;
|
|
|
|
|
|
|
|
|
|
|
|
export default function update(timestamp: number) {
|
|
|
|
if (!lastFrame) {
|
|
|
|
lastFrame = timestamp;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
const delta = timestamp - lastFrame;
|
|
|
|
|
|
|
|
village.update(state => {
|
2024-11-04 18:43:03 +01:00
|
|
|
if (state.victory) {
|
|
|
|
return state;
|
|
|
|
}
|
|
|
|
|
2024-10-21 17:35:32 +02:00
|
|
|
return produce(state, (V: VillageState) => {
|
2024-10-24 19:27:33 +02:00
|
|
|
// Advance building construction.
|
|
|
|
if (V.queue.length) {
|
|
|
|
V.queue[0].remainingTime -= delta;
|
|
|
|
if (V.queue[0].remainingTime <= 0) {
|
|
|
|
const building = getBuilding(V, V.queue[0].id);
|
|
|
|
building.level++;
|
|
|
|
V.queue.shift();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-11-05 11:35:32 +01:00
|
|
|
// Make all buildings and units produce and consume.
|
2024-10-22 17:15:35 +02:00
|
|
|
const productionPerMinute = getProduction(V);
|
|
|
|
const storage = getStorage(V);
|
|
|
|
|
|
|
|
Object.keys(productionPerMinute).forEach((key) => {
|
2024-10-25 19:03:32 +02:00
|
|
|
const resource = key as keyof ProductionType;
|
2024-10-22 17:15:35 +02:00
|
|
|
const outputPerMinute = productionPerMinute[resource];
|
|
|
|
const outputPerMilisecond = outputPerMinute / 60.0 / 1000.0;
|
|
|
|
V.resources[resource] += outputPerMilisecond * delta;
|
2024-11-05 11:35:32 +01:00
|
|
|
});
|
|
|
|
|
|
|
|
// Make sure resources do not overflow.
|
|
|
|
Object.keys(productionPerMinute).forEach((key) => {
|
|
|
|
const resource = key as keyof ProductionType;
|
2024-10-22 17:15:35 +02:00
|
|
|
|
|
|
|
if (V.resources[resource] > storage[resource]) {
|
|
|
|
V.resources[resource] = storage[resource];
|
2024-10-21 17:35:32 +02:00
|
|
|
}
|
2024-10-23 11:59:50 +02:00
|
|
|
else if (V.resources[resource] < 0) {
|
|
|
|
V.resources[resource] = 0;
|
|
|
|
}
|
2024-10-21 17:35:32 +02:00
|
|
|
});
|
2024-10-22 17:15:35 +02:00
|
|
|
|
2024-10-25 19:03:32 +02:00
|
|
|
// Recruit units.
|
|
|
|
V.buildings.forEach(b => {
|
|
|
|
if (!b.state.recruitment || !b.state.recruitment.count) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
const recruitment = b.state.recruitment;
|
|
|
|
recruitment.elapsedTime += delta;
|
|
|
|
|
|
|
|
const timeToRecruit = b.behavior.units?.recruitmentTime(V, b) * 1000;
|
|
|
|
if (recruitment.elapsedTime >= timeToRecruit) {
|
|
|
|
const unitType = b.behavior.units?.type || '';
|
|
|
|
if (!V.units.hasOwnProperty(unitType)) {
|
|
|
|
V.units[unitType] = 0;
|
|
|
|
}
|
|
|
|
V.units[unitType]++;
|
|
|
|
recruitment.count--;
|
|
|
|
recruitment.elapsedTime = (recruitment.count === 0) ? 0 : timeToRecruit - recruitment.elapsedTime;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2024-11-04 18:43:03 +01:00
|
|
|
// Check if the game is won.
|
2024-11-05 10:35:25 +01:00
|
|
|
if (V.resources.culture >= 2000) {
|
2024-11-04 18:43:03 +01:00
|
|
|
V.victory = true;
|
|
|
|
}
|
2024-11-04 18:10:26 +01:00
|
|
|
|
2024-10-21 17:35:32 +02:00
|
|
|
return V;
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
lastFrame = timestamp;
|
|
|
|
}
|