posodobitev
This commit is contained in:
226
src/systems/BuildSystem.js
Normal file
226
src/systems/BuildSystem.js
Normal file
@@ -0,0 +1,226 @@
|
||||
class BuildSystem {
|
||||
constructor(scene) {
|
||||
this.scene = scene;
|
||||
this.buildMode = false;
|
||||
this.selectedBuilding = 'fence';
|
||||
this.previewSprite = null;
|
||||
this.placedBuildings = [];
|
||||
|
||||
// Building definitions
|
||||
this.buildings = {
|
||||
'fence': {
|
||||
name: 'Fence (Old)',
|
||||
textureKey: 'fence_isometric',
|
||||
cost: { wood: 2 },
|
||||
collision: false,
|
||||
scale: 0.3
|
||||
},
|
||||
'fence_post': {
|
||||
name: 'Fence Post',
|
||||
textureKey: 'fence_post',
|
||||
cost: { wood: 1 },
|
||||
collision: false,
|
||||
scale: 0.2
|
||||
},
|
||||
'fence_horizontal': {
|
||||
name: 'Fence →',
|
||||
textureKey: 'fence_horizontal',
|
||||
cost: { wood: 2 },
|
||||
collision: false,
|
||||
scale: 0.2
|
||||
},
|
||||
'fence_vertical': {
|
||||
name: 'Fence ↓',
|
||||
textureKey: 'fence_vertical',
|
||||
cost: { wood: 2 },
|
||||
collision: false,
|
||||
scale: 0.2
|
||||
},
|
||||
'fence_corner': {
|
||||
name: 'Fence ⌞',
|
||||
textureKey: 'fence_corner',
|
||||
cost: { wood: 2 },
|
||||
collision: false,
|
||||
scale: 0.2
|
||||
},
|
||||
'barn': {
|
||||
name: 'Barn',
|
||||
textureKey: 'barn_isometric',
|
||||
cost: { wood: 40, stone: 20 },
|
||||
collision: true,
|
||||
scale: 0.5
|
||||
},
|
||||
'grave': {
|
||||
name: 'Grave',
|
||||
textureKey: 'grave_zombie',
|
||||
cost: { stone: 10 },
|
||||
collision: false,
|
||||
scale: 0.3
|
||||
},
|
||||
'farmhouse': {
|
||||
name: 'Farmhouse',
|
||||
textureKey: 'farmhouse_isometric',
|
||||
cost: { wood: 50, stone: 30, gold: 100 },
|
||||
collision: true,
|
||||
scale: 0.5
|
||||
},
|
||||
'blacksmith': {
|
||||
name: 'Blacksmith',
|
||||
textureKey: 'blacksmith_workshop',
|
||||
cost: { wood: 30, stone: 40, gold: 80 },
|
||||
collision: true,
|
||||
scale: 0.45
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
toggleBuildMode() {
|
||||
this.buildMode = !this.buildMode;
|
||||
console.log(`Build Mode: ${this.buildMode ? 'ON' : 'OFF'}`);
|
||||
|
||||
// Notify UI
|
||||
const uiScene = this.scene.scene.get('UIScene');
|
||||
if (uiScene) {
|
||||
uiScene.toggleBuildMenu(this.buildMode);
|
||||
}
|
||||
|
||||
// Show/hide preview
|
||||
if (this.buildMode) {
|
||||
this.createPreview();
|
||||
} else {
|
||||
this.destroyPreview();
|
||||
}
|
||||
|
||||
return this.buildMode;
|
||||
}
|
||||
|
||||
selectBuilding(buildingId) {
|
||||
if (!this.buildings[buildingId]) return;
|
||||
this.selectedBuilding = buildingId;
|
||||
|
||||
// Update UI
|
||||
const uiScene = this.scene.scene.get('UIScene');
|
||||
if (uiScene) {
|
||||
uiScene.updateBuildSelection(this.buildings[buildingId].name);
|
||||
}
|
||||
|
||||
// Refresh preview
|
||||
if (this.buildMode) {
|
||||
this.destroyPreview();
|
||||
this.createPreview();
|
||||
}
|
||||
}
|
||||
|
||||
createPreview() {
|
||||
const building = this.buildings[this.selectedBuilding];
|
||||
if (!this.scene.textures.exists(building.textureKey)) {
|
||||
console.warn(`Texture not found: ${building.textureKey}`);
|
||||
return;
|
||||
}
|
||||
|
||||
this.previewSprite = this.scene.add.sprite(0, 0, building.textureKey);
|
||||
this.previewSprite.setOrigin(0.5, 1);
|
||||
this.previewSprite.setAlpha(0.6);
|
||||
this.previewSprite.setDepth(10000); // Always on top
|
||||
this.previewSprite.setScale(building.scale || 1.0);
|
||||
}
|
||||
|
||||
destroyPreview() {
|
||||
if (this.previewSprite) {
|
||||
this.previewSprite.destroy();
|
||||
this.previewSprite = null;
|
||||
}
|
||||
}
|
||||
|
||||
update() {
|
||||
if (!this.buildMode || !this.previewSprite) return;
|
||||
|
||||
// Follow mouse
|
||||
const pointer = this.scene.input.activePointer;
|
||||
const worldPoint = this.scene.cameras.main.getWorldPoint(pointer.x, pointer.y);
|
||||
const gridPos = this.scene.iso.toGrid(worldPoint.x, worldPoint.y);
|
||||
const screenPos = this.scene.iso.toScreen(gridPos.x, gridPos.y);
|
||||
|
||||
this.previewSprite.setPosition(screenPos.x, screenPos.y);
|
||||
|
||||
// Check if can place
|
||||
const canPlace = this.canPlaceAt(gridPos.x, gridPos.y);
|
||||
this.previewSprite.setTint(canPlace ? 0x00ff00 : 0xff0000);
|
||||
|
||||
// Place on click
|
||||
if (pointer.isDown && canPlace) {
|
||||
this.placeBuilding(gridPos.x, gridPos.y);
|
||||
}
|
||||
}
|
||||
|
||||
canPlaceAt(gridX, gridY) {
|
||||
// Check if already has building
|
||||
const exists = this.placedBuildings.find(b => b.gridX === gridX && b.gridY === gridY);
|
||||
if (exists) return false;
|
||||
|
||||
// Check terrain (only on farm tiles)
|
||||
if (!this.scene.terrainSystem) return false;
|
||||
const tile = this.scene.terrainSystem.getTile(gridX, gridY);
|
||||
if (!tile || tile.type !== 'farm') return false;
|
||||
|
||||
// Check cost
|
||||
const building = this.buildings[this.selectedBuilding];
|
||||
if (!this.hasResources(building.cost)) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
hasResources(cost) {
|
||||
const inv = this.scene.inventorySystem;
|
||||
if (!inv) return false;
|
||||
|
||||
for (const [resource, amount] of Object.entries(cost)) {
|
||||
if (resource === 'gold') {
|
||||
if (inv.gold < amount) return false;
|
||||
} else {
|
||||
if (!inv.hasItem(resource, amount)) return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
placeBuilding(gridX, gridY) {
|
||||
const building = this.buildings[this.selectedBuilding];
|
||||
|
||||
// Consume resources
|
||||
const inv = this.scene.inventorySystem;
|
||||
for (const [resource, amount] of Object.entries(building.cost)) {
|
||||
if (resource === 'gold') {
|
||||
inv.gold -= amount;
|
||||
} else {
|
||||
inv.removeItem(resource, amount);
|
||||
}
|
||||
}
|
||||
|
||||
// Create sprite
|
||||
const screenPos = this.scene.iso.toScreen(gridX, gridY);
|
||||
const sprite = this.scene.add.sprite(screenPos.x, screenPos.y, building.textureKey);
|
||||
sprite.setOrigin(0.5, 1);
|
||||
sprite.setScale(building.scale || 1.0);
|
||||
sprite.setDepth(this.scene.iso.getDepth(gridX, gridY) + 5); // Above terrain
|
||||
|
||||
// Store
|
||||
this.placedBuildings.push({
|
||||
gridX,
|
||||
gridY,
|
||||
type: this.selectedBuilding,
|
||||
sprite,
|
||||
collision: building.collision
|
||||
});
|
||||
|
||||
console.log(`🏗️ Placed ${building.name} at (${gridX}, ${gridY})`);
|
||||
|
||||
// Update UI
|
||||
this.scene.events.emit('update-inventory');
|
||||
}
|
||||
|
||||
isCollisionAt(gridX, gridY) {
|
||||
const building = this.placedBuildings.find(b => b.gridX === gridX && b.gridY === gridY);
|
||||
return building ? building.collision : false;
|
||||
}
|
||||
}
|
||||
@@ -1,239 +1,216 @@
|
||||
const CROP_DATA = {
|
||||
'wheat': {
|
||||
name: 'Wheat',
|
||||
seedItem: 'seeds_wheat',
|
||||
harvestItem: 'wheat',
|
||||
stages: 4,
|
||||
growthTime: 10, // Seconds per stage (Total 30s)
|
||||
regrow: false,
|
||||
color: 0xffdd00
|
||||
},
|
||||
'corn': {
|
||||
name: 'Corn',
|
||||
seedItem: 'seeds_corn',
|
||||
harvestItem: 'corn',
|
||||
stages: 4,
|
||||
growthTime: 15, // Slower (Total 45s)
|
||||
regrow: true, // Corn regrows!
|
||||
regrowStage: 2, // Goes back to stage 2
|
||||
color: 0xffaa00
|
||||
}
|
||||
};
|
||||
|
||||
class FarmingSystem {
|
||||
constructor(scene) {
|
||||
this.scene = scene;
|
||||
this.growthTimer = 0;
|
||||
this.growthTickRate = 1000;
|
||||
}
|
||||
this.crops = []; // Active crops in world
|
||||
|
||||
// Called by InteractionSystem
|
||||
interact(gridX, gridY, toolType) {
|
||||
const terrain = this.scene.terrainSystem;
|
||||
const tile = terrain.getTile(gridX, gridY);
|
||||
|
||||
if (!tile) return false;
|
||||
|
||||
// 1. HARVEST
|
||||
if (tile.hasCrop) {
|
||||
const crop = terrain.cropsMap.get(`${gridX},${gridY}`);
|
||||
if (crop && crop.stage === CROP_DATA[crop.type].stages) {
|
||||
this.harvest(gridX, gridY);
|
||||
return true;
|
||||
// Crop definitions
|
||||
this.cropTypes = {
|
||||
'carrot': {
|
||||
name: 'Carrot',
|
||||
growthStages: 4,
|
||||
daysPerStage: 1,
|
||||
sellPrice: 10,
|
||||
seedCost: 5
|
||||
},
|
||||
'wheat': {
|
||||
name: 'Wheat',
|
||||
growthStages: 4,
|
||||
daysPerStage: 2,
|
||||
sellPrice: 15,
|
||||
seedCost: 8
|
||||
}
|
||||
}
|
||||
|
||||
// 2. TILLING
|
||||
if (toolType === 'hoe') {
|
||||
const typeName = tile.type.name || tile.type;
|
||||
if (typeName.includes('grass') || typeName === 'dirt') {
|
||||
if (!tile.hasDecoration && !tile.hasCrop) {
|
||||
terrain.setTileType(gridX, gridY, 'farmland');
|
||||
if (this.scene.soundManager) this.scene.soundManager.playDig();
|
||||
|
||||
// Archaeology: Chance to find artefact
|
||||
if (Math.random() < 0.15) {
|
||||
if (this.scene.interactionSystem) { // Using InteractionSystem spawnLoot wrapper or LootSystem directly?
|
||||
// InteractionSystem has spawnLoot method that wraps inventory adding and text.
|
||||
this.scene.interactionSystem.spawnLoot(gridX, gridY, 'artefact_old', 1);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 3. PLANTING
|
||||
// Check if tool is a seed
|
||||
const isSeed = toolType.startsWith('seeds_') || toolType === 'seeds';
|
||||
|
||||
if (isSeed) {
|
||||
const typeName = tile.type.name || tile.type;
|
||||
if (typeName === 'farmland' && !tile.hasCrop && !tile.hasDecoration) {
|
||||
// Determine crop type from seed name
|
||||
// "seeds_corn" -> "corn", "seeds" -> "wheat" (default)
|
||||
let cropType = 'wheat';
|
||||
if (toolType === 'seeds_corn') cropType = 'corn';
|
||||
if (toolType === 'seeds_wheat') cropType = 'wheat';
|
||||
|
||||
this.plant(gridX, gridY, cropType);
|
||||
|
||||
// Consumption
|
||||
if (this.scene.inventorySystem) {
|
||||
this.scene.inventorySystem.removeItem(toolType, 1);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// 4. WATERING
|
||||
if (toolType === 'watering_can') {
|
||||
if (tile.hasCrop) {
|
||||
const crop = terrain.cropsMap.get(`${gridX},${gridY}`);
|
||||
if (crop && !crop.isWatered) {
|
||||
this.waterCrop(gridX, gridY);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
plant(x, y, type = 'wheat') {
|
||||
const terrain = this.scene.terrainSystem;
|
||||
const data = CROP_DATA[type];
|
||||
|
||||
const cropData = {
|
||||
gridX: x,
|
||||
gridY: y,
|
||||
stage: 1,
|
||||
type: type,
|
||||
timer: 0,
|
||||
maxTime: data.growthTime
|
||||
};
|
||||
terrain.addCrop(x, y, cropData);
|
||||
|
||||
if (this.scene.soundManager) {
|
||||
this.scene.soundManager.playPlant();
|
||||
}
|
||||
|
||||
if (this.scene.questSystem) this.scene.questSystem.trackAction('plant');
|
||||
console.log(`🌱 Planted ${type} at ${x},${y}`);
|
||||
}
|
||||
|
||||
harvest(x, y) {
|
||||
const terrain = this.scene.terrainSystem;
|
||||
const crop = terrain.cropsMap.get(`${x},${y}`);
|
||||
if (!crop) return;
|
||||
// Till soil at grid position
|
||||
tillSoil(gridX, gridY) {
|
||||
if (!this.scene.terrainSystem) return false;
|
||||
|
||||
const data = CROP_DATA[crop.type];
|
||||
|
||||
// Sound
|
||||
if (this.scene.soundManager) {
|
||||
this.scene.soundManager.playHarvest();
|
||||
// Check if already tilled
|
||||
const key = `${gridX},${gridY}`;
|
||||
if (this.isTilled(gridX, gridY)) {
|
||||
console.log('Already tilled!');
|
||||
return false;
|
||||
}
|
||||
|
||||
// Loot
|
||||
if (this.scene.interactionSystem) {
|
||||
this.scene.interactionSystem.spawnLoot(x, y, data.harvestItem, 1);
|
||||
|
||||
// Chance for seeds
|
||||
if (Math.random() > 0.4) {
|
||||
this.scene.interactionSystem.spawnLoot(x, y, data.seedItem, 1);
|
||||
}
|
||||
|
||||
// Extra harvest chance
|
||||
if (Math.random() > 0.5) {
|
||||
this.scene.interactionSystem.spawnLoot(x, y, data.harvestItem, 1);
|
||||
}
|
||||
|
||||
// XP Gain
|
||||
if (this.scene.statsSystem) {
|
||||
this.scene.statsSystem.addXP(data.harvestItem === 'corn' ? 15 : 10);
|
||||
}
|
||||
// Mark as tilled in terrain
|
||||
if (!this.scene.terrainSystem.tilledSoil) {
|
||||
this.scene.terrainSystem.tilledSoil = new Set();
|
||||
}
|
||||
|
||||
// Regrow or Destroy
|
||||
if (data.regrow) {
|
||||
crop.stage = data.regrowStage;
|
||||
crop.timer = 0;
|
||||
crop.isWatered = false; // Reset watering status
|
||||
terrain.updateCropVisual(x, y, crop.stage);
|
||||
console.log(`🔄 ${crop.type} regrowing...`);
|
||||
} else {
|
||||
terrain.removeCrop(x, y);
|
||||
this.scene.terrainSystem.tilledSoil.add(key);
|
||||
|
||||
// Visual feedback - place tilled soil sprite
|
||||
const screenPos = this.scene.iso.toScreen(gridX, gridY);
|
||||
|
||||
if (this.scene.textures.exists('soil_tilled')) {
|
||||
const sprite = this.scene.add.sprite(screenPos.x, screenPos.y, 'soil_tilled');
|
||||
sprite.setOrigin(0.5, 1);
|
||||
sprite.setScale(1.0);
|
||||
sprite.setDepth(this.scene.iso.getDepth(gridX, gridY) - 1); // Below crops
|
||||
|
||||
// Store reference
|
||||
if (!this.scene.terrainSystem.tilledSprites) {
|
||||
this.scene.terrainSystem.tilledSprites = new Map();
|
||||
}
|
||||
this.scene.terrainSystem.tilledSprites.set(key, sprite);
|
||||
}
|
||||
|
||||
console.log(`✅ Tilled soil at (${gridX}, ${gridY})`);
|
||||
return true;
|
||||
}
|
||||
|
||||
isTilled(gridX, gridY) {
|
||||
if (!this.scene.terrainSystem || !this.scene.terrainSystem.tilledSoil) return false;
|
||||
return this.scene.terrainSystem.tilledSoil.has(`${gridX},${gridY}`);
|
||||
}
|
||||
|
||||
// Plant seed
|
||||
plantSeed(gridX, gridY, cropType) {
|
||||
if (!this.isTilled(gridX, gridY)) {
|
||||
console.log('Need to till soil first!');
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if already has crop
|
||||
if (this.getCropAt(gridX, gridY)) {
|
||||
console.log('Already has a crop!');
|
||||
return false;
|
||||
}
|
||||
|
||||
// Create crop
|
||||
const crop = {
|
||||
gridX,
|
||||
gridY,
|
||||
type: cropType,
|
||||
stage: 0,
|
||||
daysInStage: 0,
|
||||
plantedDay: this.scene.timeSystem ? this.scene.timeSystem.day : 0
|
||||
};
|
||||
|
||||
this.crops.push(crop);
|
||||
|
||||
// Visual - create sprite
|
||||
this.updateCropSprite(crop);
|
||||
|
||||
// Update farm stats
|
||||
if (this.scene.farmStats) {
|
||||
this.scene.farmStats.cropsPlanted++;
|
||||
}
|
||||
|
||||
console.log(`🌱 Planted ${cropType} at (${gridX}, ${gridY})`);
|
||||
return true;
|
||||
}
|
||||
|
||||
getCropAt(gridX, gridY) {
|
||||
return this.crops.find(c => c.gridX === gridX && c.gridY === gridY);
|
||||
}
|
||||
|
||||
updateCropSprite(crop) {
|
||||
const screenPos = this.scene.iso.toScreen(crop.gridX, crop.gridY);
|
||||
|
||||
// Remove old sprite
|
||||
if (crop.sprite) {
|
||||
crop.sprite.destroy();
|
||||
}
|
||||
|
||||
// Determine texture based on stage
|
||||
let textureKey = `crop_${crop.type}_stage_${crop.stage}`;
|
||||
|
||||
// Fallback textures
|
||||
if (!this.scene.textures.exists(textureKey)) {
|
||||
textureKey = 'carrots_stages'; // Use carrot stages as fallback
|
||||
}
|
||||
|
||||
if (this.scene.textures.exists(textureKey)) {
|
||||
crop.sprite = this.scene.add.sprite(screenPos.x, screenPos.y, textureKey);
|
||||
crop.sprite.setOrigin(0.5, 1);
|
||||
crop.sprite.setScale(0.8);
|
||||
crop.sprite.setDepth(this.scene.iso.getDepth(crop.gridX, crop.gridY));
|
||||
}
|
||||
}
|
||||
|
||||
waterCrop(x, y) {
|
||||
const terrain = this.scene.terrainSystem;
|
||||
const crop = terrain.cropsMap.get(`${x},${y}`);
|
||||
if (!crop) return;
|
||||
// Harvest crop
|
||||
harvestCrop(gridX, gridY) {
|
||||
const crop = this.getCropAt(gridX, gridY);
|
||||
if (!crop) return false;
|
||||
|
||||
crop.isWatered = true;
|
||||
crop.growthBoost = 2.0; // 2x faster growth!
|
||||
const cropDef = this.cropTypes[crop.type];
|
||||
const isRipe = crop.stage >= (cropDef.growthStages - 1);
|
||||
|
||||
// Visual feedback - tint slightly blue
|
||||
const key = `${x},${y}`;
|
||||
if (terrain.visibleCrops.has(key)) {
|
||||
const sprite = terrain.visibleCrops.get(key);
|
||||
sprite.setTint(0xAADDFF); // Light blue tint
|
||||
if (!isRipe) {
|
||||
console.log('Crop not ready yet!');
|
||||
return false;
|
||||
}
|
||||
|
||||
// Sound effect
|
||||
if (this.scene.soundManager) {
|
||||
this.scene.soundManager.playPlant(); // Re-use plant sound for now
|
||||
// Give items
|
||||
if (this.scene.inventorySystem) {
|
||||
this.scene.inventorySystem.addItem(crop.type, 1);
|
||||
}
|
||||
|
||||
// Floating text
|
||||
this.scene.events.emit('show-floating-text', {
|
||||
x: x * 48,
|
||||
y: y * 48,
|
||||
text: '💧 Watered!',
|
||||
color: '#00AAFF'
|
||||
});
|
||||
// Give gold
|
||||
const goldEarned = cropDef.sellPrice;
|
||||
if (this.scene.inventorySystem) {
|
||||
this.scene.inventorySystem.gold += goldEarned;
|
||||
}
|
||||
|
||||
console.log(`💧 Watered crop at ${x},${y}`);
|
||||
// Update farm stats
|
||||
if (this.scene.farmStats) {
|
||||
this.scene.farmStats.totalHarvested++;
|
||||
this.scene.farmStats.goldEarned += goldEarned;
|
||||
}
|
||||
|
||||
// Remove crop
|
||||
if (crop.sprite) crop.sprite.destroy();
|
||||
this.crops = this.crops.filter(c => c !== crop);
|
||||
|
||||
console.log(`🌾 Harvested ${crop.type}! (+${goldEarned} gold)`);
|
||||
|
||||
// Show floating text
|
||||
if (this.scene.events) {
|
||||
this.scene.events.emit('show-floating-text', {
|
||||
x: screenPos.x,
|
||||
y: screenPos.y - 30,
|
||||
text: `+${goldEarned}g`,
|
||||
color: '#FFD700'
|
||||
});
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
update(delta) {
|
||||
this.growthTimer += delta;
|
||||
if (this.growthTimer < 1000) return;
|
||||
const secondsPassed = this.growthTimer / 1000;
|
||||
this.growthTimer = 0;
|
||||
// Update - called each game day
|
||||
updateDay() {
|
||||
this.crops.forEach(crop => {
|
||||
const cropDef = this.cropTypes[crop.type];
|
||||
|
||||
const terrain = this.scene.terrainSystem;
|
||||
if (!terrain) return;
|
||||
crop.daysInStage++;
|
||||
|
||||
for (const [key, crop] of terrain.cropsMap) {
|
||||
const data = CROP_DATA[crop.type];
|
||||
if (!data) continue;
|
||||
// Advance stage?
|
||||
if (crop.daysInStage >= cropDef.daysPerStage) {
|
||||
crop.daysInStage = 0;
|
||||
crop.stage++;
|
||||
|
||||
if (crop.stage < data.stages) {
|
||||
// Apply growth boost if watered
|
||||
const growthMultiplier = crop.growthBoost || 1.0;
|
||||
crop.timer += secondsPassed * growthMultiplier;
|
||||
|
||||
if (crop.timer >= data.growthTime) {
|
||||
crop.stage++;
|
||||
crop.timer = 0;
|
||||
|
||||
// Clear watering boost after growth
|
||||
if (crop.isWatered) {
|
||||
crop.isWatered = false;
|
||||
crop.growthBoost = 1.0;
|
||||
|
||||
// Remove blue tint
|
||||
if (terrain.visibleCrops.has(key)) {
|
||||
const sprite = terrain.visibleCrops.get(key);
|
||||
sprite.clearTint();
|
||||
}
|
||||
}
|
||||
|
||||
terrain.updateCropVisual(crop.gridX, crop.gridY, crop.stage);
|
||||
// Cap at max stage
|
||||
if (crop.stage >= cropDef.growthStages) {
|
||||
crop.stage = cropDef.growthStages - 1;
|
||||
}
|
||||
|
||||
// Update visual
|
||||
this.updateCropSprite(crop);
|
||||
|
||||
console.log(`🌱 Crop grew! Stage ${crop.stage}/${cropDef.growthStages - 1}`);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Update - called each frame
|
||||
update() {
|
||||
// Update sprite depths if camera moved
|
||||
this.crops.forEach(crop => {
|
||||
if (crop.sprite) {
|
||||
crop.sprite.setDepth(this.scene.iso.getDepth(crop.gridX, crop.gridY));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -86,7 +86,7 @@ class InteractionSystem {
|
||||
|
||||
handleTalk(npc) {
|
||||
if (!this.scene.hybridSkillSystem) {
|
||||
npc.toggleState();
|
||||
console.log('Talk with:', npc.type);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -120,7 +120,7 @@ class InteractionSystem {
|
||||
color: color
|
||||
});
|
||||
|
||||
npc.toggleState(); // Stop moving briefly
|
||||
// NPC pauses briefly (handled by AI)
|
||||
}
|
||||
|
||||
handleInteraction(gridX, gridY, isAttack = false) {
|
||||
@@ -247,7 +247,7 @@ class InteractionSystem {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isAttack) npc.toggleState();
|
||||
// NPC interaction complete
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -301,11 +301,8 @@ class InteractionSystem {
|
||||
}
|
||||
}
|
||||
|
||||
// 4. Try Farming Action
|
||||
if (this.scene.farmingSystem && !isAttack) {
|
||||
const didFarm = this.scene.farmingSystem.interact(gridX, gridY, activeTool);
|
||||
if (didFarm) return;
|
||||
}
|
||||
// 4. Farming is now handled via Player Space key (handleFarmingAction)
|
||||
// No click farming anymore
|
||||
|
||||
// 5. Try damage decoration
|
||||
const id = `${gridX},${gridY}`;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// ========================================================
|
||||
// NOVE GLOBALNE KONSTANTE ZA LOKACIJE
|
||||
// ========================================================
|
||||
const FARM_SIZE = 100; // 100x100 VELIKA PLATFORMA!
|
||||
const FARM_SIZE = 8; // 8x8 MICRO FARM - Začetek igre!
|
||||
const FARM_CENTER_X = 50; // Center mape (50,50)
|
||||
const FARM_CENTER_Y = 50; // Center mape (50,50)
|
||||
|
||||
@@ -453,6 +453,7 @@ class TerrainSystem {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// --- CHUNK DECORATION PASS ---
|
||||
// DISABLED - User wants clean platform (no trees, rocks, flowers)
|
||||
|
||||
@@ -477,6 +478,81 @@ class TerrainSystem {
|
||||
// this.addDecoration(pos.x, pos.y, 'path_stone');
|
||||
// }
|
||||
// });
|
||||
|
||||
// MICRO FARM FENCE (8x8 starting area) - DISABLED FOR NOW
|
||||
// Will be added properly later
|
||||
const farmMinX = FARM_CENTER_X - FARM_SIZE / 2;
|
||||
const farmMaxX = FARM_CENTER_X + FARM_SIZE / 2;
|
||||
const farmMinY = FARM_CENTER_Y - FARM_SIZE / 2;
|
||||
const farmMaxY = FARM_CENTER_Y + FARM_SIZE / 2;
|
||||
|
||||
// DECORATIONS: Flowers & Bushes on grass tiles (random)
|
||||
for (let y = startY; y < endY; y++) {
|
||||
for (let x = startX; x < endX; x++) {
|
||||
const tile = this.tiles[y][x]; // Corrected access to this.tiles
|
||||
|
||||
// Only on grass tiles, outside farm area
|
||||
if (tile && tile.type === 'GRASS_FULL' && // Changed 'grass' to 'GRASS_FULL' to match terrainType.name
|
||||
(x < farmMinX || x > farmMaxX || y < farmMinY || y > farmMaxY)) {
|
||||
|
||||
const rand = Math.random();
|
||||
|
||||
// 10% chance for flowers
|
||||
if (rand < 0.10) {
|
||||
const flowerTypes = ['flowers_new', 'flowers_pink_isometric'];
|
||||
const randomType = flowerTypes[Math.floor(Math.random() * flowerTypes.length)];
|
||||
this.addDecoration(x, y, randomType);
|
||||
}
|
||||
// 8% chance for grass patches (visual variety)
|
||||
else if (rand >= 0.10 && rand < 0.18) {
|
||||
this.addDecoration(x, y, 'grass_sprite');
|
||||
}
|
||||
// 5% chance for bushes
|
||||
else if (rand >= 0.18 && rand < 0.23) {
|
||||
this.addDecoration(x, y, 'bush_small');
|
||||
}
|
||||
// 3% chance for small rocks
|
||||
else if (rand >= 0.23 && rand < 0.26) {
|
||||
const rockTypes = ['rock_small', 'rock_2'];
|
||||
const randomRock = rockTypes[Math.floor(Math.random() * rockTypes.length)];
|
||||
this.addDecoration(x, y, randomRock);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check if this chunk contains farm border
|
||||
if (cx * this.chunkSize <= farmMaxX && (cx + 1) * this.chunkSize >= farmMinX &&
|
||||
cy * this.chunkSize <= farmMaxY && (cy + 1) * this.chunkSize >= farmMinY) {
|
||||
|
||||
// Top border (y = farmMinY)
|
||||
if (startY <= farmMinY && endY > farmMinY) {
|
||||
for (let x = Math.max(startX, farmMinX); x <= Math.min(endX - 1, farmMaxX); x++) {
|
||||
this.addDecoration(x, farmMinY, 'fence_isometric');
|
||||
}
|
||||
}
|
||||
|
||||
// Bottom border (y = farmMaxY)
|
||||
if (startY <= farmMaxY && endY > farmMaxY) {
|
||||
for (let x = Math.max(startX, farmMinX); x <= Math.min(endX - 1, farmMaxX); x++) {
|
||||
this.addDecoration(x, farmMaxY, 'fence_isometric');
|
||||
}
|
||||
}
|
||||
|
||||
// Left border (x = farmMinX)
|
||||
if (startX <= farmMinX && endX > farmMinX) {
|
||||
for (let y = Math.max(startY, farmMinY); y <= Math.min(endY - 1, farmMaxY); y++) {
|
||||
this.addDecoration(farmMinX, y, 'fence_isometric');
|
||||
}
|
||||
}
|
||||
|
||||
// Right border (x = farmMaxX)
|
||||
if (startX <= farmMaxX && endX > farmMaxX) {
|
||||
for (let y = Math.max(startY, farmMinY); y <= Math.min(endY - 1, farmMaxY); y++) {
|
||||
this.addDecoration(farmMaxX, y, 'fence_isometric');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
updateChunks(camera) {
|
||||
@@ -732,14 +808,15 @@ class TerrainSystem {
|
||||
typeLower.includes('small_rock') ||
|
||||
typeLower.includes('path_stone') ||
|
||||
typeLower.includes('mushroom') ||
|
||||
typeLower.includes('puddle');
|
||||
typeLower.includes('puddle') ||
|
||||
typeLower.includes('fence'); // OGRAJE SO PREHODNE!
|
||||
|
||||
const isSolid = !isSmallDecor && (
|
||||
typeLower.includes('tree') ||
|
||||
typeLower.includes('sapling') ||
|
||||
typeLower.includes('rock') ||
|
||||
typeLower.includes('stone') ||
|
||||
typeLower.includes('fence') ||
|
||||
// fence REMOVED - it's walkable now!
|
||||
typeLower.includes('wall') ||
|
||||
typeLower.includes('signpost') ||
|
||||
typeLower.includes('hill') ||
|
||||
|
||||
Reference in New Issue
Block a user