Add a first unit, Philosophers, that you can recruit, but they do nothing for now.
This commit is contained in:
parent
fe34ffee8d
commit
cd872d76e8
@ -1,7 +1,7 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import type { Building } from "../types";
|
import type { BuildingType } from "../types";
|
||||||
|
|
||||||
export let building: Building;
|
export let building: BuildingType;
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<p>{ building.name }</p>
|
<p>{ building.name }</p>
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import buildings from "./buildings";
|
import buildings from "./data/buildings";
|
||||||
import { Hex } from "./hexgrid";
|
import { Hex } from "./hexgrid";
|
||||||
import type { Building, BuildingSource } from "./types";
|
import type { BuildingType, BuildingSource } from "./types";
|
||||||
|
|
||||||
|
|
||||||
let uid = 0;
|
let uid = 0;
|
||||||
@ -17,7 +17,7 @@ export function getBuildingSource(buildingType: string): BuildingSource {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export function createBuilding(buildingType: string): Building {
|
export function createBuilding(buildingType: string): BuildingType {
|
||||||
const source: BuildingSource = getBuildingSource(buildingType);
|
const source: BuildingSource = getBuildingSource(buildingType);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@ -25,5 +25,6 @@ export function createBuilding(buildingType: string): Building {
|
|||||||
id: uid++,
|
id: uid++,
|
||||||
level: 1,
|
level: 1,
|
||||||
tile: new Hex(0, 0),
|
tile: new Hex(0, 0),
|
||||||
|
state: {},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import type { Building } from "./types";
|
import type { BuildingType } from "../types";
|
||||||
import { getEmptyResources } from "./utils";
|
import { getEmptyResources } from "../utils";
|
||||||
import type { VillageState } from "./village";
|
import type { VillageState } from "../village";
|
||||||
|
|
||||||
|
|
||||||
export default [
|
export default [
|
||||||
@ -17,7 +17,7 @@ export default [
|
|||||||
};
|
};
|
||||||
},
|
},
|
||||||
behavior: {
|
behavior: {
|
||||||
storage: (_V: VillageState, _self: Building) => {
|
storage: (_V: VillageState, _self: BuildingType) => {
|
||||||
return {
|
return {
|
||||||
'wood': 100,
|
'wood': 100,
|
||||||
'stone': 100,
|
'stone': 100,
|
||||||
@ -40,7 +40,7 @@ export default [
|
|||||||
};
|
};
|
||||||
},
|
},
|
||||||
behavior: {
|
behavior: {
|
||||||
production: (V: VillageState, self: Building) => {
|
production: (V: VillageState, self: BuildingType) => {
|
||||||
const prod = getEmptyResources();
|
const prod = getEmptyResources();
|
||||||
const outputPerMinute = 5 * (self.level * self.level);
|
const outputPerMinute = 5 * (self.level * self.level);
|
||||||
prod.wood = outputPerMinute;
|
prod.wood = outputPerMinute;
|
||||||
@ -65,7 +65,7 @@ export default [
|
|||||||
};
|
};
|
||||||
},
|
},
|
||||||
behavior: {
|
behavior: {
|
||||||
production: (V: VillageState, self: Building) => {
|
production: (V: VillageState, self: BuildingType) => {
|
||||||
const prod = getEmptyResources();
|
const prod = getEmptyResources();
|
||||||
const outputPerMinute = 5 * (self.level * self.level);
|
const outputPerMinute = 5 * (self.level * self.level);
|
||||||
prod.iron = outputPerMinute;
|
prod.iron = outputPerMinute;
|
||||||
@ -90,7 +90,7 @@ export default [
|
|||||||
};
|
};
|
||||||
},
|
},
|
||||||
behavior: {
|
behavior: {
|
||||||
production: (V: VillageState, self: Building) => {
|
production: (V: VillageState, self: BuildingType) => {
|
||||||
const prod = getEmptyResources();
|
const prod = getEmptyResources();
|
||||||
const outputPerMinute = 5 * (self.level * self.level);
|
const outputPerMinute = 5 * (self.level * self.level);
|
||||||
prod.stone = outputPerMinute;
|
prod.stone = outputPerMinute;
|
||||||
@ -115,7 +115,7 @@ export default [
|
|||||||
};
|
};
|
||||||
},
|
},
|
||||||
behavior: {
|
behavior: {
|
||||||
production: (V: VillageState, self: Building) => {
|
production: (V: VillageState, self: BuildingType) => {
|
||||||
const prod = getEmptyResources();
|
const prod = getEmptyResources();
|
||||||
const outputPerMinute = 5 * (self.level * self.level);
|
const outputPerMinute = 5 * (self.level * self.level);
|
||||||
prod.food = outputPerMinute;
|
prod.food = outputPerMinute;
|
||||||
@ -135,7 +135,7 @@ export default [
|
|||||||
};
|
};
|
||||||
},
|
},
|
||||||
behavior: {
|
behavior: {
|
||||||
storage: (V: VillageState, self: Building) => {
|
storage: (V: VillageState, self: BuildingType) => {
|
||||||
const x = self.level;
|
const x = self.level;
|
||||||
const capacity = ( ( ( x + ( x * x ) ) / 2 ) + 3 ) * 25;
|
const capacity = ( ( ( x + ( x * x ) ) / 2 ) + 3 ) * 25;
|
||||||
return {
|
return {
|
||||||
@ -159,7 +159,7 @@ export default [
|
|||||||
};
|
};
|
||||||
},
|
},
|
||||||
behavior: {
|
behavior: {
|
||||||
storage: (V: VillageState, self: Building) => {
|
storage: (V: VillageState, self: BuildingType) => {
|
||||||
const x = self.level;
|
const x = self.level;
|
||||||
const capacity = ( ( ( x + ( x * x ) ) / 2 ) + 3 ) * 25;
|
const capacity = ( ( ( x + ( x * x ) ) / 2 ) + 3 ) * 25;
|
||||||
return {
|
return {
|
||||||
@ -171,4 +171,28 @@ export default [
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
type: 'university',
|
||||||
|
name: 'University',
|
||||||
|
cost: (level: number) => {
|
||||||
|
return {
|
||||||
|
wood: level * 100,
|
||||||
|
stone: level * 100,
|
||||||
|
iron: level * 100,
|
||||||
|
food: 0,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
behavior: {
|
||||||
|
production: (V: VillageState, self: BuildingType) => {
|
||||||
|
const prod = getEmptyResources();
|
||||||
|
const intakePerMinute = self.level * 2;
|
||||||
|
prod.food = -intakePerMinute;
|
||||||
|
return prod;
|
||||||
|
},
|
||||||
|
units: {
|
||||||
|
type: 'philosopher',
|
||||||
|
recruitmentTime: (V: VillageState, self: BuildingType) => 2 - 0.06 * self.level,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
];
|
];
|
16
src/data/units.ts
Normal file
16
src/data/units.ts
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
export default [
|
||||||
|
{
|
||||||
|
type: 'philosopher',
|
||||||
|
name: 'Philosopher',
|
||||||
|
cost: {
|
||||||
|
wood: 20,
|
||||||
|
stone: 50,
|
||||||
|
iron: 0,
|
||||||
|
food: 0,
|
||||||
|
},
|
||||||
|
behavior: {
|
||||||
|
culturePerMinute: 1,
|
||||||
|
foodIntakePerMinute: 2,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
];
|
@ -1,9 +1,9 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import buildings from "../buildings";
|
|
||||||
import moves from "../moves";
|
import moves from "../moves";
|
||||||
import showBuildingPanel from "../stores/showBuildingPanel";
|
import showBuildingPanel from "../stores/showBuildingPanel";
|
||||||
import { getBuilding } from "../utils";
|
import { getBuilding } from "../utils";
|
||||||
import village from "../village";
|
import village from "../village";
|
||||||
|
import UniversityPanel from "./UniversityPanel.svelte";
|
||||||
|
|
||||||
function close() {
|
function close() {
|
||||||
showBuildingPanel.set(null);
|
showBuildingPanel.set(null);
|
||||||
@ -32,7 +32,14 @@
|
|||||||
<button on:click={ close }>X</button>
|
<button on:click={ close }>X</button>
|
||||||
</span>
|
</span>
|
||||||
</header>
|
</header>
|
||||||
<div class="building">
|
<div class="content">
|
||||||
|
{ #if building.level === 0 }
|
||||||
|
<p>Building in construction…</p>
|
||||||
|
{ :else if building.type === 'university' }
|
||||||
|
<UniversityPanel { building } />
|
||||||
|
{ /if }
|
||||||
|
</div>
|
||||||
|
<div class="upgrade">
|
||||||
<div>
|
<div>
|
||||||
<p>{ building.name } ({ building.level })</p>
|
<p>{ building.name } ({ building.level })</p>
|
||||||
<button on:click={ () => upgrade() }>Upgrade</button>
|
<button on:click={ () => upgrade() }>Upgrade</button>
|
||||||
|
39
src/hud/Cost.svelte
Normal file
39
src/hud/Cost.svelte
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import type { CostType } from "../types";
|
||||||
|
|
||||||
|
export let cost: CostType;
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="cost">
|
||||||
|
<div>
|
||||||
|
<img src="/img/icons/wood.png" alt="Wood" />
|
||||||
|
{ cost.wood }
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<img src="/img/icons/stone.png" alt="Stone" />
|
||||||
|
{ cost.stone }
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<img src="/img/icons/iron.png" alt="Iron" />
|
||||||
|
{ cost.iron }
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<img src="/img/icons/food.png" alt="Food" />
|
||||||
|
{ cost.food }
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.cost {
|
||||||
|
align-items: center;
|
||||||
|
display: flex;
|
||||||
|
gap: 1em;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cost div {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.2em;
|
||||||
|
}
|
||||||
|
</style>
|
@ -9,8 +9,9 @@
|
|||||||
import BuildingCreator from "./BuildingCreator.svelte";
|
import BuildingCreator from "./BuildingCreator.svelte";
|
||||||
import BuildingPanel from "./BuildingPanel.svelte";
|
import BuildingPanel from "./BuildingPanel.svelte";
|
||||||
import Navigation from "./Navigation.svelte";
|
import Navigation from "./Navigation.svelte";
|
||||||
import Resources from "./Resources.svelte";
|
|
||||||
import Queue from "./Queue.svelte";
|
import Queue from "./Queue.svelte";
|
||||||
|
import Resources from "./Resources.svelte";
|
||||||
|
import Units from "./Units.svelte";
|
||||||
|
|
||||||
|
|
||||||
onMount(() => {
|
onMount(() => {
|
||||||
@ -34,6 +35,7 @@
|
|||||||
|
|
||||||
<section class="hud">
|
<section class="hud">
|
||||||
<header>
|
<header>
|
||||||
|
<Units />
|
||||||
<Resources />
|
<Resources />
|
||||||
<Navigation { setTab } />
|
<Navigation { setTab } />
|
||||||
</header>
|
</header>
|
||||||
|
18
src/hud/Units.svelte
Normal file
18
src/hud/Units.svelte
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import units from "../data/units";
|
||||||
|
import village from "../village";
|
||||||
|
|
||||||
|
$: currentUnits = Object.entries($village.units).map(([type, count]) => {
|
||||||
|
const unit = units.find(u => u.type === type);
|
||||||
|
return {
|
||||||
|
...unit,
|
||||||
|
count,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<section>
|
||||||
|
{ #each currentUnits as unit }
|
||||||
|
<p>{ unit.name }: { unit.count }</p>
|
||||||
|
{ /each }
|
||||||
|
</section>
|
72
src/hud/UniversityPanel.svelte
Normal file
72
src/hud/UniversityPanel.svelte
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import moves from "../moves";
|
||||||
|
import type { BuildingType, CostType, UnitType } from "../types";
|
||||||
|
import { getUnitSource } from "../utils";
|
||||||
|
import type { VillageState } from "../village";
|
||||||
|
import village from "../village";
|
||||||
|
import Cost from "./Cost.svelte";
|
||||||
|
|
||||||
|
export let building: BuildingType;
|
||||||
|
|
||||||
|
|
||||||
|
let numberOfUnits = 1;
|
||||||
|
$: unitType = building.behavior.units?.type || '';
|
||||||
|
$: unit = getUnitSource(unitType);
|
||||||
|
$: maximumUnits = getMaxCountOfUnits($village, unit);
|
||||||
|
$: if (numberOfUnits > maximumUnits) {
|
||||||
|
numberOfUnits = maximumUnits || 1;
|
||||||
|
}
|
||||||
|
$: cost = {
|
||||||
|
wood: unit.cost.wood * numberOfUnits,
|
||||||
|
stone: unit.cost.stone * numberOfUnits,
|
||||||
|
iron: unit.cost.iron * numberOfUnits,
|
||||||
|
food: unit.cost.food * numberOfUnits,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
function recruit() {
|
||||||
|
moves.recruitUnits(building.id, unitType, numberOfUnits);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getMaxCountOfUnits(V: VillageState, unitData: UnitType): number {
|
||||||
|
let res = Infinity;
|
||||||
|
Object.entries(V.resources).forEach(([resource, value]) => {
|
||||||
|
const cost = unitData.cost[resource as keyof CostType] || 0;
|
||||||
|
if (cost > 0) {
|
||||||
|
res = Math.min(
|
||||||
|
res,
|
||||||
|
Math.floor(value / cost)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="university">
|
||||||
|
<p>Create Philosophers</p>
|
||||||
|
<div class="cost"><Cost { cost } /></div>
|
||||||
|
|
||||||
|
<input
|
||||||
|
type="range"
|
||||||
|
name="units"
|
||||||
|
min="1"
|
||||||
|
max={ maximumUnits }
|
||||||
|
bind:value={ numberOfUnits }
|
||||||
|
/>
|
||||||
|
<input
|
||||||
|
type="number"
|
||||||
|
name="units"
|
||||||
|
min="1"
|
||||||
|
max={ maximumUnits }
|
||||||
|
bind:value={ numberOfUnits }
|
||||||
|
/>
|
||||||
|
<button on:click={ recruit } disabled={ numberOfUnits > maximumUnits }>Recruit</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.university .cost {
|
||||||
|
margin: 1em;
|
||||||
|
}
|
||||||
|
</style>
|
@ -1,4 +1,4 @@
|
|||||||
import buildings from "../buildings";
|
import buildings from "../data/buildings";
|
||||||
import { createBuilding, getBuildingSource } from "../create";
|
import { createBuilding, getBuildingSource } from "../create";
|
||||||
import type { Hex } from "../hexgrid";
|
import type { Hex } from "../hexgrid";
|
||||||
import { enqueueBuilding } from "../utils";
|
import { enqueueBuilding } from "../utils";
|
||||||
|
@ -3,6 +3,7 @@ import { produce } from 'immer';
|
|||||||
import village, { type VillageState } from '../village';
|
import village, { type VillageState } from '../village';
|
||||||
import build from './build';
|
import build from './build';
|
||||||
import upgradeBuilding from './upgradeBuilding';
|
import upgradeBuilding from './upgradeBuilding';
|
||||||
|
import recruitUnits from './recruitUnits';
|
||||||
|
|
||||||
|
|
||||||
// Encapsulates a move function into a store update, where the data is made
|
// Encapsulates a move function into a store update, where the data is made
|
||||||
@ -30,4 +31,5 @@ export function makeMove(move: (...args: any[]) => boolean) {
|
|||||||
export default {
|
export default {
|
||||||
build: makeMove(build),
|
build: makeMove(build),
|
||||||
upgradeBuilding: makeMove(upgradeBuilding),
|
upgradeBuilding: makeMove(upgradeBuilding),
|
||||||
|
recruitUnits: makeMove(recruitUnits),
|
||||||
};
|
};
|
||||||
|
46
src/moves/recruitUnits.ts
Normal file
46
src/moves/recruitUnits.ts
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
import units from "../data/units";
|
||||||
|
import { getBuilding } from "../utils";
|
||||||
|
import type { VillageState } from "../village";
|
||||||
|
|
||||||
|
|
||||||
|
export default function recruitUnits(
|
||||||
|
V: VillageState, buildingId: number, unitType: string, unitNumber: number
|
||||||
|
) {
|
||||||
|
const unit = units.find(u => u.type === unitType);
|
||||||
|
if (!unit) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const cost = {
|
||||||
|
wood: unit.cost.wood * unitNumber,
|
||||||
|
stone: unit.cost.stone * unitNumber,
|
||||||
|
iron: unit.cost.iron * unitNumber,
|
||||||
|
food: unit.cost.food * unitNumber,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (
|
||||||
|
cost.wood > V.resources.wood
|
||||||
|
|| cost.stone > V.resources.stone
|
||||||
|
|| cost.iron > V.resources.iron
|
||||||
|
|| cost.food > V.resources.food
|
||||||
|
) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
V.resources.wood -= cost.wood;
|
||||||
|
V.resources.stone -= cost.stone;
|
||||||
|
V.resources.iron -= cost.iron;
|
||||||
|
V.resources.food -= cost.food;
|
||||||
|
|
||||||
|
const building = getBuilding(V, buildingId);
|
||||||
|
if (!building.state.recruitment) {
|
||||||
|
building.state.recruitment = {
|
||||||
|
count: 0,
|
||||||
|
elapsedTime: 0,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
building.state.recruitment.count += unitNumber;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
29
src/types.ts
29
src/types.ts
@ -4,7 +4,7 @@ import type { Hex } from "./hexgrid";
|
|||||||
export type GameTab = 'village' | 'resources';
|
export type GameTab = 'village' | 'resources';
|
||||||
|
|
||||||
|
|
||||||
export interface Cost {
|
export interface CostType {
|
||||||
wood: number;
|
wood: number;
|
||||||
stone: number;
|
stone: number;
|
||||||
iron: number;
|
iron: number;
|
||||||
@ -12,23 +12,44 @@ export interface Cost {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export type Production = Cost;
|
export type ProductionType = CostType;
|
||||||
|
|
||||||
|
|
||||||
export interface BuildingSource {
|
export interface BuildingSource {
|
||||||
name: string;
|
name: string;
|
||||||
type: string;
|
type: string;
|
||||||
autoBuilt?: boolean;
|
autoBuilt?: boolean;
|
||||||
cost: (level: number) => Cost;
|
cost: (level: number) => CostType;
|
||||||
behavior: {
|
behavior: {
|
||||||
production?: Function;
|
production?: Function;
|
||||||
storage?: Function;
|
storage?: Function;
|
||||||
|
units?: {
|
||||||
|
type: string;
|
||||||
|
recruitmentTime: Function;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export interface Building extends BuildingSource {
|
export interface BuildingType extends BuildingSource {
|
||||||
id: number;
|
id: number;
|
||||||
level: number;
|
level: number;
|
||||||
tile: Hex;
|
tile: Hex;
|
||||||
|
state: {
|
||||||
|
recruitment?: {
|
||||||
|
count: number;
|
||||||
|
elapsedTime: number;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export interface UnitType {
|
||||||
|
type: string;
|
||||||
|
name: string;
|
||||||
|
cost: CostType;
|
||||||
|
behavior: {
|
||||||
|
foodIntakePerMinute: number;
|
||||||
|
culturePerMinute?: number;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@ import { produce } from 'immer';
|
|||||||
|
|
||||||
import { getBuilding, getProduction, getStorage } from './utils';
|
import { getBuilding, getProduction, getStorage } from './utils';
|
||||||
import village, { type VillageState } from "./village";
|
import village, { type VillageState } from "./village";
|
||||||
import type { Production } from './types';
|
import type { ProductionType } from './types';
|
||||||
|
|
||||||
|
|
||||||
let lastFrame: number;
|
let lastFrame: number;
|
||||||
@ -33,7 +33,7 @@ export default function update(timestamp: number) {
|
|||||||
const storage = getStorage(V);
|
const storage = getStorage(V);
|
||||||
|
|
||||||
Object.keys(productionPerMinute).forEach((key) => {
|
Object.keys(productionPerMinute).forEach((key) => {
|
||||||
const resource = key as keyof Production;
|
const resource = key as keyof ProductionType;
|
||||||
const outputPerMinute = productionPerMinute[resource];
|
const outputPerMinute = productionPerMinute[resource];
|
||||||
const outputPerMilisecond = outputPerMinute / 60.0 / 1000.0;
|
const outputPerMilisecond = outputPerMinute / 60.0 / 1000.0;
|
||||||
V.resources[resource] += outputPerMilisecond * delta;
|
V.resources[resource] += outputPerMilisecond * delta;
|
||||||
@ -46,6 +46,27 @@ export default function update(timestamp: number) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
return V;
|
return V;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
24
src/utils.ts
24
src/utils.ts
@ -1,8 +1,9 @@
|
|||||||
import type { Building, Production } from "./types";
|
import units from "./data/units";
|
||||||
|
import type { BuildingType, ProductionType } from "./types";
|
||||||
import type { VillageState } from "./village";
|
import type { VillageState } from "./village";
|
||||||
|
|
||||||
|
|
||||||
function _reduceResources(acc: Production, item: Production): Production {
|
function _reduceResources(acc: ProductionType, item: ProductionType): ProductionType {
|
||||||
return {
|
return {
|
||||||
wood: acc.wood + item.wood,
|
wood: acc.wood + item.wood,
|
||||||
stone: acc.stone + item.stone,
|
stone: acc.stone + item.stone,
|
||||||
@ -12,7 +13,7 @@ function _reduceResources(acc: Production, item: Production): Production {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export function getEmptyResources(): Production {
|
export function getEmptyResources(): ProductionType {
|
||||||
return {
|
return {
|
||||||
wood: 0,
|
wood: 0,
|
||||||
stone: 0,
|
stone: 0,
|
||||||
@ -22,7 +23,7 @@ export function getEmptyResources(): Production {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export function getProduction(villageState: VillageState): Production {
|
export function getProduction(villageState: VillageState): ProductionType {
|
||||||
return villageState.buildings
|
return villageState.buildings
|
||||||
.filter(b => b.behavior.production && b.level > 0)
|
.filter(b => b.behavior.production && b.level > 0)
|
||||||
.map(b => {
|
.map(b => {
|
||||||
@ -34,7 +35,7 @@ export function getProduction(villageState: VillageState): Production {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export function getStorage(villageState: VillageState): Production {
|
export function getStorage(villageState: VillageState): ProductionType {
|
||||||
return villageState.buildings
|
return villageState.buildings
|
||||||
.filter(b => b.behavior.storage && b.level > 0)
|
.filter(b => b.behavior.storage && b.level > 0)
|
||||||
.map(b => {
|
.map(b => {
|
||||||
@ -46,7 +47,7 @@ export function getStorage(villageState: VillageState): Production {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export function getBuilding(V: VillageState, buildingId: number): Building {
|
export function getBuilding(V: VillageState, buildingId: number): BuildingType {
|
||||||
const building = V.buildings.find(b => b.id === buildingId);
|
const building = V.buildings.find(b => b.id === buildingId);
|
||||||
if (!building) {
|
if (!building) {
|
||||||
throw new Error(`Cannot find building with id "${buildingId}"`);
|
throw new Error(`Cannot find building with id "${buildingId}"`);
|
||||||
@ -55,6 +56,15 @@ export function getBuilding(V: VillageState, buildingId: number): Building {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export function getUnitSource(unitType: string) {
|
||||||
|
const unit = units.find(u => u.type === unitType);
|
||||||
|
if (unit === undefined) {
|
||||||
|
throw new Error(`Unknown unit type: "${unitType}"`);
|
||||||
|
}
|
||||||
|
return unit;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
export function getKeysAsNumbers(dict: Object): Array<number> {
|
export function getKeysAsNumbers(dict: Object): Array<number> {
|
||||||
return Object.keys(dict).map(i => parseInt(i)).sort((a, b) => a - b);
|
return Object.keys(dict).map(i => parseInt(i)).sort((a, b) => a - b);
|
||||||
}
|
}
|
||||||
@ -89,7 +99,7 @@ export function shuffle<T>(array: Array<T>): Array<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export function enqueueBuilding(V: VillageState, building: Building) {
|
export function enqueueBuilding(V: VillageState, building: BuildingType) {
|
||||||
const ongoingUpgrades = V.queue.filter(q => q.id === building.id);
|
const ongoingUpgrades = V.queue.filter(q => q.id === building.id);
|
||||||
const level = building.level + 1 + ongoingUpgrades.length;
|
const level = building.level + 1 + ongoingUpgrades.length;
|
||||||
const remainingTime = 1000 * level;
|
const remainingTime = 1000 * level;
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
import { writable } from "svelte/store";
|
import { writable } from "svelte/store";
|
||||||
|
|
||||||
import buildings from "./buildings";
|
|
||||||
import { createBuilding } from "./create";
|
import { createBuilding } from "./create";
|
||||||
import type { Building } from "./types";
|
|
||||||
import { getTilesAtDistance, Hex } from "./hexgrid";
|
import { getTilesAtDistance, Hex } from "./hexgrid";
|
||||||
|
import type { BuildingType } from "./types";
|
||||||
import { getKeysAsNumbers, shuffle } from "./utils";
|
import { getKeysAsNumbers, shuffle } from "./utils";
|
||||||
|
|
||||||
|
|
||||||
@ -21,7 +20,10 @@ interface QueuedBuilding {
|
|||||||
|
|
||||||
|
|
||||||
export interface VillageState {
|
export interface VillageState {
|
||||||
buildings: Building[];
|
buildings: BuildingType[];
|
||||||
|
units: {
|
||||||
|
[key: string]: number;
|
||||||
|
},
|
||||||
resources: {
|
resources: {
|
||||||
wood: number;
|
wood: number;
|
||||||
stone: number;
|
stone: number;
|
||||||
@ -76,6 +78,7 @@ function getInitialOutsideBoard() {
|
|||||||
function getInitialState() {
|
function getInitialState() {
|
||||||
const state: VillageState = {
|
const state: VillageState = {
|
||||||
buildings: [],
|
buildings: [],
|
||||||
|
units: {},
|
||||||
resources: {
|
resources: {
|
||||||
wood: 60,
|
wood: 60,
|
||||||
stone: 60,
|
stone: 60,
|
||||||
@ -112,6 +115,7 @@ function getInitialState() {
|
|||||||
}
|
}
|
||||||
const newBuilding = createBuilding(type);
|
const newBuilding = createBuilding(type);
|
||||||
newBuilding.tile = new Hex(x, y);
|
newBuilding.tile = new Hex(x, y);
|
||||||
|
newBuilding.level = 10;
|
||||||
state.outsideTiles[y][x] = newBuilding.id;
|
state.outsideTiles[y][x] = newBuilding.id;
|
||||||
state.buildings.push(newBuilding);
|
state.buildings.push(newBuilding);
|
||||||
});
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user