168 lines
6.7 KiB
JavaScript
168 lines
6.7 KiB
JavaScript
class BuildingSystem {
|
|
constructor(scene) {
|
|
this.scene = scene;
|
|
this.isBuildMode = false;
|
|
this.selectedBuilding = 'fence'; // fence, wall, house
|
|
|
|
this.buildingsData = {
|
|
fence: { name: 'Fence', cost: { wood: 2 }, w: 1, h: 1 },
|
|
wall: { name: 'Stone Wall', cost: { stone: 2 }, w: 1, h: 1 },
|
|
house: { name: 'House', cost: { wood: 20, stone: 20, gold: 50 }, w: 1, h: 1 }, // Visual is bigger but anchor is 1 tile
|
|
barn: { name: 'Barn', cost: { wood: 50, stone: 10 }, w: 1, h: 1 },
|
|
silo: { name: 'Silo', cost: { wood: 30, stone: 30 }, w: 1, h: 1 },
|
|
stable: { name: 'Stable', cost: { wood: 40, stone: 20 }, w: 1, h: 1 },
|
|
greenhouse: { name: 'Greenhouse', cost: { glass: 20, wood: 15 }, w: 2, h: 2 } // Winter farming
|
|
};
|
|
|
|
// Textures init
|
|
if (!this.scene.textures.exists('struct_fence')) TextureGenerator.createStructureSprite(this.scene, 'struct_fence', 'fence');
|
|
if (!this.scene.textures.exists('struct_wall')) TextureGenerator.createStructureSprite(this.scene, 'struct_wall', 'wall');
|
|
if (!this.scene.textures.exists('struct_house')) TextureGenerator.createStructureSprite(this.scene, 'struct_house', 'house');
|
|
if (!this.scene.textures.exists('struct_barn')) TextureGenerator.createStructureSprite(this.scene, 'struct_barn', 'barn');
|
|
if (this.scene.textures.exists('struct_silo')) TextureGenerator.createStructureSprite(this.scene, 'struct_silo', 'silo');
|
|
if (!this.scene.textures.exists('struct_stable')) TextureGenerator.createStructureSprite(this.scene, 'struct_stable', 'stable');
|
|
// House Lv2 Texture
|
|
TextureGenerator.createStructureSprite(this.scene, 'struct_house_lv2', 'house_lv2');
|
|
}
|
|
|
|
toggleBuildMode() {
|
|
this.isBuildMode = !this.isBuildMode;
|
|
console.log(`🔨 Build Mode: ${this.isBuildMode}`);
|
|
|
|
// Update UI
|
|
const uiScene = this.scene.scene.get('UIScene');
|
|
if (uiScene) {
|
|
uiScene.toggleBuildMenu(this.isBuildMode);
|
|
}
|
|
}
|
|
|
|
selectBuilding(type) {
|
|
if (this.buildingsData[type]) {
|
|
this.selectedBuilding = type;
|
|
console.log(`🔨 Selected: ${this.selectedBuilding}`);
|
|
|
|
// UI feedback?
|
|
const uiScene = this.scene.scene.get('UIScene');
|
|
if (uiScene) uiScene.updateBuildSelection(type);
|
|
}
|
|
}
|
|
|
|
tryBuild(gridX, gridY) {
|
|
if (!this.isBuildMode) return false;
|
|
|
|
const building = this.buildingsData[this.selectedBuilding];
|
|
const inv = this.scene.inventorySystem;
|
|
const terrain = this.scene.terrainSystem;
|
|
|
|
// 1. Check Cost
|
|
if (building.cost.wood) {
|
|
if (!inv.hasItem('wood', building.cost.wood)) {
|
|
console.log('❌ Not enough Wood!');
|
|
this.showFloatingText('Need Wood!', gridX, gridY, '#FF0000');
|
|
return true; // We handled the click, even if failed
|
|
}
|
|
}
|
|
if (building.cost.stone) {
|
|
if (!inv.hasItem('stone', building.cost.stone)) {
|
|
console.log('❌ Not enough Stone!');
|
|
this.showFloatingText('Need Stone!', gridX, gridY, '#FF0000');
|
|
return true;
|
|
}
|
|
}
|
|
if (building.cost.gold) {
|
|
if (inv.gold < building.cost.gold) {
|
|
console.log('❌ Not enough Gold!');
|
|
this.showFloatingText('Need Gold!', gridX, gridY, '#FF0000');
|
|
return true;
|
|
}
|
|
}
|
|
|
|
// 2. Check Space
|
|
const tile = terrain.getTile(gridX, gridY);
|
|
if (!tile || tile.type === 'water' || tile.hasDecoration || tile.hasCrop || tile.hasBuilding) {
|
|
console.log('❌ Space occupied!');
|
|
this.showFloatingText('Occupied!', gridX, gridY, '#FF0000');
|
|
return true;
|
|
}
|
|
|
|
// 3. Consume Resources
|
|
if (building.cost.wood) inv.removeItem('wood', building.cost.wood);
|
|
if (building.cost.stone) inv.removeItem('stone', building.cost.stone);
|
|
if (building.cost.gold) {
|
|
inv.gold -= building.cost.gold;
|
|
inv.updateUI();
|
|
}
|
|
|
|
// 4. Place Building
|
|
// Using decorations layer for now
|
|
const structType = `struct_${this.selectedBuilding}`;
|
|
terrain.addDecoration(gridX, gridY, structType);
|
|
|
|
// Assume success if no error (addDecoration checks internally but doesn't return value easily, but we checked space before)
|
|
{
|
|
this.showFloatingText(`Built ${building.name}!`, gridX, gridY, '#00FF00');
|
|
|
|
// Build Sound
|
|
if (this.scene.soundManager) {
|
|
this.scene.soundManager.playBuild();
|
|
}
|
|
|
|
// Quest Tracking
|
|
if (this.scene.questSystem) {
|
|
this.scene.questSystem.trackAction(`build_${this.selectedBuilding}`);
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
tryUpgrade(gridX, gridY) {
|
|
const terrain = this.scene.terrainSystem;
|
|
const decKey = `${gridX},${gridY}`;
|
|
const decor = terrain.decorationsMap.get(decKey);
|
|
|
|
if (!decor) return false;
|
|
|
|
// Check if House Lv1
|
|
if (decor.type === 'struct_house') {
|
|
const cost = { wood: 100, stone: 50, gold: 100 };
|
|
const inv = this.scene.inventorySystem;
|
|
|
|
// Check Resources
|
|
if (!inv.hasItem('wood', cost.wood) || !inv.hasItem('stone', cost.stone) || inv.gold < cost.gold) {
|
|
this.showFloatingText('Upgrade Cost: 100 Wood, 50 Stone, 100G', gridX, gridY, '#FF4444');
|
|
return true;
|
|
}
|
|
|
|
// Pay
|
|
inv.removeItem('wood', cost.wood);
|
|
inv.removeItem('stone', cost.stone);
|
|
inv.gold -= cost.gold;
|
|
inv.updateUI();
|
|
|
|
// Perform Upgrade
|
|
terrain.removeDecoration(gridX, gridY);
|
|
terrain.addDecoration(gridX, gridY, 'struct_house_lv2'); // Re-add Lv2
|
|
|
|
this.showFloatingText('HOUSE CRADED! (Lv. 2)', gridX, gridY, '#00FFFF');
|
|
if (this.scene.soundManager) this.scene.soundManager.playSuccess();
|
|
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
showFloatingText(text, gridX, gridY, color) {
|
|
const iso = new IsometricUtils(48, 24);
|
|
const pos = iso.toScreen(gridX, gridY);
|
|
const popup = this.scene.add.text(
|
|
pos.x + this.scene.terrainOffsetX,
|
|
pos.y + this.scene.terrainOffsetY - 40,
|
|
text,
|
|
{ fontSize: '14px', fill: color, stroke: '#000', strokeThickness: 3 }
|
|
).setOrigin(0.5);
|
|
this.scene.tweens.add({ targets: popup, y: popup.y - 30, alpha: 0, duration: 2000, onComplete: () => popup.destroy() });
|
|
}
|
|
}
|