import { createHero } from "../create"; import type { BuildingType } from "../types"; import { getEmptyResources } from "../utils"; import type { VillageState } from "../village"; function getStandardTimeToBuild(level: number) { return Math.round(Math.pow(level, 1 / 0.8) + 2); } function getResourceBuildingCost(level: number, initial: number) { return initial * level * (level - 1); } function getStorageBuildingCost(level: number, initial: number) { return initial * Math.round( (level + level * level) / 3); } function getUnitBuildingCost(level: number, initial: number) { return initial * Math.round( (level + level * level) / 2); } function getMultiplierBuildingCost(level: number, initial: number) { return initial * Math.round( (level + level * level) / 3); } export default [ { type: 'townhall', name: 'Town Hall', autoBuilt: true, maxLevel: 20, requiredTownhallLevel: 0, cost: (level: number) => { return { wood: getResourceBuildingCost(level, 10), stone: getResourceBuildingCost(level, 15), iron: getResourceBuildingCost(level, 20), food: getResourceBuildingCost(level, 5), }; }, timeToBuild: getStandardTimeToBuild, behavior: { storage: (_V: VillageState, _self: BuildingType) => { return { 'wood': 100, 'stone': 100, 'iron': 100, 'food': 100, } }, constructionTimeReductionPerLevel: 0.025, }, }, { type: 'woodcutter', name: 'Woodcutter', autoBuilt: true, maxLevel: 20, requiredTownhallLevel: 0, cost: (level: number) => { return { wood: getResourceBuildingCost(level, 6), stone: getResourceBuildingCost(level, 10), iron: getResourceBuildingCost(level, 14), food: getResourceBuildingCost(level, 10), }; }, timeToBuild: getStandardTimeToBuild, behavior: { production: (V: VillageState, self: BuildingType) => { const prod = getEmptyResources(); const outputPerMinute = 5 * (self.level * self.level); prod.wood = outputPerMinute; const intakePerMinute = Math.ceil(self.level / 5); prod.food = -intakePerMinute; return prod; }, }, }, { type: 'mine', name: 'Mine', autoBuilt: true, maxLevel: 20, requiredTownhallLevel: 0, cost: (level: number) => { return { wood: getResourceBuildingCost(level, 10), stone: getResourceBuildingCost(level, 14), iron: getResourceBuildingCost(level, 6), food: getResourceBuildingCost(level, 10), }; }, timeToBuild: getStandardTimeToBuild, behavior: { production: (V: VillageState, self: BuildingType) => { const prod = getEmptyResources(); const outputPerMinute = 5 * (self.level * self.level); prod.iron = outputPerMinute; const intakePerMinute = Math.ceil(self.level / 5); prod.food = -intakePerMinute; return prod; }, }, }, { type: 'pit', name: 'Pit', autoBuilt: true, maxLevel: 20, requiredTownhallLevel: 0, cost: (level: number) => { return { wood: getResourceBuildingCost(level, 14), stone: getResourceBuildingCost(level, 6), iron: getResourceBuildingCost(level, 10), food: getResourceBuildingCost(level, 10), }; }, timeToBuild: getStandardTimeToBuild, behavior: { production: (V: VillageState, self: BuildingType) => { const prod = getEmptyResources(); const outputPerMinute = 5 * (self.level * self.level); prod.stone = outputPerMinute; const intakePerMinute = Math.ceil(self.level / 5); prod.food = -intakePerMinute; return prod; }, }, }, { type: 'field', name: 'Field', autoBuilt: true, maxLevel: 20, requiredTownhallLevel: 0, cost: (level: number) => { return { wood: getResourceBuildingCost(level, 14), stone: getResourceBuildingCost(level, 14), iron: getResourceBuildingCost(level, 12), food: getResourceBuildingCost(level, 0), }; }, timeToBuild: getStandardTimeToBuild, behavior: { production: (V: VillageState, self: BuildingType) => { const prod = getEmptyResources(); const outputPerMinute = 5 * (self.level * self.level); prod.food = outputPerMinute; return prod; }, }, }, { type: 'warehouse', name: 'Warehouse', maxLevel: 20, requiredTownhallLevel: 0, cost: (level: number) => { return { wood: getStorageBuildingCost(level, 15), stone: getStorageBuildingCost(level, 20), iron: getStorageBuildingCost(level, 10), food: getStorageBuildingCost(level, 15), }; }, timeToBuild: getStandardTimeToBuild, behavior: { storage: (V: VillageState, self: BuildingType) => { const x = self.level; const capacity = ( ( ( x + ( x * x ) ) / 2 ) + 3 ) * 25; return { 'wood': capacity, 'stone': capacity, 'iron': capacity, 'food': 0, }; }, }, }, { type: 'granary', name: 'Granary', maxLevel: 20, requiredTownhallLevel: 0, cost: (level: number) => { return { wood: getStorageBuildingCost(level, 12), stone: getStorageBuildingCost(level, 22), iron: getStorageBuildingCost(level, 10), food:getStorageBuildingCost(level, 6), }; }, timeToBuild: getStandardTimeToBuild, behavior: { storage: (V: VillageState, self: BuildingType) => { const x = self.level; const capacity = ( ( ( x + ( x * x ) ) / 2 ) + 3 ) * 25; return { 'wood': 0, 'stone': 0, 'iron': 0, 'food': capacity, }; }, }, }, { type: 'great-warehouse', name: 'Great Warehouse', maxLevel: 20, requiredTownhallLevel: 15, cost: (level: number) => { return { wood: getStorageBuildingCost(level, 150), stone: getStorageBuildingCost(level, 200), iron: getStorageBuildingCost(level, 100), food: getStorageBuildingCost(level, 150), }; }, timeToBuild: (level: number) => getStandardTimeToBuild(level) * 2, behavior: { storage: (V: VillageState, self: BuildingType) => { const x = self.level; const capacity = ( ( ( x + ( x * x ) ) / 2 ) + 3 ) * 250; return { 'wood': capacity, 'stone': capacity, 'iron': capacity, 'food': 0, }; }, }, }, { type: 'great-granary', name: 'Great Granary', maxLevel: 20, requiredTownhallLevel: 15, cost: (level: number) => { return { wood: getStorageBuildingCost(level, 120), stone: getStorageBuildingCost(level, 220), iron: getStorageBuildingCost(level, 100), food:getStorageBuildingCost(level, 60), }; }, timeToBuild: (level: number) => getStandardTimeToBuild(level) * 2, behavior: { storage: (V: VillageState, self: BuildingType) => { const x = self.level; const capacity = ( ( ( x + ( x * x ) ) / 2 ) + 3 ) * 250; return { 'wood': 0, 'stone': 0, 'iron': 0, 'food': capacity, }; }, }, }, { type: 'university', name: 'University', maxLevel: 20, requiredTownhallLevel: 5, cost: (level: number) => { return { wood: getUnitBuildingCost(level, 75), stone: getUnitBuildingCost(level, 90), iron: getUnitBuildingCost(level, 50), food: getUnitBuildingCost(level, 45), }; }, timeToBuild: getStandardTimeToBuild, 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, }, }, }, { type: 'barracks', name: 'Barracks', maxLevel: 20, requiredTownhallLevel: 3, cost: (level: number) => { return { wood: getUnitBuildingCost(level, 60), stone: getUnitBuildingCost(level, 30), iron: getUnitBuildingCost(level, 90), food: getUnitBuildingCost(level, 40), }; }, timeToBuild: getStandardTimeToBuild, 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, }, }, }, { type: 'palace', name: 'Palace', maxLevel: 10, unique: true, requiredTownhallLevel: 10, cost: (level: number) => { return { wood: getStorageBuildingCost(level, 200), stone: getStorageBuildingCost(level, 240), iron: getStorageBuildingCost(level, 110), food: getStorageBuildingCost(level, 70), }; }, timeToBuild: getStandardTimeToBuild, behavior: { production: (V: VillageState, self: BuildingType) => { const prod = getEmptyResources(); prod.food = self.level * -30; return prod; }, triggers: { onLevelUp: (V: VillageState, self: BuildingType) => { if (self.level === 5 || self.level === 10) { // Create a new hero. V.heroes.push(createHero()); } }, }, }, }, { type: 'sawmill', name: 'Sawmill', maxLevel: 5, unique: true, requiredTownhallLevel: 7, cost: (level: number) => { return { wood: getMultiplierBuildingCost(level, 440), stone: getMultiplierBuildingCost(level, 610), iron: getMultiplierBuildingCost(level, 870), food: getMultiplierBuildingCost(level, 700), }; }, timeToBuild: (level: number) => getStandardTimeToBuild(level) * 3, behavior: { production: (V: VillageState, self: BuildingType) => { const resourceProd = V.buildings .filter(b => b.type === 'woodcutter') .map(f => f.behavior.production?.(V, f).wood) .reduce((acc, f) => acc + f, 0); const prod = getEmptyResources(); prod.wood = resourceProd * self.level * 0.05; return prod; }, }, }, { type: 'stonecutter', name: 'Stonecutter', maxLevel: 5, unique: true, requiredTownhallLevel: 7, cost: (level: number) => { return { wood: getMultiplierBuildingCost(level, 870), stone: getMultiplierBuildingCost(level, 440), iron: getMultiplierBuildingCost(level, 610), food: getMultiplierBuildingCost(level, 700), }; }, timeToBuild: (level: number) => getStandardTimeToBuild(level) * 3, behavior: { production: (V: VillageState, self: BuildingType) => { const resourceProd = V.buildings .filter(b => b.type === 'pit') .map(f => f.behavior.production?.(V, f).stone) .reduce((acc, f) => acc + f, 0); const prod = getEmptyResources(); prod.stone = resourceProd * self.level * 0.05; return prod; }, }, }, { type: 'blacksmith', name: 'Blacksmith', maxLevel: 5, unique: true, requiredTownhallLevel: 7, cost: (level: number) => { return { wood: getMultiplierBuildingCost(level, 610), stone: getMultiplierBuildingCost(level, 870), iron: getMultiplierBuildingCost(level, 440), food: getMultiplierBuildingCost(level, 700), }; }, timeToBuild: (level: number) => getStandardTimeToBuild(level) * 3, behavior: { production: (V: VillageState, self: BuildingType) => { const resourceProd = V.buildings .filter(b => b.type === 'mine') .map(f => f.behavior.production?.(V, f).iron) .reduce((acc, f) => acc + f, 0); const prod = getEmptyResources(); prod.iron = resourceProd * self.level * 0.05; return prod; }, }, }, { type: 'bakery', name: 'Bakery', maxLevel: 5, unique: true, requiredTownhallLevel: 7, cost: (level: number) => { return { wood: getMultiplierBuildingCost(level, 670), stone: getMultiplierBuildingCost(level, 740), iron: getMultiplierBuildingCost(level, 670), food: getMultiplierBuildingCost(level, 520), }; }, timeToBuild: (level: number) => getStandardTimeToBuild(level) * 3, behavior: { production: (V: VillageState, self: BuildingType) => { const fields = V.buildings.filter(b => b.type === 'field'); const fieldFoodProd = fields .map(f => f.behavior.production?.(V, f).food) .reduce((acc, f) => acc + f, 0); const prod = getEmptyResources(); prod.food = fieldFoodProd * self.level * 0.05; return prod; }, }, }, { type: 'wonder', name: 'World Wonder', maxLevel: 1, unique: true, requiredTownhallLevel: 20, cost: () => { return { wood: 42000, stone: 42000, iron: 42000, food: 38000, }; }, timeToBuild: () => 120, behavior: { production: (V: VillageState, self: BuildingType) => { const prod = getEmptyResources(); prod.food = self.level * -300; return prod; }, triggers: { onLevelUp: (V: VillageState, self: BuildingType) => { if (self.level === 1) { // Gain a lot of culture. V.resources.culture += 18000; } }, }, }, }, ];