From fe34ffee8d06bab96d2b8ae08e256e44fa2fd1bd Mon Sep 17 00:00:00 2001 From: Adrian Gaudebert Date: Thu, 24 Oct 2024 19:27:33 +0200 Subject: [PATCH] Add buildings to a construction queue when building or upgrading them. --- src/board/Outside.svelte | 4 ++- src/buildings.ts | 5 ++-- src/hud/Game.svelte | 19 ++++++++++---- src/hud/Queue.svelte | 50 ++++++++++++++++++++++++++++++++++++ src/hud/Resources.svelte | 1 + src/moves/build.ts | 3 +++ src/moves/upgradeBuilding.ts | 9 ++++--- src/update.ts | 13 +++++++++- src/utils.ts | 16 ++++++++++-- src/village.ts | 8 ++++++ 10 files changed, 113 insertions(+), 15 deletions(-) create mode 100644 src/hud/Queue.svelte diff --git a/src/board/Outside.svelte b/src/board/Outside.svelte index aa8839d..ec618df 100644 --- a/src/board/Outside.svelte +++ b/src/board/Outside.svelte @@ -26,7 +26,9 @@ { :else if $village.outsideTiles[y][x] === VILLAGE_TILE } gameTab.set('village') } - /> + > + + { /if } { /each } diff --git a/src/buildings.ts b/src/buildings.ts index 5393927..4ca610b 100644 --- a/src/buildings.ts +++ b/src/buildings.ts @@ -1,9 +1,9 @@ -import type { Building, BuildingSource } from "./types"; +import type { Building } from "./types"; import { getEmptyResources } from "./utils"; import type { VillageState } from "./village"; -const buildings = [ +export default [ { type: 'townhall', name: 'Town Hall', @@ -172,4 +172,3 @@ const buildings = [ }, }, ]; -export default buildings; diff --git a/src/hud/Game.svelte b/src/hud/Game.svelte index 64e81bb..adf574f 100644 --- a/src/hud/Game.svelte +++ b/src/hud/Game.svelte @@ -1,15 +1,16 @@ + +
+ { #each queue as item } +
+

{ item.building.name }

+

{ Math.ceil(item.remainingTime / 1000) }’

+
+ { /each } +
+ + diff --git a/src/hud/Resources.svelte b/src/hud/Resources.svelte index d5140db..f7ebc9e 100644 --- a/src/hud/Resources.svelte +++ b/src/hud/Resources.svelte @@ -34,6 +34,7 @@ .resources { display: flex; justify-content: space-around; + gap: 1em; } .resources div { diff --git a/src/moves/build.ts b/src/moves/build.ts index 266696b..ce77338 100644 --- a/src/moves/build.ts +++ b/src/moves/build.ts @@ -1,6 +1,7 @@ import buildings from "../buildings"; import { createBuilding, getBuildingSource } from "../create"; import type { Hex } from "../hexgrid"; +import { enqueueBuilding } from "../utils"; import { DEFAULT_TILE, type VillageState } from "../village"; @@ -28,9 +29,11 @@ export default function build(V: VillageState, buildingType: string, tile: Hex) const newBuilding = createBuilding(buildingType); newBuilding.tile = tile; + newBuilding.level = 0; V.buildings.push(newBuilding); V.villageTiles[tile.y][tile.x] = newBuilding.id; + enqueueBuilding(V, newBuilding); return true; } diff --git a/src/moves/upgradeBuilding.ts b/src/moves/upgradeBuilding.ts index 27294cc..be8fa7b 100644 --- a/src/moves/upgradeBuilding.ts +++ b/src/moves/upgradeBuilding.ts @@ -1,3 +1,4 @@ +import { enqueueBuilding } from "../utils"; import type { VillageState } from "../village"; @@ -7,7 +8,10 @@ export default function upgradeBuilding(V: VillageState, buildingId: number) { return false; } - const cost = building.cost(building.level + 1); + const ongoingUpgrades = V.queue.filter(q => q.id === building.id); + const level = building.level + 1 + ongoingUpgrades.length; + + const cost = building.cost(level); if ( cost.wood > V.resources.wood @@ -22,8 +26,7 @@ export default function upgradeBuilding(V: VillageState, buildingId: number) { V.resources.stone -= cost.stone; V.resources.iron -= cost.iron; V.resources.food -= cost.food; - - building.level++; + enqueueBuilding(V, building); return true; } diff --git a/src/update.ts b/src/update.ts index 055a3f0..75fc22a 100644 --- a/src/update.ts +++ b/src/update.ts @@ -1,6 +1,6 @@ import { produce } from 'immer'; -import { getProduction, getStorage } from './utils'; +import { getBuilding, getProduction, getStorage } from './utils'; import village, { type VillageState } from "./village"; import type { Production } from './types'; @@ -18,6 +18,17 @@ export default function update(timestamp: number) { village.update(state => { return produce(state, (V: VillageState) => { + // 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(); + } + } + + // Make all buildings produce and consume. const productionPerMinute = getProduction(V); const storage = getStorage(V); diff --git a/src/utils.ts b/src/utils.ts index e60d4e5..7ef51bb 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -24,7 +24,7 @@ export function getEmptyResources(): Production { export function getProduction(villageState: VillageState): Production { return villageState.buildings - .filter(b => b.behavior.production) + .filter(b => b.behavior.production && b.level > 0) .map(b => { if (b.behavior.production) { return b.behavior.production(villageState, b); @@ -36,7 +36,7 @@ export function getProduction(villageState: VillageState): Production { export function getStorage(villageState: VillageState): Production { return villageState.buildings - .filter(b => b.behavior.storage) + .filter(b => b.behavior.storage && b.level > 0) .map(b => { if (b.behavior.storage) { return b.behavior.storage(villageState, b); @@ -87,3 +87,15 @@ export function shuffle(array: Array): Array { } return result; } + + +export function enqueueBuilding(V: VillageState, building: Building) { + const ongoingUpgrades = V.queue.filter(q => q.id === building.id); + const level = building.level + 1 + ongoingUpgrades.length; + const remainingTime = 1000 * level; + + V.queue.push({ + id: building.id, + remainingTime, + }); +} diff --git a/src/village.ts b/src/village.ts index ae1db5a..069b080 100644 --- a/src/village.ts +++ b/src/village.ts @@ -14,6 +14,12 @@ type Board = { } +interface QueuedBuilding { + id: number; + remainingTime: number; +} + + export interface VillageState { buildings: Building[]; resources: { @@ -25,6 +31,7 @@ export interface VillageState { }; villageTiles: Board; outsideTiles: Board; + queue: QueuedBuilding[]; } @@ -78,6 +85,7 @@ function getInitialState() { }, villageTiles: getInitialVillageBoard(), outsideTiles: getInitialOutsideBoard(), + queue: [], }; // Create the Town hall.