posodobitev

This commit is contained in:
2025-12-11 19:36:08 +01:00
parent 5395f4abd2
commit 6e998d516d
36 changed files with 2045 additions and 304 deletions

View File

@@ -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));
}
});
}
}