Compare commits
7 Commits
f427f4e2b6
...
10bd9121a2
Author | SHA1 | Date | |
---|---|---|---|
10bd9121a2 | |||
1f312c072b | |||
92dd8716a4 | |||
42b8dae615 | |||
2dffb2dcac | |||
149a6b47f9 | |||
9639ff1368 |
1
public/img/icons/world.svg
Normal file
1
public/img/icons/world.svg
Normal file
@ -0,0 +1 @@
|
|||||||
|
<svg style="height: 512px; width: 512px;" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><g class="" style="" transform="translate(0,0)"><path d="M253.47 17.406C123.76 17.406 18.437 122.76 18.437 252.47c0 129.707 105.324 235.06 235.03 235.06 129.707 0 235.063-105.353 235.063-235.06 0-129.71-105.355-235.064-235.06-235.064zM367.874 68.75c61.246 38.19 101.97 106.14 101.97 183.72 0 17.143-1.993 33.823-5.75 49.81l-34.25-18.06 22 54.874c-9.454 21.647-22.362 41.432-38 58.687l-43.158-30.936-64.625 47.72-61.656 6.967-13.906-41.78-49.72 26.844-68.093-18.938 9.157 36.594c-28.41-21.793-51.23-50.466-66-83.563L81.25 304.47l32.25 17.124 59.22-9.875 2.843-40.908-37.344-1.718 4.905-17.844 30.78-25.313-25.093-15.625 67.22-38.593-45.345-29.657-66.625 40.187-49.437-15.28c13.812-32.14 35.21-60.22 61.906-82.064l-3.75 44.375 43.376-34.124 72 22.22-22.5-27.407L233 75.562l26.813 28.468 71 9.845-3.5-34.47 41.468 12.657-.905-23.312zm1.156 120.03L278 199.47l28.906 43.218 3.156 64.468L339.25 321l11.438-28.375 62.656 48.656L395.78 294l6.408-48.344-43.75-22.72 10.593-34.155zM221 192.438l-31.594 21.188 36.47 14.78 16.686-14.78L221 192.437zm22.188 144.688l18.687 52.594 19.78-42.564-38.467-10.03z" fill="#ffffff" fill-opacity="1"></path></g></svg>
|
After Width: | Height: | Size: 1.2 KiB |
@ -37,9 +37,6 @@ h1 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#app {
|
#app {
|
||||||
max-width: 1280px;
|
|
||||||
margin: 0 auto;
|
|
||||||
padding: 2rem;
|
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
|
|
||||||
$: isUpgrading = building.state.upgrade.isUpgrading;
|
$: isUpgrading = building.state.upgrade.isUpgrading;
|
||||||
$: canUpgrade = !isUpgrading && canPayBuildingCost($village, building);
|
$: canUpgrade = !isUpgrading && canPayBuildingCost($village, building);
|
||||||
|
$: maxLevelReached = building.level === building.maxLevel;
|
||||||
|
|
||||||
|
|
||||||
function upgradeBuilding() {
|
function upgradeBuilding() {
|
||||||
@ -24,6 +25,7 @@
|
|||||||
class="level"
|
class="level"
|
||||||
class:can-upgrade={ canUpgrade }
|
class:can-upgrade={ canUpgrade }
|
||||||
class:is-upgrading={ isUpgrading }
|
class:is-upgrading={ isUpgrading }
|
||||||
|
class:max-level={ maxLevelReached }
|
||||||
on:click|stopPropagation={ upgradeBuilding }
|
on:click|stopPropagation={ upgradeBuilding }
|
||||||
>
|
>
|
||||||
{ building.level }
|
{ building.level }
|
||||||
@ -59,4 +61,8 @@
|
|||||||
.level.is-upgrading {
|
.level.is-upgrading {
|
||||||
border-color: hsl(56, 99%, 43%);
|
border-color: hsl(56, 99%, 43%);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.level.max-level {
|
||||||
|
border-color: hsl(209, 70%, 52%);
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
66
src/board/OasisRegion.svelte
Normal file
66
src/board/OasisRegion.svelte
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import moves from "../moves";
|
||||||
|
import type { OasisType } from "../types";
|
||||||
|
import { getRemainingUnitCount } from "../utils";
|
||||||
|
import village from "../village";
|
||||||
|
|
||||||
|
export let region: OasisType;
|
||||||
|
|
||||||
|
|
||||||
|
let numberOfUnits = 0;
|
||||||
|
$: maximumUnits = getRemainingUnitCount($village, 'soldier');
|
||||||
|
$: if (numberOfUnits > maximumUnits) {
|
||||||
|
numberOfUnits = maximumUnits || 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function setMaxUnits() {
|
||||||
|
numberOfUnits = maximumUnits;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function pillage() {
|
||||||
|
moves.pillage(region.state.index, numberOfUnits);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<h2>
|
||||||
|
<img src="/img/icons/{ region.resource }.png" alt="{ region.resource }">
|
||||||
|
Oasis
|
||||||
|
(→ { region.distance })
|
||||||
|
</h2>
|
||||||
|
{ #if region.state.mission }
|
||||||
|
<div>
|
||||||
|
<p>{ region.state.mission.unitCount } soldiers are on a mission here.</p>
|
||||||
|
<p>Remaining: { Math.ceil(region.state.mission.remainingTime / 1000) }</p>
|
||||||
|
</div>
|
||||||
|
{ :else }
|
||||||
|
<div>
|
||||||
|
<input
|
||||||
|
type="range"
|
||||||
|
name="units"
|
||||||
|
min="0"
|
||||||
|
max={ maximumUnits }
|
||||||
|
bind:value={ numberOfUnits }
|
||||||
|
/>
|
||||||
|
<input
|
||||||
|
type="number"
|
||||||
|
name="units"
|
||||||
|
min="0"
|
||||||
|
max={ maximumUnits }
|
||||||
|
bind:value={ numberOfUnits }
|
||||||
|
/>
|
||||||
|
<button on:click={ setMaxUnits }>↑</button>
|
||||||
|
<button on:click={ pillage } disabled={ numberOfUnits === 0 }>Pillage</button>
|
||||||
|
</div>
|
||||||
|
{ /if }
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
h2 {
|
||||||
|
align-items: center;
|
||||||
|
display: flex;
|
||||||
|
gap: 0.4em;
|
||||||
|
}
|
||||||
|
</style>
|
@ -40,7 +40,6 @@
|
|||||||
.outside-map {
|
.outside-map {
|
||||||
display: grid;
|
display: grid;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
margin-top: 0.8em;
|
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,7 +43,6 @@
|
|||||||
.village-map {
|
.village-map {
|
||||||
display: grid;
|
display: grid;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
margin-top: 0.8em;
|
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
29
src/board/Worldmap.svelte
Normal file
29
src/board/Worldmap.svelte
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import village from "../village";
|
||||||
|
import OasisRegion from "./OasisRegion.svelte";
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<section class="worldmap">
|
||||||
|
{ #each $village.worldmap as region }
|
||||||
|
<div class="region">
|
||||||
|
{ #if region.type === 'oasis' }
|
||||||
|
<OasisRegion { region } />
|
||||||
|
{ /if }
|
||||||
|
</div>
|
||||||
|
{ /each }
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.worldmap {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-around;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.region {
|
||||||
|
border: 1px solid white;
|
||||||
|
padding: 1em;
|
||||||
|
}
|
||||||
|
</style>
|
@ -1,6 +1,6 @@
|
|||||||
import buildings from "./data/buildings";
|
import buildings from "./data/buildings";
|
||||||
import { Hex } from "./hexgrid";
|
import { Hex } from "./hexgrid";
|
||||||
import type { BuildingType, BuildingSource } from "./types";
|
import type { BuildingSource, BuildingType } from "./types";
|
||||||
|
|
||||||
|
|
||||||
let uid = 0;
|
let uid = 0;
|
||||||
|
@ -8,6 +8,7 @@ export default [
|
|||||||
type: 'townhall',
|
type: 'townhall',
|
||||||
name: 'Town Hall',
|
name: 'Town Hall',
|
||||||
autoBuilt: true,
|
autoBuilt: true,
|
||||||
|
maxLevel: 20,
|
||||||
cost: (level: number) => {
|
cost: (level: number) => {
|
||||||
return {
|
return {
|
||||||
wood: level * 10,
|
wood: level * 10,
|
||||||
@ -31,6 +32,7 @@ export default [
|
|||||||
type: 'woodcutter',
|
type: 'woodcutter',
|
||||||
name: 'Woodcutter',
|
name: 'Woodcutter',
|
||||||
autoBuilt: true,
|
autoBuilt: true,
|
||||||
|
maxLevel: 20,
|
||||||
cost: (level: number) => {
|
cost: (level: number) => {
|
||||||
return {
|
return {
|
||||||
wood: level * 10,
|
wood: level * 10,
|
||||||
@ -56,6 +58,7 @@ export default [
|
|||||||
type: 'mine',
|
type: 'mine',
|
||||||
name: 'Mine',
|
name: 'Mine',
|
||||||
autoBuilt: true,
|
autoBuilt: true,
|
||||||
|
maxLevel: 20,
|
||||||
cost: (level: number) => {
|
cost: (level: number) => {
|
||||||
return {
|
return {
|
||||||
wood: level * 10,
|
wood: level * 10,
|
||||||
@ -81,6 +84,7 @@ export default [
|
|||||||
type: 'pit',
|
type: 'pit',
|
||||||
name: 'Pit',
|
name: 'Pit',
|
||||||
autoBuilt: true,
|
autoBuilt: true,
|
||||||
|
maxLevel: 20,
|
||||||
cost: (level: number) => {
|
cost: (level: number) => {
|
||||||
return {
|
return {
|
||||||
wood: level * 10,
|
wood: level * 10,
|
||||||
@ -106,6 +110,7 @@ export default [
|
|||||||
type: 'field',
|
type: 'field',
|
||||||
name: 'Field',
|
name: 'Field',
|
||||||
autoBuilt: true,
|
autoBuilt: true,
|
||||||
|
maxLevel: 20,
|
||||||
cost: (level: number) => {
|
cost: (level: number) => {
|
||||||
return {
|
return {
|
||||||
wood: level * 10,
|
wood: level * 10,
|
||||||
@ -126,6 +131,7 @@ export default [
|
|||||||
{
|
{
|
||||||
type: 'warehouse',
|
type: 'warehouse',
|
||||||
name: 'Warehouse',
|
name: 'Warehouse',
|
||||||
|
maxLevel: 20,
|
||||||
cost: (level: number) => {
|
cost: (level: number) => {
|
||||||
return {
|
return {
|
||||||
wood: level * 10,
|
wood: level * 10,
|
||||||
@ -150,6 +156,7 @@ export default [
|
|||||||
{
|
{
|
||||||
type: 'granary',
|
type: 'granary',
|
||||||
name: 'Granary',
|
name: 'Granary',
|
||||||
|
maxLevel: 20,
|
||||||
cost: (level: number) => {
|
cost: (level: number) => {
|
||||||
return {
|
return {
|
||||||
wood: level * 10,
|
wood: level * 10,
|
||||||
@ -174,6 +181,7 @@ export default [
|
|||||||
{
|
{
|
||||||
type: 'university',
|
type: 'university',
|
||||||
name: 'University',
|
name: 'University',
|
||||||
|
maxLevel: 20,
|
||||||
cost: (level: number) => {
|
cost: (level: number) => {
|
||||||
return {
|
return {
|
||||||
wood: level * 100,
|
wood: level * 100,
|
||||||
@ -194,5 +202,30 @@ export default [
|
|||||||
recruitmentTime: (V: VillageState, self: BuildingType) => 2 - 0.06 * self.level,
|
recruitmentTime: (V: VillageState, self: BuildingType) => 2 - 0.06 * self.level,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
},
|
||||||
|
{
|
||||||
|
type: 'barracks',
|
||||||
|
name: 'Barracks',
|
||||||
|
maxLevel: 20,
|
||||||
|
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 = Math.ceil(self.level / 3) * 3;
|
||||||
|
prod.food = -intakePerMinute;
|
||||||
|
return prod;
|
||||||
|
},
|
||||||
|
units: {
|
||||||
|
type: 'soldier',
|
||||||
|
recruitmentTime: (V: VillageState, self: BuildingType) => 1 - 0.03 * self.level,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
@ -9,8 +9,23 @@ export default [
|
|||||||
food: 0,
|
food: 0,
|
||||||
},
|
},
|
||||||
behavior: {
|
behavior: {
|
||||||
|
caryingCapacity: 2,
|
||||||
culturePerMinute: 1,
|
culturePerMinute: 1,
|
||||||
foodIntakePerMinute: 2,
|
foodIntakePerMinute: 2,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
type: 'soldier',
|
||||||
|
name: 'Soldier',
|
||||||
|
cost: {
|
||||||
|
wood: 15,
|
||||||
|
stone: 5,
|
||||||
|
iron: 40,
|
||||||
|
food: 0,
|
||||||
|
},
|
||||||
|
behavior: {
|
||||||
|
caryingCapacity: 4,
|
||||||
|
foodIntakePerMinute: 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
22
src/data/worldmap.ts
Normal file
22
src/data/worldmap.ts
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
export default [
|
||||||
|
{
|
||||||
|
type: 'oasis',
|
||||||
|
resource: 'food',
|
||||||
|
distance: 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'oasis',
|
||||||
|
resource: 'wood',
|
||||||
|
distance: 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'oasis',
|
||||||
|
resource: 'stone',
|
||||||
|
distance: 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'oasis',
|
||||||
|
resource: 'iron',
|
||||||
|
distance: 1,
|
||||||
|
},
|
||||||
|
];
|
@ -1,7 +1,11 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
|
import { createBuilding } from "../create";
|
||||||
import buildings from "../data/buildings";
|
import buildings from "../data/buildings";
|
||||||
import moves from "../moves";
|
import moves from "../moves";
|
||||||
import showBuildingCreator from "../stores/showBuildingCreator";
|
import showBuildingCreator from "../stores/showBuildingCreator";
|
||||||
|
import { canPayBuildingCost } from "../utils";
|
||||||
|
import village from "../village";
|
||||||
|
import Cost from "./Cost.svelte";
|
||||||
|
|
||||||
function close() {
|
function close() {
|
||||||
showBuildingCreator.set(null);
|
showBuildingCreator.set(null);
|
||||||
@ -18,7 +22,11 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const constructible = buildings.filter(b => !b.autoBuilt);
|
const constructible = buildings.filter(b => !b.autoBuilt).map(b =>{
|
||||||
|
const building = createBuilding(b.type);
|
||||||
|
building.level = 0;
|
||||||
|
return building;
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{ #if $showBuildingCreator !== null }
|
{ #if $showBuildingCreator !== null }
|
||||||
@ -34,7 +42,13 @@
|
|||||||
{ #each constructible as building }
|
{ #each constructible as building }
|
||||||
<div>
|
<div>
|
||||||
<p>{ building.name }</p>
|
<p>{ building.name }</p>
|
||||||
<button on:click={ () => build(building.type) }>Build</button>
|
<Cost cost={ building.cost(1) } />
|
||||||
|
<button
|
||||||
|
on:click={ () => build(building.type) }
|
||||||
|
disabled={ !canPayBuildingCost($village, building) }
|
||||||
|
>
|
||||||
|
Build
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
{ /each }
|
{ /each }
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import moves from "../moves";
|
import moves from "../moves";
|
||||||
import showBuildingPanel from "../stores/showBuildingPanel";
|
import showBuildingPanel from "../stores/showBuildingPanel";
|
||||||
import { getBuilding } from "../utils";
|
import { getBuilding, getBuildingUpgradeCost } from "../utils";
|
||||||
import village from "../village";
|
import village from "../village";
|
||||||
import UniversityPanel from "./UniversityPanel.svelte";
|
import BuildingRecruitment from "./BuildingRecruitment.svelte";
|
||||||
|
import Cost from "./Cost.svelte";
|
||||||
|
|
||||||
function close() {
|
function close() {
|
||||||
showBuildingPanel.set(null);
|
showBuildingPanel.set(null);
|
||||||
@ -35,14 +36,24 @@
|
|||||||
<div class="content">
|
<div class="content">
|
||||||
{ #if building.level === 0 }
|
{ #if building.level === 0 }
|
||||||
<p>Building in construction…</p>
|
<p>Building in construction…</p>
|
||||||
{ :else if building.type === 'university' }
|
{ :else if building.behavior.units }
|
||||||
<UniversityPanel { building } />
|
<BuildingRecruitment { building } />
|
||||||
{ /if }
|
{ /if }
|
||||||
</div>
|
</div>
|
||||||
<div class="upgrade">
|
<div class="upgrade">
|
||||||
|
{ #if building.state.upgrade.isUpgrading }
|
||||||
|
<p>
|
||||||
|
Upgrading to level { building.level + 1 }
|
||||||
|
({ Math.ceil(building.state.upgrade.remainingTime / 1000) }’)
|
||||||
|
</p>
|
||||||
|
{ :else if building.level === building.maxLevel }
|
||||||
|
<p>Max level reached!</p>
|
||||||
|
{ :else }
|
||||||
<div>
|
<div>
|
||||||
|
<Cost cost={ getBuildingUpgradeCost($village, building) } />
|
||||||
<button on:click={ () => upgrade() }>Upgrade</button>
|
<button on:click={ () => upgrade() }>Upgrade</button>
|
||||||
</div>
|
</div>
|
||||||
|
{ /if }
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
@ -49,8 +49,8 @@
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="university">
|
<div class="recruitment">
|
||||||
<p>Create Philosophers</p>
|
<p>Recruit { unit.name }s</p>
|
||||||
<div class="cost">
|
<div class="cost">
|
||||||
<Cost { cost } duration={ timeToRecruit } />
|
<Cost { cost } duration={ timeToRecruit } />
|
||||||
</div>
|
</div>
|
||||||
@ -77,7 +77,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
.university .cost {
|
.recruitment .cost {
|
||||||
margin: 1em;
|
margin: 1em;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
import Outside from "../board/Outside.svelte";
|
import Outside from "../board/Outside.svelte";
|
||||||
import Village from "../board/Village.svelte";
|
import Village from "../board/Village.svelte";
|
||||||
|
import Worldmap from "../board/Worldmap.svelte";
|
||||||
import gameTab from "../stores/gameTab";
|
import gameTab from "../stores/gameTab";
|
||||||
import type { GameTab } from "../types";
|
import type { GameTab } from "../types";
|
||||||
import update from "../update";
|
import update from "../update";
|
||||||
@ -12,6 +13,7 @@
|
|||||||
import Resources from "./Resources.svelte";
|
import Resources from "./Resources.svelte";
|
||||||
import Units from "./Units.svelte";
|
import Units from "./Units.svelte";
|
||||||
import Victory from "./Victory.svelte";
|
import Victory from "./Victory.svelte";
|
||||||
|
import Quests from "./Quests.svelte";
|
||||||
|
|
||||||
|
|
||||||
onMount(() => {
|
onMount(() => {
|
||||||
@ -35,15 +37,20 @@
|
|||||||
|
|
||||||
<section class="hud">
|
<section class="hud">
|
||||||
<header>
|
<header>
|
||||||
<Units />
|
|
||||||
<Resources />
|
|
||||||
<Navigation { setTab } />
|
<Navigation { setTab } />
|
||||||
|
<Resources />
|
||||||
</header>
|
</header>
|
||||||
|
<div class="side">
|
||||||
|
<Units />
|
||||||
|
<Quests />
|
||||||
|
</div>
|
||||||
<div class="board">
|
<div class="board">
|
||||||
{ #if $gameTab === 'village' }
|
{ #if $gameTab === 'village' }
|
||||||
<Village />
|
<Village />
|
||||||
{ :else if $gameTab === 'resources' }
|
{ :else if $gameTab === 'resources' }
|
||||||
<Outside />
|
<Outside />
|
||||||
|
{ :else if $gameTab === 'world' }
|
||||||
|
<Worldmap />
|
||||||
{ /if }
|
{ /if }
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
@ -54,9 +61,19 @@
|
|||||||
</section>
|
</section>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
header {
|
.hud {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 20vw 1fr 20vw;
|
||||||
|
grid-template-rows: 20vh 1fr;
|
||||||
|
height: 100vh;
|
||||||
|
width: 100vw;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hud header {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-around;
|
justify-content: center;
|
||||||
|
flex-direction: column;
|
||||||
|
grid-area: 1 / span 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
.overlay {
|
.overlay {
|
||||||
|
@ -19,6 +19,13 @@
|
|||||||
<img src="/img/icons/field.svg" alt="">
|
<img src="/img/icons/field.svg" alt="">
|
||||||
<span>Resources</span>
|
<span>Resources</span>
|
||||||
</button>
|
</button>
|
||||||
|
<button
|
||||||
|
class="invisible"
|
||||||
|
on:click={ () => setTab('world') }
|
||||||
|
>
|
||||||
|
<img src="/img/icons/world.svg" alt="">
|
||||||
|
<span>Worldmap</span>
|
||||||
|
</button>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
50
src/hud/Quests.svelte
Normal file
50
src/hud/Quests.svelte
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { fly } from "svelte/transition";
|
||||||
|
|
||||||
|
import moves from "../moves";
|
||||||
|
import village from "../village";
|
||||||
|
import Reward from "./Reward.svelte";
|
||||||
|
import { flip } from "svelte/animate";
|
||||||
|
|
||||||
|
|
||||||
|
$: isQuestStarted = $village.quests.some(q => q.started);
|
||||||
|
|
||||||
|
function startQuest(id: number) {
|
||||||
|
moves.startQuest(id);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<section>
|
||||||
|
{ #each $village.quests as quest (quest.id) }
|
||||||
|
<div
|
||||||
|
class="quest"
|
||||||
|
in:fly={{ duration: 200, delay: 100, x: -500 }}
|
||||||
|
out:fly={{ duration: 200, x: 500 }}
|
||||||
|
animate:flip={{ duration: 100 }}
|
||||||
|
>
|
||||||
|
<p>
|
||||||
|
<Reward reward={ quest.reward } />
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<img src="/img/icons/time.png" alt="Duration">
|
||||||
|
{ #if quest.started }
|
||||||
|
{ Math.ceil((quest.remainingTime || 0) / 1000) }
|
||||||
|
{ :else }
|
||||||
|
{ quest.duration }
|
||||||
|
<button
|
||||||
|
on:click={ () => startQuest(quest.id) }
|
||||||
|
disabled={ isQuestStarted }
|
||||||
|
>
|
||||||
|
Start quest
|
||||||
|
</button>
|
||||||
|
{ /if }
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
{ /each }
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.quest {
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
</style>
|
@ -38,8 +38,8 @@
|
|||||||
<style>
|
<style>
|
||||||
.resources {
|
.resources {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-around;
|
justify-content: center;
|
||||||
gap: 1em;
|
gap: 2em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.resources div {
|
.resources div {
|
||||||
|
53
src/hud/Reward.svelte
Normal file
53
src/hud/Reward.svelte
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import type { ResourcesType } from "../types";
|
||||||
|
|
||||||
|
export let reward: ResourcesType;
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="reward">
|
||||||
|
{ #if reward.wood > 0 }
|
||||||
|
<div>
|
||||||
|
<img src="/img/icons/wood.png" alt="Wood" />
|
||||||
|
{ reward.wood }
|
||||||
|
</div>
|
||||||
|
{ /if }
|
||||||
|
{ #if reward.stone > 0 }
|
||||||
|
<div>
|
||||||
|
<img src="/img/icons/stone.png" alt="Stone" />
|
||||||
|
{ reward.stone }
|
||||||
|
</div>
|
||||||
|
{ /if }
|
||||||
|
{ #if reward.iron > 0 }
|
||||||
|
<div>
|
||||||
|
<img src="/img/icons/iron.png" alt="Iron" />
|
||||||
|
{ reward.iron }
|
||||||
|
</div>
|
||||||
|
{ /if }
|
||||||
|
{ #if reward.food > 0 }
|
||||||
|
<div>
|
||||||
|
<img src="/img/icons/food.png" alt="Food" />
|
||||||
|
{ reward.food }
|
||||||
|
</div>
|
||||||
|
{ /if }
|
||||||
|
{ #if reward.culture > 0 }
|
||||||
|
<div>
|
||||||
|
<img src="/img/icons/culture.png" alt="Culture" />
|
||||||
|
{ reward.culture }
|
||||||
|
</div>
|
||||||
|
{ /if }
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.reward {
|
||||||
|
align-items: center;
|
||||||
|
display: flex;
|
||||||
|
gap: 1em;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.reward div {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.2em;
|
||||||
|
}
|
||||||
|
</style>
|
@ -1,9 +1,14 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import units from "../data/units";
|
import units from "../data/units";
|
||||||
|
import { getRemainingUnitCount } from "../utils";
|
||||||
import village from "../village";
|
import village from "../village";
|
||||||
|
|
||||||
$: currentUnits = Object.entries($village.units).map(([type, count]) => {
|
$: currentUnits = Object.entries($village.units).map(([type, count]) => {
|
||||||
const unit = units.find(u => u.type === type);
|
const unit = units.find(u => u.type === type);
|
||||||
|
if (!unit) {
|
||||||
|
throw new Error(`Unable to find unit: "${type}"`);
|
||||||
|
|
||||||
|
}
|
||||||
return {
|
return {
|
||||||
...unit,
|
...unit,
|
||||||
count,
|
count,
|
||||||
@ -13,6 +18,6 @@
|
|||||||
|
|
||||||
<section>
|
<section>
|
||||||
{ #each currentUnits as unit }
|
{ #each currentUnits as unit }
|
||||||
<p>{ unit.name }: { unit.count }</p>
|
<p>{ unit.name }: { getRemainingUnitCount($village, unit.type) } / { unit.count }</p>
|
||||||
{ /each }
|
{ /each }
|
||||||
</section>
|
</section>
|
||||||
|
34
src/missions.ts
Normal file
34
src/missions.ts
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
import type { OasisType, RegionType } from "./types";
|
||||||
|
import { getUnitSource } from "./utils";
|
||||||
|
import type { VillageState } from "./village";
|
||||||
|
|
||||||
|
|
||||||
|
export function resolveMission(V: VillageState, region: RegionType) {
|
||||||
|
const mission = region.state.mission;
|
||||||
|
if (!mission) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (mission.type) {
|
||||||
|
case 'pillage':
|
||||||
|
if (region.type === 'oasis') {
|
||||||
|
resolvePillageOasis(V, region);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new Error(`Unknown mission type: "${ mission.type }"`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function resolvePillageOasis(V: VillageState, region: OasisType) {
|
||||||
|
const mission = region.state.mission;
|
||||||
|
if (!mission) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const unit = getUnitSource('soldier');
|
||||||
|
|
||||||
|
V.resources[region.resource] += mission.unitCount * unit.behavior.caryingCapacity;
|
||||||
|
delete region.state.mission;
|
||||||
|
}
|
@ -2,8 +2,10 @@ 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 pillage from './pillage';
|
||||||
import recruitUnits from './recruitUnits';
|
import recruitUnits from './recruitUnits';
|
||||||
|
import startQuest from './startQuest';
|
||||||
|
import upgradeBuilding from './upgradeBuilding';
|
||||||
|
|
||||||
|
|
||||||
// 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
|
||||||
@ -31,5 +33,7 @@ export function makeMove(move: (...args: any[]) => boolean) {
|
|||||||
export default {
|
export default {
|
||||||
build: makeMove(build),
|
build: makeMove(build),
|
||||||
upgradeBuilding: makeMove(upgradeBuilding),
|
upgradeBuilding: makeMove(upgradeBuilding),
|
||||||
|
pillage: makeMove(pillage),
|
||||||
recruitUnits: makeMove(recruitUnits),
|
recruitUnits: makeMove(recruitUnits),
|
||||||
|
startQuest: makeMove(startQuest),
|
||||||
};
|
};
|
||||||
|
24
src/moves/pillage.ts
Normal file
24
src/moves/pillage.ts
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
import { getRemainingUnitCount } from "../utils";
|
||||||
|
import type { VillageState } from "../village";
|
||||||
|
|
||||||
|
|
||||||
|
export default function pillage(V: VillageState, regionIndex: number, soldiersCount: number) {
|
||||||
|
if (soldiersCount > getRemainingUnitCount(V, 'soldier')) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const region = V.worldmap[regionIndex];
|
||||||
|
|
||||||
|
if (region.state.mission) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
region.state.mission = {
|
||||||
|
type: 'pillage',
|
||||||
|
unitType: 'soldier',
|
||||||
|
unitCount: soldiersCount,
|
||||||
|
remainingTime: region.distance * 10 * 1000,
|
||||||
|
};
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
13
src/moves/startQuest.ts
Normal file
13
src/moves/startQuest.ts
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
import type { VillageState } from "../village";
|
||||||
|
|
||||||
|
export default function startQuest(V: VillageState, questId: number) {
|
||||||
|
const quest = V.quests.find(q => q.id === questId);
|
||||||
|
if (!quest) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
quest.started = true;
|
||||||
|
quest.remainingTime = quest.duration * 1000;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
@ -12,6 +12,10 @@ export default function upgradeBuilding(V: VillageState, buildingId: number) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (building.level >= building.maxLevel) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (!canPayBuildingCost(V, building)) {
|
if (!canPayBuildingCost(V, building)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
34
src/quests.ts
Normal file
34
src/quests.ts
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
import type { QuestType, ResourcesType } from "./types";
|
||||||
|
import { getEmptyResources, random } from "./utils";
|
||||||
|
|
||||||
|
|
||||||
|
let uid = 0;
|
||||||
|
|
||||||
|
|
||||||
|
export function createQuest(level: number): QuestType {
|
||||||
|
const reward = getEmptyResources();
|
||||||
|
const adjustedLevel = level * 2 + 5;
|
||||||
|
const duration = random(adjustedLevel - 2, adjustedLevel + 2);
|
||||||
|
Object.keys(reward).forEach(r => {
|
||||||
|
const resource = r as keyof ResourcesType;
|
||||||
|
reward[resource] = random(
|
||||||
|
duration * 5 - level * 10,
|
||||||
|
duration * 5 + level * 10,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (resource === 'food') {
|
||||||
|
reward[resource] = Math.round(reward[resource] / 3);
|
||||||
|
}
|
||||||
|
else if (resource === 'culture') {
|
||||||
|
reward[resource] = Math.round(reward[resource] / 20);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
id: uid++,
|
||||||
|
duration,
|
||||||
|
reward,
|
||||||
|
level,
|
||||||
|
started: false,
|
||||||
|
};
|
||||||
|
}
|
50
src/types.ts
50
src/types.ts
@ -1,7 +1,7 @@
|
|||||||
import type { Hex } from "./hexgrid";
|
import type { Hex } from "./hexgrid";
|
||||||
|
|
||||||
|
|
||||||
export type GameTab = 'village' | 'resources';
|
export type GameTab = 'village' | 'resources' | 'world';
|
||||||
|
|
||||||
|
|
||||||
export interface CostType {
|
export interface CostType {
|
||||||
@ -24,6 +24,7 @@ export interface BuildingSource {
|
|||||||
name: string;
|
name: string;
|
||||||
type: string;
|
type: string;
|
||||||
autoBuilt?: boolean;
|
autoBuilt?: boolean;
|
||||||
|
maxLevel: number;
|
||||||
cost: (level: number) => CostType;
|
cost: (level: number) => CostType;
|
||||||
behavior: {
|
behavior: {
|
||||||
production?: Function;
|
production?: Function;
|
||||||
@ -58,7 +59,54 @@ export interface UnitType {
|
|||||||
name: string;
|
name: string;
|
||||||
cost: CostType;
|
cost: CostType;
|
||||||
behavior: {
|
behavior: {
|
||||||
|
caryingCapacity: number;
|
||||||
foodIntakePerMinute: number;
|
foodIntakePerMinute: number;
|
||||||
culturePerMinute?: number;
|
culturePerMinute?: number;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export interface MissionType {
|
||||||
|
type: string;
|
||||||
|
unitType: string;
|
||||||
|
unitCount: number;
|
||||||
|
remainingTime: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface BaseRegionType {
|
||||||
|
distance: number;
|
||||||
|
state: {
|
||||||
|
index: number;
|
||||||
|
mission?: MissionType;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export interface OasisType extends BaseRegionType {
|
||||||
|
type: 'oasis';
|
||||||
|
resource: keyof CostType;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export interface BourgadeType extends BaseRegionType {
|
||||||
|
type: 'bourgade';
|
||||||
|
distance: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export type RegionType = OasisType | BourgadeType;
|
||||||
|
|
||||||
|
|
||||||
|
export interface HeroType {
|
||||||
|
id: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export interface QuestType {
|
||||||
|
id: number;
|
||||||
|
duration: number;
|
||||||
|
reward: ResourcesType;
|
||||||
|
level: number;
|
||||||
|
started: boolean;
|
||||||
|
remainingTime?: number;
|
||||||
|
}
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
import { produce } from 'immer';
|
import { produce } from 'immer';
|
||||||
|
|
||||||
import { CULTURE_TO_WIN } from './constants';
|
import { CULTURE_TO_WIN } from './constants';
|
||||||
|
import { resolveMission } from './missions';
|
||||||
import type { ProductionType } from './types';
|
import type { ProductionType } from './types';
|
||||||
import { getProduction, getStorage, shuffle } from './utils';
|
import { getProduction, getStorage, shuffle } from './utils';
|
||||||
import village, { type VillageState } from "./village";
|
import village, { type VillageState } from "./village";
|
||||||
|
import { createQuest } from './quests';
|
||||||
|
|
||||||
|
|
||||||
let lastFrame: number;
|
let lastFrame: number;
|
||||||
@ -32,6 +34,39 @@ export default function update(timestamp: number) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Advance missions.
|
||||||
|
V.worldmap.forEach(region => {
|
||||||
|
if (!region.state.mission) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const mission = region.state.mission;
|
||||||
|
mission.remainingTime -= delta;
|
||||||
|
if (mission.remainingTime <= 0) {
|
||||||
|
resolveMission(V, region);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Advance quests.
|
||||||
|
V.quests.filter(q => q.started).forEach(quest => {
|
||||||
|
if (!quest.remainingTime) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
quest.remainingTime -= delta;
|
||||||
|
if (quest.remainingTime <= 0) {
|
||||||
|
V.resources.wood += quest.reward.wood;
|
||||||
|
V.resources.stone += quest.reward.stone;
|
||||||
|
V.resources.iron += quest.reward.iron;
|
||||||
|
V.resources.food += quest.reward.food;
|
||||||
|
V.resources.culture += quest.reward.culture;
|
||||||
|
|
||||||
|
// Replace the finished quest with a new one.
|
||||||
|
V.quests = V.quests.filter(q => q.id !== quest.id);
|
||||||
|
V.quests.push(createQuest(quest.level + 1));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// Make all buildings and units produce and consume.
|
// Make all buildings and units produce and consume.
|
||||||
const productionPerMinute = getProduction(V);
|
const productionPerMinute = getProduction(V);
|
||||||
const storage = getStorage(V);
|
const storage = getStorage(V);
|
||||||
|
29
src/utils.ts
29
src/utils.ts
@ -1,5 +1,5 @@
|
|||||||
import units from "./data/units";
|
import units from "./data/units";
|
||||||
import type { BuildingType, CostType, ProductionType, ResourcesType } from "./types";
|
import type { BuildingType, CostType, MissionType, ProductionType, ResourcesType } from "./types";
|
||||||
import type { VillageState } from "./village";
|
import type { VillageState } from "./village";
|
||||||
|
|
||||||
|
|
||||||
@ -39,7 +39,7 @@ export function getProduction(villageState: VillageState): ResourcesType {
|
|||||||
.reduce(_reduceResources, production);
|
.reduce(_reduceResources, production);
|
||||||
|
|
||||||
// Add units production and intake.
|
// Add units production and intake.
|
||||||
['philosopher'].forEach(type => {
|
['philosopher', 'soldier'].forEach(type => {
|
||||||
const unit = getUnitSource(type);
|
const unit = getUnitSource(type);
|
||||||
const unitCount = villageState.units[type] || 0;
|
const unitCount = villageState.units[type] || 0;
|
||||||
|
|
||||||
@ -49,7 +49,7 @@ export function getProduction(villageState: VillageState): ResourcesType {
|
|||||||
|
|
||||||
// Add culture production for Philosophers.
|
// Add culture production for Philosophers.
|
||||||
if (type === 'philosopher') {
|
if (type === 'philosopher') {
|
||||||
const outputPerMinute = unit.behavior.culturePerMinute;
|
const outputPerMinute = unit.behavior.culturePerMinute || 0;
|
||||||
production.culture += outputPerMinute * unitCount;
|
production.culture += outputPerMinute * unitCount;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -88,6 +88,14 @@ export function getUnitSource(unitType: string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export function getRemainingUnitCount(V: VillageState, unitType: string) {
|
||||||
|
let total = V.units[unitType] || 0;
|
||||||
|
const missions = V.worldmap.filter(r => r.state.mission?.unitType === unitType).map(r => r.state.mission);
|
||||||
|
missions.forEach(m => total -= m?.unitCount || 0);
|
||||||
|
return total;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
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);
|
||||||
}
|
}
|
||||||
@ -122,6 +130,21 @@ export function shuffle<T>(array: Array<T>): Array<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a random integer in the range [ min, max ] (min and max can be returned).
|
||||||
|
* @param min integer
|
||||||
|
* @param max integer
|
||||||
|
* @returns integer
|
||||||
|
*/
|
||||||
|
export function random(min: number, max?: number) {
|
||||||
|
if (max == null) {
|
||||||
|
max = min;
|
||||||
|
min = 0;
|
||||||
|
}
|
||||||
|
return min + Math.floor(Math.random() * (max - min + 1.0));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
export function getBuildingUpgradeCost(_V: VillageState, building: BuildingType): CostType {
|
export function getBuildingUpgradeCost(_V: VillageState, building: BuildingType): CostType {
|
||||||
const level = building.level + 1;
|
const level = building.level + 1;
|
||||||
return building.cost(level);
|
return building.cost(level);
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
import { writable } from "svelte/store";
|
import { writable } from "svelte/store";
|
||||||
|
|
||||||
import { createBuilding } from "./create";
|
import { createBuilding } from "./create";
|
||||||
|
import worldmap from "./data/worldmap";
|
||||||
import { getTilesAtDistance, Hex } from "./hexgrid";
|
import { getTilesAtDistance, Hex } from "./hexgrid";
|
||||||
import type { BuildingType, ResourcesType } from "./types";
|
import type { BuildingType, QuestType, RegionType, ResourcesType } from "./types";
|
||||||
import { getKeysAsNumbers, shuffle } from "./utils";
|
import { getKeysAsNumbers, shuffle } from "./utils";
|
||||||
|
import { createQuest } from "./quests";
|
||||||
|
|
||||||
|
|
||||||
type Board = {
|
type Board = {
|
||||||
@ -21,6 +23,8 @@ export interface VillageState {
|
|||||||
resources: ResourcesType;
|
resources: ResourcesType;
|
||||||
villageTiles: Board;
|
villageTiles: Board;
|
||||||
outsideTiles: Board;
|
outsideTiles: Board;
|
||||||
|
worldmap: RegionType[];
|
||||||
|
quests: QuestType[];
|
||||||
victory: boolean;
|
victory: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -63,6 +67,28 @@ function getInitialOutsideBoard() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function getInitialWorldmap(): RegionType[] {
|
||||||
|
return worldmap.map((r, index) => {
|
||||||
|
const region = r as RegionType;
|
||||||
|
return {
|
||||||
|
...region,
|
||||||
|
state: {
|
||||||
|
index,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function getInitialQuests(): QuestType[] {
|
||||||
|
return [
|
||||||
|
createQuest(1),
|
||||||
|
createQuest(1),
|
||||||
|
createQuest(1),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
function getInitialState() {
|
function getInitialState() {
|
||||||
const state: VillageState = {
|
const state: VillageState = {
|
||||||
buildings: [],
|
buildings: [],
|
||||||
@ -76,6 +102,8 @@ function getInitialState() {
|
|||||||
},
|
},
|
||||||
villageTiles: getInitialVillageBoard(),
|
villageTiles: getInitialVillageBoard(),
|
||||||
outsideTiles: getInitialOutsideBoard(),
|
outsideTiles: getInitialOutsideBoard(),
|
||||||
|
worldmap: getInitialWorldmap(),
|
||||||
|
quests: getInitialQuests(),
|
||||||
victory: false,
|
victory: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -103,7 +131,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 = newBuilding.type === 'field' ? 1 : 10;
|
newBuilding.level = 1; //newBuilding.type === 'field' ? 1 : 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