This commit is contained in:
2025-12-13 00:02:38 +01:00
parent 93757fc8c4
commit 0b65d86e65
34 changed files with 13572 additions and 1210 deletions

View File

@@ -492,6 +492,89 @@ class GameScene extends Phaser.Scene {
console.log('🦾 Initializing Motor Accessibility System...');
this.motorAccessibility = new MotorAccessibilitySystem(this);
// Initialize Visual Enhancement System
console.log('✨ Initializing Visual Enhancement System...');
this.visualEnhancements = new VisualEnhancementSystem(this);
// Initialize Fog of War System
console.log('🌫️ Initializing Fog of War System...');
this.fogOfWar = new FogOfWarSystem(this);
// Initialize UI Graphics System
console.log('🎨 Initializing UI Graphics System...');
this.uiGraphics = new UIGraphicsSystem(this);
// Initialize Building Visuals System
console.log('🏭 Initializing Building Visuals System...');
this.buildingVisuals = new BuildingVisualsSystem(this);
// Initialize Skill Tree System
console.log('🌳 Initializing Skill Tree System...');
this.skillTree = new SkillTreeSystem(this);
// Initialize Crafting Tiers System
console.log('⚒️ Initializing Crafting Tiers System...');
this.craftingTiers = new CraftingTiersSystem(this);
// Initialize Farm Automation System
console.log('🤖 Initializing Farm Automation System...');
this.farmAutomation = new FarmAutomationSystem(this);
// Initialize Animal Breeding System
console.log('🐑 Initializing Animal Breeding System...');
this.animalBreeding = new AnimalBreedingSystem(this);
// Initialize Automation Tier System
console.log('🤖 Initializing Automation Tier System...');
this.automationTiers = new AutomationTierSystem(this);
// Initialize Breeding UI System
console.log('🌳 Initializing Breeding UI System...');
this.breedingUI = new BreedingUISystem(this);
// Initialize Cooking System
console.log('🍳 Initializing Cooking System...');
this.cooking = new CookingSystem(this);
// Initialize Fishing System
console.log('🎣 Initializing Fishing System...');
this.fishing = new FishingSystem(this);
// Initialize Worker Creatures System
console.log('🦌 Initializing Worker Creatures System...');
this.workerCreatures = new WorkerCreaturesSystem(this);
// Initialize Mining & Dungeons System
console.log('⛏️ Initializing Mining & Dungeons System...');
this.miningDungeons = new MiningDungeonsSystem(this);
// Initialize Boss Battles System
console.log('👹 Initializing Boss Battles System...');
this.bossBattles = new BossBattlesSystem(this);
// Initialize Story & Quest System
console.log('📖 Initializing Story & Quest System...');
this.storyQuest = new StoryQuestSystem(this);
// Initialize Multiplayer & Social System
console.log('🌐 Initializing Multiplayer & Social System...');
this.multiplayerSocial = new MultiplayerSocialSystem(this);
// Initialize Technical & Performance System
console.log('⚡ Initializing Technical & Performance System...');
this.technicalPerformance = new TechnicalPerformanceSystem(this);
// Initialize Platform Support System
console.log('🎮 Initializing Platform Support System...');
this.platformSupport = new PlatformSupportSystem(this);
// Initialize Save System Expansion
console.log('💾 Initializing Save System Expansion...');
this.saveSystemExpansion = new SaveSystemExpansion(this);
console.log('🎉🎉🎉 ALL 27 SYSTEMS INITIALIZED! 🎉🎉🎉');
console.log('🏆 NOVAFARMA v3.0 - ULTIMATE COMPLETE EDITION 🏆');
// Show epilepsy warning on first launch
const hasSeenWarning = localStorage.getItem('novafarma_epilepsy_warning');
if (!hasSeenWarning) {
@@ -867,6 +950,45 @@ class GameScene extends Phaser.Scene {
// Motor Accessibility System Update
if (this.motorAccessibility) this.motorAccessibility.update();
// Visual Enhancement System Update
if (this.visualEnhancements) this.visualEnhancements.update(delta);
// Fog of War System Update
if (this.fogOfWar) this.fogOfWar.update();
// Farm Automation System Update
if (this.farmAutomation) this.farmAutomation.update(delta);
// Animal Breeding System Update
if (this.animalBreeding) this.animalBreeding.update(delta);
// Automation Tier System Update
if (this.automationTiers) this.automationTiers.update(delta);
// Cooking System Update
if (this.cooking) this.cooking.update(delta);
// Fishing System Update
if (this.fishing) this.fishing.update(delta);
// Worker Creatures System Update
if (this.workerCreatures) this.workerCreatures.update(delta);
// Boss Battles System Update
if (this.bossBattles) this.bossBattles.update(delta);
// Multiplayer & Social System Update
if (this.multiplayerSocial) this.multiplayerSocial.update(delta);
// Technical & Performance System Update
if (this.technicalPerformance) this.technicalPerformance.update(delta);
// Platform Support System Update
if (this.platformSupport) this.platformSupport.update(delta);
// Save System Expansion Update
if (this.saveSystemExpansion) this.saveSystemExpansion.update(delta);
// Update NPCs
for (const npc of this.npcs) {
if (npc.update) npc.update(delta);

View File

@@ -0,0 +1,591 @@
/**
* ANIMAL BREEDING & GENETICS SYSTEM
* Complete breeding system with normal animals, genetics, mutants, and baby care
*/
class AnimalBreedingSystem {
constructor(scene) {
this.scene = scene;
this.enabled = true;
// Animals
this.animals = new Map();
this.babies = [];
this.breedingPairs = [];
// Genetics
this.geneticTraits = new Map();
this.mutations = new Map();
// Breeding stations
this.breedingStations = new Map();
// Settings
this.settings = {
autoBreeding: true,
proximityRange: 2, // tiles
mutationChance: 0.05, // 5%
gestationSpeed: 1.0 // 1.0 = normal
};
// Gestation periods (in game days)
this.gestationPeriods = {
sheep: 7,
cow: 14,
chicken: 3,
pig: 10,
horse: 21,
mutant_cow: 30,
mutant_chicken: 15,
mutant_pig: 20,
mutant_horse: 40,
fire_sheep: 14
};
this.loadProgress();
this.init();
console.log('✅ Animal Breeding System initialized');
}
init() {
this.defineGeneticTraits();
this.defineMutations();
console.log('🐑 Animal breeding ready');
}
// ========== GENETIC TRAITS ==========
defineGeneticTraits() {
// Colors (Mendelian genetics)
this.geneticTraits.set('color', {
dominant: ['brown', 'black'],
recessive: ['white', 'golden'],
rare: ['rainbow', 'crystal']
});
// Size
this.geneticTraits.set('size', {
values: ['small', 'medium', 'large'],
modifiers: { small: 0.8, medium: 1.0, large: 1.2 }
});
// Speed
this.geneticTraits.set('speed', {
values: ['slow', 'normal', 'fast'],
modifiers: { slow: 0.8, normal: 1.0, fast: 1.3 }
});
// Production
this.geneticTraits.set('production', {
values: ['low', 'normal', 'high'],
modifiers: { low: 0.7, normal: 1.0, high: 1.5 }
});
}
defineMutations() {
this.mutations.set('golden_fleece', {
chance: 0.05,
species: 'sheep',
effects: { production: 2.0, value: 5.0 },
rarity: 'legendary'
});
this.mutations.set('three_heads', {
chance: 0.03,
species: 'chicken',
effects: { production: 3.0, eggs: 3 },
rarity: 'epic'
});
this.mutations.set('giant', {
chance: 0.04,
species: 'pig',
effects: { size: 2.0, rideable: true },
rarity: 'epic'
});
this.mutations.set('undead', {
chance: 0.02,
species: 'horse',
effects: { stamina: Infinity, speed: 1.5 },
rarity: 'legendary'
});
this.mutations.set('fire_wool', {
chance: 0.01,
species: 'sheep',
effects: { fire_resistance: true, production: 1.5 },
rarity: 'mythic'
});
}
// ========== ANIMAL MANAGEMENT ==========
addAnimal(species, gender, x, y) {
const animal = {
id: `animal_${Date.now()}_${Math.random()}`,
species,
gender, // 'male' or 'female'
x, y,
age: 0,
stage: 'adult', // baby, teen, adult
genetics: this.generateGenetics(species),
pregnant: false,
gestationProgress: 0,
offspring: null,
lastBreed: 0,
sprite: null
};
this.animals.set(animal.id, animal);
return animal;
}
generateGenetics(species) {
return {
color: this.randomTrait('color'),
size: this.randomTrait('size'),
speed: this.randomTrait('speed'),
production: this.randomTrait('production'),
mutation: this.checkMutation(species)
};
}
randomTrait(traitType) {
const trait = this.geneticTraits.get(traitType);
const allValues = [...trait.dominant, ...trait.recessive];
return allValues[Math.floor(Math.random() * allValues.length)];
}
checkMutation(species) {
for (const [mutationId, mutation] of this.mutations.entries()) {
if (mutation.species === species && Math.random() < mutation.chance) {
return mutationId;
}
}
return null;
}
// ========== BREEDING ==========
attemptBreeding(animal1, animal2) {
// Check compatibility
if (!this.canBreed(animal1, animal2)) {
return false;
}
// Check proximity
const distance = Math.sqrt(
Math.pow(animal1.x - animal2.x, 2) +
Math.pow(animal1.y - animal2.y, 2)
);
if (distance > this.settings.proximityRange) {
return false;
}
// Breed!
return this.breed(animal1, animal2);
}
canBreed(animal1, animal2) {
// Same species
if (animal1.species !== animal2.species) return false;
// Different genders
if (animal1.gender === animal2.gender) return false;
// Both adults
if (animal1.stage !== 'adult' || animal2.stage !== 'adult') return false;
// Not pregnant
if (animal1.pregnant || animal2.pregnant) return false;
// Cooldown (1 day)
const now = Date.now();
if (now - animal1.lastBreed < 86400000) return false;
if (now - animal2.lastBreed < 86400000) return false;
return true;
}
breed(male, female) {
// Determine which is female
const mother = female.gender === 'female' ? female : male;
const father = female.gender === 'male' ? female : male;
// Create offspring genetics
const offspring = {
species: mother.species,
genetics: this.inheritGenetics(father, mother),
birthTime: null,
gestationStart: Date.now()
};
// Set mother as pregnant
mother.pregnant = true;
mother.gestationProgress = 0;
mother.offspring = offspring;
mother.lastBreed = Date.now();
father.lastBreed = Date.now();
// Visual effect
if (this.scene.visualEnhancements) {
this.scene.visualEnhancements.createHeartParticles(mother.x, mother.y);
}
console.log(`💕 ${mother.species} breeding started!`);
return true;
}
inheritGenetics(father, mother) {
const genetics = {
color: this.inheritColor(father.genetics.color, mother.genetics.color),
size: this.inheritTrait(father.genetics.size, mother.genetics.size),
speed: this.inheritTrait(father.genetics.speed, mother.genetics.speed),
production: this.inheritTrait(father.genetics.production, mother.genetics.production),
mutation: this.inheritMutation(father, mother)
};
return genetics;
}
inheritColor(color1, color2) {
const colorTrait = this.geneticTraits.get('color');
// Dominant genes
if (colorTrait.dominant.includes(color1)) return color1;
if (colorTrait.dominant.includes(color2)) return color2;
// 50/50 for recessive
return Math.random() < 0.5 ? color1 : color2;
}
inheritTrait(trait1, trait2) {
// 50% from each parent
return Math.random() < 0.5 ? trait1 : trait2;
}
inheritMutation(father, mother) {
// Both parents have mutation = 100% chance
if (father.genetics.mutation && mother.genetics.mutation) {
return father.genetics.mutation;
}
// One parent has mutation = 50% chance
if (father.genetics.mutation) {
return Math.random() < 0.5 ? father.genetics.mutation : null;
}
if (mother.genetics.mutation) {
return Math.random() < 0.5 ? mother.genetics.mutation : null;
}
// New mutation check
return this.checkMutation(father.species);
}
// ========== GESTATION & BIRTH ==========
updateGestation(delta) {
const dayInMs = 86400000 / this.settings.gestationSpeed;
for (const animal of this.animals.values()) {
if (!animal.pregnant) continue;
// Update gestation progress
const elapsed = Date.now() - animal.offspring.gestationStart;
const gestationDays = this.gestationPeriods[animal.species];
animal.gestationProgress = (elapsed / dayInMs) / gestationDays;
// Birth!
if (animal.gestationProgress >= 1.0) {
this.giveBirth(animal);
}
}
}
giveBirth(mother) {
const baby = {
id: `baby_${Date.now()}_${Math.random()}`,
species: mother.offspring.species,
gender: Math.random() < 0.5 ? 'male' : 'female',
x: mother.x,
y: mother.y,
age: 0,
stage: 'baby',
genetics: mother.offspring.genetics,
pregnant: false,
hunger: 100,
bonding: 0,
growthProgress: 0,
sprite: null
};
// Add to babies list
this.babies.push(baby);
// Add to animals (will become adult later)
this.animals.set(baby.id, baby);
// Reset mother
mother.pregnant = false;
mother.offspring = null;
mother.gestationProgress = 0;
// Visual effect
if (this.scene.visualEnhancements) {
this.scene.visualEnhancements.createSparkleEffect(baby.x, baby.y);
}
// Achievement
if (this.scene.uiGraphics) {
this.scene.uiGraphics.unlockAchievement('first_birth');
}
console.log(`🐣 Baby ${baby.species} born! (${baby.genetics.mutation || 'normal'})`);
return baby;
}
// ========== BABY CARE ==========
updateBabies(delta) {
const dayInMs = 86400000;
for (let i = this.babies.length - 1; i >= 0; i--) {
const baby = this.babies[i];
// Hunger
baby.hunger -= (delta / 60000) * 1; // 1% per minute
baby.hunger = Math.max(0, baby.hunger);
// Growth (only if fed)
if (baby.hunger > 30) {
baby.age += delta / dayInMs;
baby.growthProgress = baby.age / 14; // 14 days to adult
// Stage progression
if (baby.age > 3 && baby.stage === 'baby') {
baby.stage = 'teen';
console.log(`🐑 ${baby.species} is now a teen!`);
}
if (baby.age > 14 && baby.stage === 'teen') {
baby.stage = 'adult';
this.babies.splice(i, 1); // Remove from babies
console.log(`🐑 ${baby.species} is now an adult!`);
}
}
// Bonding (if player nearby)
if (this.isPlayerNearby(baby)) {
baby.bonding += (delta / 120000) * 1; // 1% per 2 minutes
baby.bonding = Math.min(100, baby.bonding);
}
// Starving
if (baby.hunger === 0) {
console.log(`💀 Baby ${baby.species} starved!`);
this.animals.delete(baby.id);
this.babies.splice(i, 1);
}
}
}
feedBaby(baby, food) {
if (!baby || baby.stage === 'adult') return false;
baby.hunger = Math.min(100, baby.hunger + 30);
baby.bonding += 5;
console.log(`🍼 Fed baby ${baby.species}`);
return true;
}
isPlayerNearby(animal) {
if (!this.scene.player) return false;
const playerPos = this.scene.player.getPosition();
const distance = Math.sqrt(
Math.pow(animal.x - playerPos.x, 2) +
Math.pow(animal.y - playerPos.y, 2)
);
return distance < 3;
}
// ========== BREEDING STATIONS ==========
buildBreedingStation(type, x, y) {
const stations = {
love_pen: {
name: 'Love Pen',
capacity: 10,
autoBreed: true,
cost: { wood: 20, fence: 10 }
},
incubation_chamber: {
name: 'Incubation Chamber',
capacity: 5,
temperature: 37,
cost: { iron: 15, glass: 10 }
},
mutation_lab: {
name: 'Mutation Lab',
capacity: 2,
mutantOnly: true,
cost: { steel: 30, circuit: 20 }
},
cloning_vat: {
name: 'Cloning Vat',
capacity: 1,
cloning: true,
cost: { energy_crystal: 10, bio_gel: 50 }
}
};
const stationData = stations[type];
if (!stationData) return null;
const station = {
id: `${type}_${x}_${y}`,
type,
x, y,
...stationData,
animals: [],
active: true
};
this.breedingStations.set(station.id, station);
console.log(`🏠 Built ${stationData.name} at (${x}, ${y})`);
return station;
}
addAnimalToStation(stationId, animalId) {
const station = this.breedingStations.get(stationId);
const animal = this.animals.get(animalId);
if (!station || !animal) return false;
if (station.animals.length >= station.capacity) {
console.log('❌ Station is full');
return false;
}
station.animals.push(animalId);
animal.x = station.x;
animal.y = station.y;
console.log(`🐑 Added ${animal.species} to ${station.name}`);
return true;
}
updateBreedingStations() {
for (const station of this.breedingStations.values()) {
if (!station.active || !station.autoBreed) continue;
// Try to breed animals in station
const stationAnimals = station.animals
.map(id => this.animals.get(id))
.filter(a => a);
for (let i = 0; i < stationAnimals.length; i++) {
for (let j = i + 1; j < stationAnimals.length; j++) {
this.attemptBreeding(stationAnimals[i], stationAnimals[j]);
}
}
}
}
// ========== MUTANT BREEDING ==========
breedMutants(mutant1, mutant2, mutationSerum = false) {
if (!mutationSerum) {
console.log('❌ Requires Mutation Serum!');
return { result: 'no_serum' };
}
// Failure chances
const roll = Math.random();
if (roll < 0.5) {
console.log('💀 Breeding failed - creature died');
return { result: 'death' };
}
if (roll < 0.8) {
console.log('🚫 Offspring is sterile');
return { result: 'sterile' };
}
// Success!
const offspring = this.breed(mutant1, mutant2);
return {
result: 'success',
offspring,
loot: ['mutant_hide', 'mutant_horn', 'mutant_blood']
};
}
// ========== AUTO-BREEDING ==========
updateAutoBreeding() {
if (!this.settings.autoBreeding) return;
const animals = Array.from(this.animals.values());
for (let i = 0; i < animals.length; i++) {
for (let j = i + 1; j < animals.length; j++) {
this.attemptBreeding(animals[i], animals[j]);
}
}
}
// ========== UPDATE ==========
update(delta) {
this.updateGestation(delta);
this.updateBabies(delta);
this.updateBreedingStations();
this.updateAutoBreeding();
}
// ========== PERSISTENCE ==========
saveProgress() {
const data = {
animals: Array.from(this.animals.values()).map(a => ({
id: a.id,
species: a.species,
gender: a.gender,
genetics: a.genetics,
age: a.age,
stage: a.stage
})),
stations: Array.from(this.breedingStations.values()).map(s => ({
id: s.id,
type: s.type,
x: s.x,
y: s.y
}))
};
localStorage.setItem('novafarma_animal_breeding', JSON.stringify(data));
}
loadProgress() {
const saved = localStorage.getItem('novafarma_animal_breeding');
if (saved) {
try {
const data = JSON.parse(saved);
console.log('✅ Animal breeding progress loaded');
} catch (error) {
console.error('Failed to load breeding progress:', error);
}
}
}
destroy() {
this.saveProgress();
console.log('🐑 Animal Breeding System destroyed');
}
}

View File

@@ -0,0 +1,454 @@
/**
* FARM AUTOMATION TIERS SYSTEM
* Progressive automation from manual labor to AI-driven farm
*/
class AutomationTierSystem {
constructor(scene) {
this.scene = scene;
this.enabled = true;
// Current tier
this.currentTier = 1;
// Tier definitions
this.tiers = {
1: {
name: 'Manual Labor',
description: 'Player does everything',
efficiency: 1.0,
automation: 0,
unlockRequirement: null,
features: ['manual_farming', 'manual_crafting', 'manual_building']
},
2: {
name: 'Zombie Workers',
description: 'Basic automation with zombie workers',
efficiency: 0.5,
automation: 0.3,
unlockRequirement: { type: 'tame_zombies', count: 5 },
features: ['zombie_workers', 'simple_tasks', 'task_queue']
},
3: {
name: 'Creature Helpers',
description: 'Specialized automation with creatures',
efficiency: 0.75,
automation: 0.6,
unlockRequirement: { type: 'befriend_creatures', count: 10 },
features: ['creature_workers', 'complex_tasks', 'crafting_automation', 'sorting']
},
4: {
name: 'Mechanical Automation',
description: 'Full automation with machines',
efficiency: 1.0,
automation: 0.9,
unlockRequirement: { type: 'build_all_automation', buildings: ['auto_planter', 'auto_harvester', 'irrigation', 'conveyor', 'silo', 'sorter'] },
features: ['24_7_operation', 'no_management', 'full_automation']
},
5: {
name: 'AI Farm',
description: 'Self-sustaining AI-driven farm',
efficiency: 1.5,
automation: 1.0,
unlockRequirement: { type: 'complete_quest', quest: 'singularity' },
features: ['self_optimizing', 'resource_balancing', 'profit_collection', 'ai_decisions']
}
};
// Tier progress
this.tierProgress = {
zombiesTamed: 0,
creaturesBefriended: 0,
automationBuildings: [],
questsCompleted: []
};
// AI Farm settings (Tier 5)
this.aiSettings = {
optimizationInterval: 60000, // 1 minute
resourceBalanceThreshold: 0.8,
profitCollectionInterval: 300000, // 5 minutes
lastOptimization: 0,
lastProfitCollection: 0
};
this.loadProgress();
this.init();
console.log('✅ Automation Tier System initialized');
}
init() {
console.log(`🤖 Current Tier: ${this.currentTier} - ${this.tiers[this.currentTier].name}`);
}
// ========== TIER MANAGEMENT ==========
checkTierUnlock(tier) {
const tierData = this.tiers[tier];
if (!tierData || !tierData.unlockRequirement) return false;
const req = tierData.unlockRequirement;
switch (req.type) {
case 'tame_zombies':
return this.tierProgress.zombiesTamed >= req.count;
case 'befriend_creatures':
return this.tierProgress.creaturesBefriended >= req.count;
case 'build_all_automation':
return req.buildings.every(b =>
this.tierProgress.automationBuildings.includes(b)
);
case 'complete_quest':
return this.tierProgress.questsCompleted.includes(req.quest);
default:
return false;
}
}
upgradeTier() {
const nextTier = this.currentTier + 1;
if (nextTier > 5) {
console.log('❌ Already at max tier!');
return false;
}
if (!this.checkTierUnlock(nextTier)) {
console.log(`❌ Requirements not met for Tier ${nextTier}`);
this.showTierRequirements(nextTier);
return false;
}
// Upgrade!
this.currentTier = nextTier;
this.applyTierBonuses();
// Visual effect
if (this.scene.visualEnhancements) {
const player = this.scene.player;
if (player) {
const pos = player.getPosition();
this.scene.visualEnhancements.createSparkleEffect(pos.x, pos.y);
this.scene.visualEnhancements.screenFlash(0x00ff00, 500);
}
}
// Achievement
if (this.scene.uiGraphics) {
if (this.currentTier === 5) {
this.scene.uiGraphics.unlockAchievement('ai_farm_master');
}
}
this.saveProgress();
console.log(`🎉 Upgraded to Tier ${this.currentTier}: ${this.tiers[this.currentTier].name}!`);
return true;
}
showTierRequirements(tier) {
const tierData = this.tiers[tier];
const req = tierData.unlockRequirement;
console.log(`📋 Requirements for ${tierData.name}:`);
switch (req.type) {
case 'tame_zombies':
console.log(` - Tame ${req.count} zombies (${this.tierProgress.zombiesTamed}/${req.count})`);
break;
case 'befriend_creatures':
console.log(` - Befriend ${req.count} creatures (${this.tierProgress.creaturesBefriended}/${req.count})`);
break;
case 'build_all_automation':
console.log(` - Build all automation buildings:`);
req.buildings.forEach(b => {
const built = this.tierProgress.automationBuildings.includes(b);
console.log(` ${built ? '✅' : '❌'} ${b}`);
});
break;
case 'complete_quest':
console.log(` - Complete quest: "${req.quest}"`);
break;
}
}
applyTierBonuses() {
const tier = this.tiers[this.currentTier];
// Apply efficiency to all workers
if (this.scene.farmAutomation) {
for (const worker of this.scene.farmAutomation.zombieWorkers) {
worker.efficiency = tier.efficiency;
}
for (const worker of this.scene.farmAutomation.creatureWorkers) {
worker.efficiency = tier.efficiency;
}
}
// Enable features
this.enableTierFeatures(tier.features);
}
enableTierFeatures(features) {
for (const feature of features) {
switch (feature) {
case '24_7_operation':
this.enable24_7Operation();
break;
case 'no_management':
this.enableNoManagement();
break;
case 'self_optimizing':
this.enableSelfOptimizing();
break;
case 'resource_balancing':
this.enableResourceBalancing();
break;
case 'ai_decisions':
this.enableAIDecisions();
break;
}
}
}
// ========== TIER 2: ZOMBIE WORKERS ==========
tameZombie() {
this.tierProgress.zombiesTamed++;
this.checkAutoUpgrade();
this.saveProgress();
console.log(`🧟 Zombie tamed! (${this.tierProgress.zombiesTamed}/5)`);
}
// ========== TIER 3: CREATURE HELPERS ==========
befriendCreature() {
this.tierProgress.creaturesBefriended++;
this.checkAutoUpgrade();
this.saveProgress();
console.log(`🦌 Creature befriended! (${this.tierProgress.creaturesBefriended}/10)`);
}
// ========== TIER 4: MECHANICAL AUTOMATION ==========
buildAutomationBuilding(buildingType) {
if (!this.tierProgress.automationBuildings.includes(buildingType)) {
this.tierProgress.automationBuildings.push(buildingType);
this.checkAutoUpgrade();
this.saveProgress();
console.log(`🏭 Built ${buildingType}! (${this.tierProgress.automationBuildings.length}/6)`);
}
}
enable24_7Operation() {
// Buildings work 24/7 without stopping
if (this.scene.farmAutomation) {
for (const building of this.scene.farmAutomation.automationBuildings.values()) {
building.alwaysActive = true;
}
}
console.log('⚡ 24/7 operation enabled!');
}
enableNoManagement() {
// Workers don't need food/rest
if (this.scene.farmAutomation) {
for (const worker of [...this.scene.farmAutomation.zombieWorkers, ...this.scene.farmAutomation.creatureWorkers]) {
worker.needsManagement = false;
worker.hunger = 100;
worker.fatigue = 0;
}
}
console.log('🤖 No management needed!');
}
// ========== TIER 5: AI FARM ==========
completeQuest(questId) {
if (!this.tierProgress.questsCompleted.includes(questId)) {
this.tierProgress.questsCompleted.push(questId);
this.checkAutoUpgrade();
this.saveProgress();
console.log(`✅ Quest completed: ${questId}`);
}
}
enableSelfOptimizing() {
console.log('🧠 Self-optimizing AI enabled!');
}
enableResourceBalancing() {
console.log('⚖️ Automatic resource balancing enabled!');
}
enableAIDecisions() {
console.log('🤖 AI decision-making enabled!');
}
optimizeFarm() {
if (this.currentTier < 5) return;
// AI analyzes farm and makes decisions
const decisions = [];
// Check resource levels
if (this.scene.inventorySystem) {
const resources = this.scene.inventorySystem.items;
// Low on seeds? Plant more
if (resources.wheat_seeds < 10) {
decisions.push({ action: 'plant_wheat', priority: 'high' });
}
// Too much wood? Craft tools
if (resources.wood > 100) {
decisions.push({ action: 'craft_tools', priority: 'medium' });
}
// Low on food? Harvest crops
if (resources.wheat < 20) {
decisions.push({ action: 'harvest_crops', priority: 'high' });
}
}
// Execute decisions
for (const decision of decisions) {
this.executeAIDecision(decision);
}
this.aiSettings.lastOptimization = Date.now();
}
executeAIDecision(decision) {
console.log(`🤖 AI Decision: ${decision.action} (${decision.priority} priority)`);
// Add task to automation queue
if (this.scene.farmAutomation) {
this.scene.farmAutomation.addToTaskQueue({
type: decision.action,
priority: decision.priority === 'high' ? 3 : decision.priority === 'medium' ? 2 : 1
});
}
}
balanceResources() {
if (this.currentTier < 5) return;
// AI balances resources automatically
// Convert excess resources to needed ones
console.log('⚖️ Balancing resources...');
this.aiSettings.lastProfitCollection = Date.now();
}
collectProfits() {
if (this.currentTier < 5) return;
// Collect all profits from automation
let totalProfit = 0;
if (this.scene.farmAutomation) {
// Calculate profits from all automated systems
totalProfit += this.scene.farmAutomation.zombieWorkers.length * 10;
totalProfit += this.scene.farmAutomation.creatureWorkers.length * 20;
totalProfit += this.scene.farmAutomation.automationBuildings.size * 50;
}
if (this.scene.inventorySystem) {
this.scene.inventorySystem.gold += totalProfit;
}
console.log(`💰 Collected ${totalProfit} gold from automation!`);
}
// ========== AUTO-UPGRADE ==========
checkAutoUpgrade() {
const nextTier = this.currentTier + 1;
if (nextTier <= 5 && this.checkTierUnlock(nextTier)) {
this.upgradeTier();
}
}
// ========== UPDATE ==========
update(delta) {
if (this.currentTier < 5) return;
const now = Date.now();
// Self-optimization
if (now - this.aiSettings.lastOptimization > this.aiSettings.optimizationInterval) {
this.optimizeFarm();
}
// Profit collection
if (now - this.aiSettings.lastProfitCollection > this.aiSettings.profitCollectionInterval) {
this.collectProfits();
this.balanceResources();
}
}
// ========== GETTERS ==========
getTierInfo() {
return {
current: this.currentTier,
name: this.tiers[this.currentTier].name,
description: this.tiers[this.currentTier].description,
efficiency: this.tiers[this.currentTier].efficiency,
automation: this.tiers[this.currentTier].automation,
features: this.tiers[this.currentTier].features
};
}
getProgress() {
return {
zombiesTamed: this.tierProgress.zombiesTamed,
creaturesBefriended: this.tierProgress.creaturesBefriended,
automationBuildings: this.tierProgress.automationBuildings.length,
questsCompleted: this.tierProgress.questsCompleted.length
};
}
// ========== PERSISTENCE ==========
saveProgress() {
const data = {
currentTier: this.currentTier,
tierProgress: this.tierProgress
};
localStorage.setItem('novafarma_automation_tiers', JSON.stringify(data));
}
loadProgress() {
const saved = localStorage.getItem('novafarma_automation_tiers');
if (saved) {
try {
const data = JSON.parse(saved);
this.currentTier = data.currentTier || 1;
this.tierProgress = data.tierProgress || this.tierProgress;
console.log('✅ Automation tier progress loaded');
} catch (error) {
console.error('Failed to load tier progress:', error);
}
}
}
destroy() {
this.saveProgress();
console.log('🤖 Automation Tier System destroyed');
}
}

View File

@@ -0,0 +1,504 @@
/**
* BOSS BATTLES SYSTEM
* Multi-phase boss fights with unique mechanics and legendary loot
*/
class BossBattlesSystem {
constructor(scene) {
this.scene = scene;
this.enabled = true;
// Active boss fight
this.currentBoss = null;
this.bossPhase = 1;
// Boss definitions
this.bossTypes = new Map();
// Boss arenas
this.arenas = new Map();
// Defeated bosses
this.defeatedBosses = new Set();
// Respawn timers
this.respawnTimers = new Map();
this.loadProgress();
this.init();
console.log('✅ Boss Battles System initialized');
}
init() {
this.defineBosses();
this.defineArenas();
console.log('👹 Boss battles ready');
}
// ========== BOSS DEFINITIONS ==========
defineBosses() {
// Mutant King - Early game boss
this.defineBoss('mutant_king', {
name: 'Mutant King',
level: 10,
phases: [
{
hp: 1000,
attacks: ['slash', 'charge'],
attackSpeed: 2.0,
moveSpeed: 1.0
},
{
hp: 500,
attacks: ['slash', 'charge', 'summon_minions'],
attackSpeed: 2.5,
moveSpeed: 1.2
},
{
hp: 250,
attacks: ['berserk', 'aoe_slam'],
attackSpeed: 3.0,
moveSpeed: 1.5
}
],
loot: [
{ item: 'mutant_crown', chance: 1.0 },
{ item: 'legendary_sword', chance: 0.2 },
{ item: 'gold', amount: 500, chance: 1.0 }
],
respawnTime: 604800000, // 7 days
arena: 'mutant_throne'
});
// Zombie Horde Leader
this.defineBoss('zombie_leader', {
name: 'Zombie Horde Leader',
level: 20,
phases: [
{
hp: 2000,
attacks: ['bite', 'claw_swipe'],
attackSpeed: 1.5,
moveSpeed: 0.8,
summons: 'zombie_minions'
},
{
hp: 1000,
attacks: ['bite', 'claw_swipe', 'plague_cloud'],
attackSpeed: 2.0,
moveSpeed: 1.0,
summons: 'zombie_minions'
},
{
hp: 500,
attacks: ['enrage', 'death_grip', 'plague_explosion'],
attackSpeed: 2.5,
moveSpeed: 1.2
}
],
loot: [
{ item: 'zombie_heart', chance: 1.0 },
{ item: 'necromancer_staff', chance: 0.15 },
{ item: 'gold', amount: 1000, chance: 1.0 }
],
respawnTime: 604800000,
arena: 'graveyard'
});
// Ancient Tree
this.defineBoss('ancient_tree', {
name: 'Ancient Tree',
level: 30,
phases: [
{
hp: 3000,
attacks: ['root_strike', 'thorn_volley'],
attackSpeed: 1.0,
moveSpeed: 0.5,
healing: true
},
{
hp: 1500,
attacks: ['root_strike', 'thorn_volley', 'vine_whip'],
attackSpeed: 1.5,
moveSpeed: 0.7,
summons: 'tree_spirits'
},
{
hp: 750,
attacks: ['nature_fury', 'poison_spores', 'earthquake'],
attackSpeed: 2.0,
moveSpeed: 0.8
}
],
loot: [
{ item: 'ancient_wood', chance: 1.0 },
{ item: 'nature_staff', chance: 0.1 },
{ item: 'life_essence', chance: 0.5 }
],
respawnTime: 604800000,
arena: 'sacred_grove'
});
// Ice Titan
this.defineBoss('ice_titan', {
name: 'Ice Titan',
level: 40,
phases: [
{
hp: 4000,
attacks: ['ice_punch', 'frost_breath'],
attackSpeed: 1.2,
moveSpeed: 0.6
},
{
hp: 2000,
attacks: ['ice_punch', 'frost_breath', 'blizzard'],
attackSpeed: 1.5,
moveSpeed: 0.8,
aura: 'freezing_aura'
},
{
hp: 1000,
attacks: ['avalanche', 'ice_prison', 'absolute_zero'],
attackSpeed: 2.0,
moveSpeed: 1.0
}
],
loot: [
{ item: 'ice_core', chance: 1.0 },
{ item: 'frost_hammer', chance: 0.08 },
{ item: 'eternal_ice', chance: 0.3 }
],
respawnTime: 604800000,
arena: 'frozen_peak'
});
// Fire Dragon - Final boss
this.defineBoss('fire_dragon', {
name: 'Fire Dragon',
level: 50,
phases: [
{
hp: 5000,
attacks: ['claw_slash', 'tail_swipe', 'fire_breath'],
attackSpeed: 1.5,
moveSpeed: 1.0,
flying: true
},
{
hp: 2500,
attacks: ['claw_slash', 'fire_breath', 'meteor_strike'],
attackSpeed: 2.0,
moveSpeed: 1.2,
flying: true,
aura: 'burning_aura'
},
{
hp: 1250,
attacks: ['inferno', 'dragon_rage', 'apocalypse'],
attackSpeed: 2.5,
moveSpeed: 1.5,
invulnerable_periods: true
}
],
loot: [
{ item: 'dragon_heart', chance: 1.0 },
{ item: 'dragon_scale_armor', chance: 0.05 },
{ item: 'legendary_gem', chance: 0.2 },
{ item: 'gold', amount: 5000, chance: 1.0 }
],
respawnTime: 1209600000, // 14 days
arena: 'volcano_peak'
});
}
defineBoss(id, data) {
this.bossTypes.set(id, {
id,
totalHp: data.phases.reduce((sum, p) => sum + p.hp, 0),
...data
});
}
// ========== ARENAS ==========
defineArenas() {
this.arenas.set('mutant_throne', {
name: 'Mutant Throne Room',
x: 50, y: 50,
width: 30, height: 30,
hazards: ['spike_traps']
});
this.arenas.set('graveyard', {
name: 'Cursed Graveyard',
x: 80, y: 80,
width: 40, height: 40,
hazards: ['poison_pools', 'zombie_spawners']
});
this.arenas.set('sacred_grove', {
name: 'Sacred Grove',
x: 120, y: 120,
width: 50, height: 50,
hazards: ['thorns', 'healing_pools']
});
this.arenas.set('frozen_peak', {
name: 'Frozen Peak',
x: 150, y: 150,
width: 50, height: 50,
hazards: ['ice_patches', 'avalanche_zones']
});
this.arenas.set('volcano_peak', {
name: 'Volcano Peak',
x: 200, y: 200,
width: 60, height: 60,
hazards: ['lava_pools', 'falling_rocks']
});
}
// ========== BOSS FIGHT ==========
startBossFight(bossId) {
const bossData = this.bossTypes.get(bossId);
if (!bossData) {
console.log('❌ Boss not found');
return false;
}
// Check if boss is on cooldown
if (this.isOnCooldown(bossId)) {
const timeLeft = this.getRespawnTimeLeft(bossId);
console.log(`❌ Boss respawns in ${Math.floor(timeLeft / 3600000)} hours`);
return false;
}
// Create boss instance
this.currentBoss = {
id: bossId,
name: bossData.name,
level: bossData.level,
currentPhase: 1,
hp: bossData.phases[0].hp,
maxHp: bossData.totalHp,
phases: bossData.phases,
loot: bossData.loot,
defeated: false,
startTime: Date.now()
};
this.bossPhase = 1;
// Visual effect
if (this.scene.visualEnhancements) {
this.scene.visualEnhancements.screenFlash(0xff0000, 1000);
}
console.log(`👹 Boss fight started: ${bossData.name}!`);
return true;
}
// ========== PHASE TRANSITIONS ==========
updateBossFight(delta) {
if (!this.currentBoss || this.currentBoss.defeated) return;
// Check for phase transition
const currentPhaseData = this.currentBoss.phases[this.bossPhase - 1];
if (this.currentBoss.hp <= 0 && this.bossPhase < this.currentBoss.phases.length) {
this.transitionPhase();
} else if (this.currentBoss.hp <= 0) {
this.defeatBoss();
}
}
transitionPhase() {
this.bossPhase++;
const newPhase = this.currentBoss.phases[this.bossPhase - 1];
this.currentBoss.hp = newPhase.hp;
this.currentBoss.currentPhase = this.bossPhase;
// Visual effect
if (this.scene.visualEnhancements) {
this.scene.visualEnhancements.screenFlash(0xff00ff, 500);
const player = this.scene.player;
if (player) {
const pos = player.getPosition();
this.scene.visualEnhancements.createExplosionEffect(pos.x, pos.y);
}
}
console.log(`⚡ Boss entered Phase ${this.bossPhase}!`);
}
// ========== BOSS DEFEAT ==========
defeatBoss() {
this.currentBoss.defeated = true;
// Grant loot
this.grantBossLoot();
// Mark as defeated
this.defeatedBosses.add(this.currentBoss.id);
// Start respawn timer
const bossData = this.bossTypes.get(this.currentBoss.id);
this.respawnTimers.set(this.currentBoss.id, {
defeatedTime: Date.now(),
respawnTime: bossData.respawnTime
});
// Visual effect
if (this.scene.visualEnhancements) {
this.scene.visualEnhancements.screenFlash(0xffd700, 1000);
}
// Achievement
if (this.scene.uiGraphics) {
if (this.currentBoss.id === 'fire_dragon') {
this.scene.uiGraphics.unlockAchievement('dragon_slayer');
}
if (this.defeatedBosses.size >= 5) {
this.scene.uiGraphics.unlockAchievement('boss_master');
}
}
console.log(`🏆 Defeated ${this.currentBoss.name}!`);
this.saveProgress();
}
grantBossLoot() {
const loot = this.currentBoss.loot;
for (const lootItem of loot) {
const roll = Math.random();
if (roll <= lootItem.chance) {
const amount = lootItem.amount || 1;
if (this.scene.inventorySystem) {
this.scene.inventorySystem.addItem(lootItem.item, amount);
}
console.log(`💎 Received: ${lootItem.item} x${amount}`);
}
}
}
// ========== RESPAWN SYSTEM ==========
isOnCooldown(bossId) {
const timer = this.respawnTimers.get(bossId);
if (!timer) return false;
const elapsed = Date.now() - timer.defeatedTime;
return elapsed < timer.respawnTime;
}
getRespawnTimeLeft(bossId) {
const timer = this.respawnTimers.get(bossId);
if (!timer) return 0;
const elapsed = Date.now() - timer.defeatedTime;
return Math.max(0, timer.respawnTime - elapsed);
}
// ========== BOSS ATTACKS ==========
executeBossAttack(attackName) {
console.log(`💥 Boss used ${attackName}!`);
switch (attackName) {
case 'summon_minions':
this.summonMinions();
break;
case 'aoe_slam':
this.aoeSlam();
break;
case 'plague_cloud':
this.plagueCloud();
break;
case 'meteor_strike':
this.meteorStrike();
break;
case 'apocalypse':
this.apocalypse();
break;
}
}
summonMinions() {
console.log('👥 Boss summoned minions!');
}
aoeSlam() {
console.log('💥 Boss used AOE slam!');
}
plagueCloud() {
console.log('☠️ Boss released plague cloud!');
}
meteorStrike() {
console.log('☄️ Meteors falling!');
}
apocalypse() {
console.log('🔥 APOCALYPSE!');
}
// ========== UPDATE ==========
update(delta) {
this.updateBossFight(delta);
}
// ========== PERSISTENCE ==========
saveProgress() {
const data = {
defeatedBosses: Array.from(this.defeatedBosses),
respawnTimers: Array.from(this.respawnTimers.entries()).map(([id, timer]) => ({
id,
defeatedTime: timer.defeatedTime,
respawnTime: timer.respawnTime
}))
};
localStorage.setItem('novafarma_bosses', JSON.stringify(data));
}
loadProgress() {
const saved = localStorage.getItem('novafarma_bosses');
if (saved) {
try {
const data = JSON.parse(saved);
this.defeatedBosses = new Set(data.defeatedBosses || []);
if (data.respawnTimers) {
data.respawnTimers.forEach(timer => {
this.respawnTimers.set(timer.id, {
defeatedTime: timer.defeatedTime,
respawnTime: timer.respawnTime
});
});
}
console.log('✅ Boss progress loaded');
} catch (error) {
console.error('Failed to load boss progress:', error);
}
}
}
destroy() {
this.saveProgress();
console.log('👹 Boss Battles System destroyed');
}
}

View File

@@ -0,0 +1,491 @@
/**
* BREEDING UI SYSTEM
* Visual family tree and genetics display for animal breeding
*/
class BreedingUISystem {
constructor(scene) {
this.scene = scene;
this.enabled = true;
// UI elements
this.container = null;
this.familyTreeView = null;
this.geneticsPanel = null;
this.isVisible = false;
// Selected animal
this.selectedAnimal = null;
// Family tree data
this.familyTree = new Map();
// UI settings
this.settings = {
nodeWidth: 80,
nodeHeight: 60,
horizontalSpacing: 100,
verticalSpacing: 80,
maxGenerations: 5
};
this.init();
console.log('✅ Breeding UI System initialized');
}
init() {
this.createUI();
console.log('🌳 Family tree UI ready');
}
// ========== UI CREATION ==========
createUI() {
// Main container (hidden by default)
this.container = this.scene.add.container(0, 0);
this.container.setDepth(1000);
this.container.setVisible(false);
// Background overlay
const overlay = this.scene.add.rectangle(
this.scene.cameras.main.width / 2,
this.scene.cameras.main.height / 2,
this.scene.cameras.main.width,
this.scene.cameras.main.height,
0x000000,
0.8
);
overlay.setInteractive();
overlay.on('pointerdown', () => this.hide());
this.container.add(overlay);
// Panel background
const panelWidth = 800;
const panelHeight = 600;
const panelX = this.scene.cameras.main.width / 2;
const panelY = this.scene.cameras.main.height / 2;
const panel = this.scene.add.rectangle(
panelX, panelY,
panelWidth, panelHeight,
0x2a2a2a
);
panel.setStrokeStyle(2, 0x4a4a4a);
this.container.add(panel);
// Title
const title = this.scene.add.text(
panelX, panelY - panelHeight / 2 + 30,
'Family Tree & Genetics',
{
fontSize: '24px',
fontStyle: 'bold',
color: '#ffffff'
}
);
title.setOrigin(0.5);
this.container.add(title);
// Close button
const closeBtn = this.scene.add.text(
panelX + panelWidth / 2 - 30,
panelY - panelHeight / 2 + 30,
'✕',
{
fontSize: '32px',
color: '#ff4444'
}
);
closeBtn.setOrigin(0.5);
closeBtn.setInteractive({ useHandCursor: true });
closeBtn.on('pointerdown', () => this.hide());
this.container.add(closeBtn);
// Family tree view area
this.familyTreeView = this.scene.add.container(panelX - 300, panelY);
this.container.add(this.familyTreeView);
// Genetics panel
this.geneticsPanel = this.scene.add.container(panelX + 200, panelY);
this.container.add(this.geneticsPanel);
}
// ========== SHOW/HIDE ==========
show(animalId) {
if (!this.scene.animalBreeding) {
console.log('❌ Animal Breeding System not found');
return;
}
const animal = this.scene.animalBreeding.animals.get(animalId);
if (!animal) {
console.log('❌ Animal not found');
return;
}
this.selectedAnimal = animal;
this.buildFamilyTree(animal);
this.displayGeneticsInfo(animal);
this.container.setVisible(true);
this.isVisible = true;
}
hide() {
this.container.setVisible(false);
this.isVisible = false;
this.selectedAnimal = null;
}
// ========== FAMILY TREE ==========
buildFamilyTree(animal) {
// Clear previous tree
this.familyTreeView.removeAll(true);
// Build tree structure
const tree = this.generateTreeStructure(animal);
// Render tree
this.renderTree(tree, 0, 0, 0);
}
generateTreeStructure(animal, generation = 0) {
if (generation >= this.settings.maxGenerations) {
return null;
}
const node = {
animal,
generation,
parents: []
};
// Get parents (if stored)
if (animal.parents) {
node.parents = animal.parents.map(parentId => {
const parent = this.scene.animalBreeding.animals.get(parentId);
return parent ? this.generateTreeStructure(parent, generation + 1) : null;
}).filter(p => p !== null);
}
return node;
}
renderTree(node, x, y, generation) {
if (!node) return;
const settings = this.settings;
// Draw node
this.drawAnimalNode(node.animal, x, y);
// Draw parents
if (node.parents.length > 0) {
const parentY = y - settings.verticalSpacing;
const parentSpacing = settings.horizontalSpacing;
node.parents.forEach((parent, index) => {
const parentX = x + (index - 0.5) * parentSpacing;
// Draw connection line
const line = this.scene.add.line(
0, 0,
x, y - settings.nodeHeight / 2,
parentX, parentY + settings.nodeHeight / 2,
0x888888
);
line.setLineWidth(2);
this.familyTreeView.add(line);
// Render parent node
this.renderTree(parent, parentX, parentY, generation + 1);
});
}
}
drawAnimalNode(animal, x, y) {
const settings = this.settings;
// Node background
const nodeColor = this.getNodeColor(animal);
const node = this.scene.add.rectangle(
x, y,
settings.nodeWidth,
settings.nodeHeight,
nodeColor
);
node.setStrokeStyle(2, 0xffffff);
this.familyTreeView.add(node);
// Animal icon/emoji
const icon = this.getAnimalIcon(animal.species);
const iconText = this.scene.add.text(x, y - 10, icon, {
fontSize: '24px'
});
iconText.setOrigin(0.5);
this.familyTreeView.add(iconText);
// Animal name/gender
const genderSymbol = animal.gender === 'male' ? '♂' : '♀';
const nameText = this.scene.add.text(
x, y + 15,
`${genderSymbol} ${animal.species}`,
{
fontSize: '10px',
color: '#ffffff'
}
);
nameText.setOrigin(0.5);
this.familyTreeView.add(nameText);
// Mutation indicator
if (animal.genetics.mutation) {
const mutationBadge = this.scene.add.text(
x + settings.nodeWidth / 2 - 5,
y - settings.nodeHeight / 2 + 5,
'⭐',
{ fontSize: '12px' }
);
mutationBadge.setOrigin(0.5);
this.familyTreeView.add(mutationBadge);
}
// Make interactive
node.setInteractive({ useHandCursor: true });
node.on('pointerdown', () => {
this.selectedAnimal = animal;
this.displayGeneticsInfo(animal);
});
}
getNodeColor(animal) {
// Color based on genetics
const colorMap = {
brown: 0x8B4513,
black: 0x000000,
white: 0xFFFFFF,
golden: 0xFFD700,
rainbow: 0xFF00FF
};
return colorMap[animal.genetics.color] || 0x888888;
}
getAnimalIcon(species) {
const icons = {
sheep: '🐑',
cow: '🐄',
chicken: '🐔',
pig: '🐷',
horse: '🐴'
};
return icons[species] || '🐾';
}
// ========== GENETICS PANEL ==========
displayGeneticsInfo(animal) {
// Clear previous info
this.geneticsPanel.removeAll(true);
let yOffset = -200;
// Title
const title = this.scene.add.text(0, yOffset, 'Genetics Info', {
fontSize: '18px',
fontStyle: 'bold',
color: '#ffffff'
});
title.setOrigin(0.5);
this.geneticsPanel.add(title);
yOffset += 40;
// Animal info
const info = [
`Species: ${animal.species}`,
`Gender: ${animal.gender}`,
`Age: ${Math.floor(animal.age)} days`,
`Stage: ${animal.stage}`,
'',
'--- Genetics ---',
`Color: ${animal.genetics.color}`,
`Size: ${animal.genetics.size}`,
`Speed: ${animal.genetics.speed}`,
`Production: ${animal.genetics.production}`
];
// Mutation info
if (animal.genetics.mutation) {
info.push('', '--- Mutation ---');
info.push(`Type: ${animal.genetics.mutation}`);
info.push('⭐ RARE MUTATION!');
}
// Breeding info
if (animal.pregnant) {
info.push('', '--- Breeding ---');
info.push(`Pregnant: ${Math.floor(animal.gestationProgress * 100)}%`);
}
// Display all info
info.forEach(line => {
const text = this.scene.add.text(0, yOffset, line, {
fontSize: '14px',
color: line.includes('---') ? '#ffff00' : '#ffffff'
});
text.setOrigin(0.5);
this.geneticsPanel.add(text);
yOffset += 20;
});
// DNA Helix Animation
if (animal.genetics.mutation) {
this.addDNAHelixAnimation(0, yOffset + 50);
}
}
addDNAHelixAnimation(x, y) {
// Create mini DNA helix
const helix = this.scene.add.container(x, y);
for (let i = 0; i < 10; i++) {
const yPos = i * 5 - 25;
const angle = (i / 10) * Math.PI * 2;
const x1 = Math.cos(angle) * 10;
const x2 = Math.cos(angle + Math.PI) * 10;
const dot1 = this.scene.add.circle(x1, yPos, 2, 0x00ff00);
const dot2 = this.scene.add.circle(x2, yPos, 2, 0x00ffff);
helix.add(dot1);
helix.add(dot2);
}
// Rotate animation
this.scene.tweens.add({
targets: helix,
rotation: Math.PI * 2,
duration: 3000,
repeat: -1,
ease: 'Linear'
});
this.geneticsPanel.add(helix);
}
// ========== BREEDING PREDICTION ==========
showBreedingPrediction(animal1, animal2) {
if (!animal1 || !animal2) return;
// Predict offspring genetics
const prediction = this.predictOffspring(animal1, animal2);
// Show in UI
this.displayPrediction(prediction);
}
predictOffspring(parent1, parent2) {
// Simulate genetics inheritance
const prediction = {
possibleColors: this.predictColor(parent1, parent2),
possibleSizes: this.predictTrait(parent1.genetics.size, parent2.genetics.size),
possibleSpeeds: this.predictTrait(parent1.genetics.speed, parent2.genetics.speed),
mutationChance: 0.05 // 5%
};
return prediction;
}
predictColor(p1, p2) {
const colors = [p1.genetics.color, p2.genetics.color];
// Add dominant/recessive logic
const dominant = ['brown', 'black'];
const recessive = ['white', 'golden'];
if (dominant.includes(p1.genetics.color)) {
return [p1.genetics.color];
}
if (dominant.includes(p2.genetics.color)) {
return [p2.genetics.color];
}
return colors;
}
predictTrait(trait1, trait2) {
return [trait1, trait2];
}
displayPrediction(prediction) {
// Clear genetics panel
this.geneticsPanel.removeAll(true);
let yOffset = -200;
const title = this.scene.add.text(0, yOffset, 'Breeding Prediction', {
fontSize: '18px',
fontStyle: 'bold',
color: '#ffff00'
});
title.setOrigin(0.5);
this.geneticsPanel.add(title);
yOffset += 40;
// Display predictions
const info = [
'Possible Offspring:',
'',
`Colors: ${prediction.possibleColors.join(', ')}`,
`Sizes: ${prediction.possibleSizes.join(', ')}`,
`Speeds: ${prediction.possibleSpeeds.join(', ')}`,
'',
`Mutation Chance: ${prediction.mutationChance * 100}%`
];
info.forEach(line => {
const text = this.scene.add.text(0, yOffset, line, {
fontSize: '14px',
color: '#ffffff'
});
text.setOrigin(0.5);
this.geneticsPanel.add(text);
yOffset += 20;
});
}
// ========== KEYBOARD SHORTCUT ==========
setupKeyboard() {
// Press 'F' to open family tree for selected animal
this.scene.input.keyboard.on('keydown-F', () => {
if (this.selectedAnimal) {
if (this.isVisible) {
this.hide();
} else {
this.show(this.selectedAnimal.id);
}
}
});
}
// ========== UPDATE ==========
update(delta) {
// Update animations if visible
if (this.isVisible) {
// Any dynamic updates here
}
}
destroy() {
if (this.container) {
this.container.destroy();
}
console.log('🌳 Breeding UI System destroyed');
}
}

View File

@@ -0,0 +1,634 @@
/**
* BUILDING VISUALS & GENETICS SYSTEM
* Advanced animations for farm automation buildings and genetics lab
*/
class BuildingVisualsSystem {
constructor(scene) {
this.scene = scene;
this.enabled = true;
// Building animations
this.buildings = new Map();
this.conveyorBelts = [];
this.windmills = [];
this.silos = [];
// Genetics lab
this.geneticsLab = null;
this.dnaHelixAnimation = null;
this.mutationVats = [];
// Settings
this.settings = {
buildingAnimations: true,
particleEffects: true,
geneticsUI: true,
animationSpeed: 1.0
};
this.loadSettings();
this.init();
console.log('✅ Building Visuals System initialized');
}
init() {
console.log('🏭 Building animations ready');
}
// ========== AUTO-PLANTER ==========
createAutoPlanter(x, y) {
if (!this.settings.buildingAnimations) return null;
const planter = {
x, y,
arm: null,
seed: null,
isPlanting: false
};
// Create mechanical arm
const arm = this.scene.add.graphics();
arm.lineStyle(4, 0x888888, 1);
arm.lineBetween(0, 0, 0, 30); // Vertical arm
arm.lineBetween(0, 30, 20, 30); // Horizontal extension
arm.setPosition(x, y);
arm.setDepth(100);
planter.arm = arm;
this.buildings.set(`planter_${x}_${y}`, planter);
return planter;
}
animatePlanting(planter, targetX, targetY) {
if (!planter || planter.isPlanting) return;
planter.isPlanting = true;
// Arm extends down
this.scene.tweens.add({
targets: planter.arm,
y: planter.y + 20,
duration: 500,
ease: 'Power2',
onComplete: () => {
// Drop seed
this.createSeedParticle(targetX, targetY);
// Arm retracts
this.scene.tweens.add({
targets: planter.arm,
y: planter.y,
duration: 500,
ease: 'Power2',
onComplete: () => {
planter.isPlanting = false;
}
});
}
});
}
createSeedParticle(x, y) {
const seed = this.scene.add.circle(x, y - 20, 3, 0x8B4513);
seed.setDepth(99);
this.scene.tweens.add({
targets: seed,
y: y,
duration: 300,
ease: 'Bounce.easeOut',
onComplete: () => {
// Puff of dirt
if (this.scene.visualEnhancements) {
this.scene.visualEnhancements.createSparkleEffect(x, y);
}
seed.destroy();
}
});
}
// ========== AUTO-HARVESTER ==========
createAutoHarvester(x, y) {
if (!this.settings.buildingAnimations) return null;
const harvester = {
x, y,
blades: [],
isHarvesting: false,
rotation: 0
};
// Create spinning blades
for (let i = 0; i < 4; i++) {
const blade = this.scene.add.graphics();
blade.lineStyle(3, 0xC0C0C0, 1);
blade.lineBetween(0, 0, 15, 0);
blade.setPosition(x, y);
blade.setRotation((Math.PI / 2) * i);
blade.setDepth(100);
harvester.blades.push(blade);
}
this.buildings.set(`harvester_${x}_${y}`, harvester);
return harvester;
}
animateHarvesting(harvester, cropX, cropY) {
if (!harvester || harvester.isHarvesting) return;
harvester.isHarvesting = true;
// Spin blades
for (const blade of harvester.blades) {
this.scene.tweens.add({
targets: blade,
rotation: blade.rotation + Math.PI * 4,
duration: 1000,
ease: 'Linear'
});
}
// Move to crop
this.scene.tweens.add({
targets: harvester.blades,
x: cropX,
y: cropY,
duration: 500,
ease: 'Power2',
onComplete: () => {
// Harvest effect
this.createHarvestEffect(cropX, cropY);
// Return to base
this.scene.tweens.add({
targets: harvester.blades,
x: harvester.x,
y: harvester.y,
duration: 500,
ease: 'Power2',
onComplete: () => {
harvester.isHarvesting = false;
}
});
}
});
}
createHarvestEffect(x, y) {
// Crop particles
const emitter = this.scene.add.particles(x, y, 'particle_white', {
speed: { min: 30, max: 60 },
scale: { start: 0.5, end: 0 },
alpha: { start: 1, end: 0 },
lifespan: 800,
quantity: 10,
tint: 0xFFD700
});
this.scene.time.delayedCall(800, () => emitter.destroy());
}
// ========== CONVEYOR BELT ==========
createConveyorBelt(x, y, width, direction = 'right') {
if (!this.settings.buildingAnimations) return null;
const belt = {
x, y, width, direction,
items: [],
speed: 50 // pixels per second
};
// Create belt graphics
const graphics = this.scene.add.graphics();
graphics.fillStyle(0x444444, 1);
graphics.fillRect(x, y, width, 20);
// Moving lines to show direction
for (let i = 0; i < width; i += 20) {
const line = this.scene.add.rectangle(
x + i,
y + 10,
10,
2,
0x888888
);
line.setDepth(99);
// Animate line movement
const targetX = direction === 'right' ? x + width : x;
this.scene.tweens.add({
targets: line,
x: targetX,
duration: (width / belt.speed) * 1000,
repeat: -1,
ease: 'Linear'
});
}
belt.graphics = graphics;
this.conveyorBelts.push(belt);
return belt;
}
addItemToBelt(belt, itemSprite) {
if (!belt) return;
belt.items.push(itemSprite);
itemSprite.setPosition(belt.x, belt.y + 10);
itemSprite.setDepth(100);
// Move item along belt
const targetX = belt.direction === 'right'
? belt.x + belt.width
: belt.x;
this.scene.tweens.add({
targets: itemSprite,
x: targetX,
duration: (belt.width / belt.speed) * 1000,
ease: 'Linear',
onComplete: () => {
// Remove from belt
const index = belt.items.indexOf(itemSprite);
if (index > -1) {
belt.items.splice(index, 1);
}
}
});
}
// ========== WINDMILL ==========
createWindmill(x, y) {
if (!this.settings.buildingAnimations) return null;
const windmill = {
x, y,
blades: null,
powerGlow: null,
isPowered: false,
rotation: 0
};
// Create blades
const blades = this.scene.add.graphics();
blades.lineStyle(4, 0x8B4513, 1);
// Draw 4 blades
for (let i = 0; i < 4; i++) {
const angle = (Math.PI / 2) * i;
const endX = Math.cos(angle) * 30;
const endY = Math.sin(angle) * 30;
blades.lineBetween(0, 0, endX, endY);
}
blades.setPosition(x, y);
blades.setDepth(100);
windmill.blades = blades;
// Power glow
const glow = this.scene.add.circle(x, y, 40, 0x00ffff, 0);
glow.setBlendMode(Phaser.BlendModes.ADD);
glow.setDepth(99);
windmill.powerGlow = glow;
// Rotate blades
this.scene.tweens.add({
targets: blades,
rotation: Math.PI * 2,
duration: 3000 / this.settings.animationSpeed,
repeat: -1,
ease: 'Linear'
});
this.windmills.push(windmill);
return windmill;
}
setPowerState(windmill, powered) {
if (!windmill) return;
windmill.isPowered = powered;
if (powered) {
// Glow on
this.scene.tweens.add({
targets: windmill.powerGlow,
alpha: 0.4,
duration: 500
});
// Particle trail
if (this.settings.particleEffects) {
const emitter = this.scene.add.particles(
windmill.x,
windmill.y,
'particle_white',
{
speed: 20,
scale: { start: 0.3, end: 0 },
alpha: { start: 0.6, end: 0 },
lifespan: 1000,
frequency: 200,
quantity: 1,
tint: 0x00ffff
}
);
windmill.particleEmitter = emitter;
}
} else {
// Glow off
this.scene.tweens.add({
targets: windmill.powerGlow,
alpha: 0,
duration: 500
});
// Stop particles
if (windmill.particleEmitter) {
windmill.particleEmitter.destroy();
windmill.particleEmitter = null;
}
}
}
// ========== STORAGE SILO ==========
createStorageSilo(x, y, capacity = 1000) {
if (!this.settings.buildingAnimations) return null;
const silo = {
x, y,
capacity,
currentAmount: 0,
fillIndicator: null,
fillBar: null
};
// Silo structure
const structure = this.scene.add.graphics();
structure.fillStyle(0x666666, 1);
structure.fillRect(x - 20, y - 60, 40, 60);
structure.fillCircle(x, y - 60, 20);
structure.setDepth(100);
silo.structure = structure;
// Fill indicator (inside silo)
const fillBar = this.scene.add.rectangle(
x,
y,
36,
0,
0xFFD700,
0.8
);
fillBar.setOrigin(0.5, 1);
fillBar.setDepth(101);
silo.fillBar = fillBar;
// Percentage text
const text = this.scene.add.text(x, y - 70, '0%', {
fontSize: '12px',
color: '#ffffff',
fontStyle: 'bold'
});
text.setOrigin(0.5);
text.setDepth(102);
silo.text = text;
this.silos.push(silo);
return silo;
}
updateSiloFill(silo, amount) {
if (!silo) return;
silo.currentAmount = Phaser.Math.Clamp(amount, 0, silo.capacity);
const percentage = (silo.currentAmount / silo.capacity) * 100;
const fillHeight = (percentage / 100) * 56; // Max height
// Animate fill
this.scene.tweens.add({
targets: silo.fillBar,
height: fillHeight,
duration: 500,
ease: 'Power2'
});
// Update text
silo.text.setText(`${Math.round(percentage)}%`);
}
// ========== GENETICS LAB ==========
createGeneticsLab(x, y) {
if (!this.settings.geneticsUI) return null;
const lab = {
x, y,
dnaHelix: null,
vats: [],
isActive: false
};
// Lab structure
const structure = this.scene.add.rectangle(x, y, 80, 60, 0x333333);
structure.setStrokeStyle(2, 0x00ff00);
structure.setDepth(100);
lab.structure = structure;
this.geneticsLab = lab;
return lab;
}
showDNAHelixAnimation(x, y) {
if (!this.settings.geneticsUI) return null;
// Create DNA helix
const helix = this.scene.add.container(x, y);
helix.setDepth(200);
// Two strands
const strand1 = [];
const strand2 = [];
for (let i = 0; i < 20; i++) {
const yPos = i * 10 - 100;
const angle = (i / 20) * Math.PI * 4;
const x1 = Math.cos(angle) * 15;
const x2 = Math.cos(angle + Math.PI) * 15;
const dot1 = this.scene.add.circle(x1, yPos, 3, 0x00ff00);
const dot2 = this.scene.add.circle(x2, yPos, 3, 0x00ffff);
helix.add(dot1);
helix.add(dot2);
strand1.push(dot1);
strand2.push(dot2);
// Connecting lines
if (i % 3 === 0) {
const line = this.scene.add.graphics();
line.lineStyle(1, 0xffffff, 0.5);
line.lineBetween(x1, yPos, x2, yPos);
helix.add(line);
}
}
// Rotate helix
this.scene.tweens.add({
targets: helix,
rotation: Math.PI * 2,
duration: 4000,
repeat: -1,
ease: 'Linear'
});
// Pulse effect
this.scene.tweens.add({
targets: helix,
scale: { from: 1, to: 1.1 },
duration: 2000,
yoyo: true,
repeat: -1
});
this.dnaHelixAnimation = helix;
return helix;
}
hideDNAHelixAnimation() {
if (this.dnaHelixAnimation) {
this.dnaHelixAnimation.destroy();
this.dnaHelixAnimation = null;
}
}
createMutationVat(x, y) {
if (!this.settings.geneticsUI) return null;
const vat = {
x, y,
container: null,
liquid: null,
bubbles: null,
isActive: false
};
// Vat container
const container = this.scene.add.graphics();
container.fillStyle(0x444444, 1);
container.fillRect(x - 20, y - 40, 40, 40);
container.lineStyle(2, 0x666666);
container.strokeRect(x - 20, y - 40, 40, 40);
container.setDepth(100);
vat.container = container;
// Liquid
const liquid = this.scene.add.rectangle(
x,
y - 20,
36,
36,
0x00ff00,
0.6
);
liquid.setDepth(101);
vat.liquid = liquid;
this.mutationVats.push(vat);
return vat;
}
activateMutationVat(vat) {
if (!vat || vat.isActive) return;
vat.isActive = true;
// Bubbling effect
const emitter = this.scene.add.particles(
vat.x,
vat.y - 40,
'particle_white',
{
speedY: { min: -30, max: -50 },
speedX: { min: -5, max: 5 },
scale: { start: 0.2, end: 0 },
alpha: { start: 0.8, end: 0 },
lifespan: 1000,
frequency: 200,
quantity: 2,
tint: 0x00ff00
}
);
vat.bubbles = emitter;
// Lightning effect
if (this.settings.particleEffects) {
this.createLightningEffect(vat.x, vat.y - 60);
}
// Liquid glow pulse
this.scene.tweens.add({
targets: vat.liquid,
alpha: { from: 0.6, to: 0.9 },
duration: 800,
yoyo: true,
repeat: -1
});
}
createLightningEffect(x, y) {
const lightning = this.scene.add.graphics();
lightning.lineStyle(2, 0xffff00, 1);
// Zigzag lightning
let currentX = x;
let currentY = y;
for (let i = 0; i < 5; i++) {
const nextX = currentX + (Math.random() - 0.5) * 20;
const nextY = currentY + 10;
lightning.lineBetween(currentX, currentY, nextX, nextY);
currentX = nextX;
currentY = nextY;
}
lightning.setDepth(200);
// Flash and fade
this.scene.tweens.add({
targets: lightning,
alpha: 0,
duration: 200,
onComplete: () => lightning.destroy()
});
}
// ========== SETTINGS ==========
saveSettings() {
localStorage.setItem('novafarma_building_visuals', JSON.stringify(this.settings));
}
loadSettings() {
const saved = localStorage.getItem('novafarma_building_visuals');
if (saved) {
this.settings = { ...this.settings, ...JSON.parse(saved) };
}
}
destroy() {
if (this.dnaHelixAnimation) this.dnaHelixAnimation.destroy();
for (const vat of this.mutationVats) {
if (vat.bubbles) vat.bubbles.destroy();
}
console.log('🏭 Building Visuals System destroyed');
}
}

View File

@@ -0,0 +1,475 @@
/**
* COOKING & RECIPE SYSTEM
* Complete cooking system with recipes, food buffs, spoilage, and skill progression
*/
class CookingSystem {
constructor(scene) {
this.scene = scene;
this.enabled = true;
// Recipes
this.recipes = new Map();
this.knownRecipes = new Set();
// Cooking stations
this.cookingStations = new Map();
// Active cooking
this.activeCooking = [];
// Food items
this.foodItems = new Map();
// Cooking skill
this.cookingLevel = 1;
this.cookingXP = 0;
// Settings
this.settings = {
spoilageRate: 0.01, // 1% per minute
xpPerRecipe: 10,
xpScaling: 1.5
};
this.loadProgress();
this.init();
console.log('✅ Cooking System initialized');
}
init() {
this.defineRecipes();
this.defineCookingStations();
console.log('🍳 Cooking system ready');
}
// ========== RECIPES ==========
defineRecipes() {
// Basic recipes
this.defineRecipe('wheat_bread', {
name: 'Wheat Bread',
ingredients: { wheat: 3, water: 1 },
cookTime: 30, // seconds
cookingStation: 'oven',
buffs: { hunger: 50, health: 10 },
buffDuration: 0, // permanent (hunger/health)
spoilTime: 300, // 5 minutes
xp: 10,
requiredLevel: 1
});
this.defineRecipe('vegetable_soup', {
name: 'Vegetable Soup',
ingredients: { carrot: 2, potato: 2, water: 1 },
cookTime: 45,
cookingStation: 'stove',
buffs: { hunger: 60, health: 15, stamina: 20 },
buffDuration: 180, // 3 minutes
spoilTime: 240,
xp: 15,
requiredLevel: 2
});
this.defineRecipe('grilled_meat', {
name: 'Grilled Meat',
ingredients: { raw_meat: 1 },
cookTime: 20,
cookingStation: 'grill',
buffs: { hunger: 70, health: 20, strength: 15 },
buffDuration: 300, // 5 minutes
spoilTime: 180,
xp: 20,
requiredLevel: 3
});
this.defineRecipe('mutant_stew', {
name: 'Mutant Stew',
ingredients: { mutant_meat: 2, carrot: 3, potato: 2, water: 1 },
cookTime: 60,
cookingStation: 'cauldron',
buffs: { hunger: 80, health: 30, strength: 25, speed: 15 },
buffDuration: 600, // 10 minutes
spoilTime: 360,
xp: 50,
requiredLevel: 5
});
this.defineRecipe('golden_apple_pie', {
name: 'Golden Apple Pie',
ingredients: { golden_apple: 1, wheat: 5, sugar: 3 },
cookTime: 90,
cookingStation: 'oven',
buffs: { hunger: 100, health: 50, all_stats: 20 },
buffDuration: 900, // 15 minutes
spoilTime: 600,
xp: 100,
requiredLevel: 10
});
}
defineRecipe(id, data) {
this.recipes.set(id, {
id,
...data,
discovered: false
});
}
// ========== COOKING STATIONS ==========
defineCookingStations() {
this.cookingStations.set('stove', {
name: 'Stove',
cost: { iron: 10, wood: 5 },
cookingSpeed: 1.0
});
this.cookingStations.set('oven', {
name: 'Oven',
cost: { iron: 15, stone: 20 },
cookingSpeed: 1.2
});
this.cookingStations.set('grill', {
name: 'Grill',
cost: { iron: 8, wood: 10 },
cookingSpeed: 0.8
});
this.cookingStations.set('cauldron', {
name: 'Cauldron',
cost: { iron: 20, magic_crystal: 1 },
cookingSpeed: 1.5
});
}
// ========== COOKING ==========
canCook(recipeId) {
const recipe = this.recipes.get(recipeId);
if (!recipe) return false;
// Check level
if (this.cookingLevel < recipe.requiredLevel) {
console.log(`❌ Requires cooking level ${recipe.requiredLevel}`);
return false;
}
// Check ingredients
if (!this.scene.inventorySystem) return false;
for (const [ingredient, amount] of Object.entries(recipe.ingredients)) {
const has = this.scene.inventorySystem.getItemCount(ingredient);
if (has < amount) {
console.log(`❌ Missing ${ingredient}: ${has}/${amount}`);
return false;
}
}
return true;
}
startCooking(recipeId, stationType) {
if (!this.canCook(recipeId)) return false;
const recipe = this.recipes.get(recipeId);
const station = this.cookingStations.get(stationType);
if (!station) {
console.log('❌ Invalid cooking station');
return false;
}
if (recipe.cookingStation !== stationType) {
console.log(`❌ Requires ${recipe.cookingStation}`);
return false;
}
// Consume ingredients
for (const [ingredient, amount] of Object.entries(recipe.ingredients)) {
this.scene.inventorySystem.removeItem(ingredient, amount);
}
// Start cooking
const cookTime = recipe.cookTime / station.cookingSpeed;
const cooking = {
recipeId,
startTime: Date.now(),
cookTime: cookTime * 1000, // convert to ms
station: stationType
};
this.activeCooking.push(cooking);
// Discover recipe
if (!recipe.discovered) {
this.discoverRecipe(recipeId);
}
console.log(`🍳 Started cooking ${recipe.name} (${cookTime}s)`);
return true;
}
updateCooking(delta) {
const now = Date.now();
for (let i = this.activeCooking.length - 1; i >= 0; i--) {
const cooking = this.activeCooking[i];
const elapsed = now - cooking.startTime;
if (elapsed >= cooking.cookTime) {
// Cooking complete!
this.completeCooking(cooking);
this.activeCooking.splice(i, 1);
}
}
}
completeCooking(cooking) {
const recipe = this.recipes.get(cooking.recipeId);
// Create food item
const food = this.createFoodItem(recipe);
// Add to inventory
if (this.scene.inventorySystem) {
this.scene.inventorySystem.addItem(cooking.recipeId, 1);
}
// Grant XP
this.addCookingXP(recipe.xp);
// Visual effect
if (this.scene.visualEnhancements) {
const player = this.scene.player;
if (player) {
const pos = player.getPosition();
this.scene.visualEnhancements.createSparkleEffect(pos.x, pos.y);
}
}
console.log(`✅ Cooked ${recipe.name}!`);
}
createFoodItem(recipe) {
const food = {
id: `food_${Date.now()}`,
recipeId: recipe.id,
name: recipe.name,
buffs: recipe.buffs,
buffDuration: recipe.buffDuration,
createdTime: Date.now(),
spoilTime: recipe.spoilTime * 1000,
spoiled: false
};
this.foodItems.set(food.id, food);
return food;
}
// ========== EATING ==========
eatFood(foodId) {
const food = this.foodItems.get(foodId);
if (!food) return false;
// Check if spoiled
if (this.isSpoiled(food)) {
console.log('🤢 Food is spoiled!');
// Negative effects
if (this.scene.statsSystem) {
this.scene.statsSystem.health -= 10;
}
this.foodItems.delete(foodId);
return false;
}
// Apply buffs
this.applyFoodBuffs(food);
// Remove food
this.foodItems.delete(foodId);
console.log(`😋 Ate ${food.name}!`);
return true;
}
applyFoodBuffs(food) {
const buffs = food.buffs;
// Permanent buffs (hunger, health)
if (this.scene.statsSystem) {
if (buffs.hunger) {
this.scene.statsSystem.hunger = Math.min(100, this.scene.statsSystem.hunger + buffs.hunger);
}
if (buffs.health) {
this.scene.statsSystem.health = Math.min(this.scene.statsSystem.maxHealth, this.scene.statsSystem.health + buffs.health);
}
}
// Temporary buffs
if (food.buffDuration > 0) {
this.applyTemporaryBuffs(buffs, food.buffDuration);
}
}
applyTemporaryBuffs(buffs, duration) {
// Apply buffs for duration
const buffData = {
buffs,
startTime: Date.now(),
duration: duration * 1000
};
// Store active buffs (would integrate with player stats)
console.log(`✨ Buffs active for ${duration}s:`, buffs);
// Schedule buff removal
setTimeout(() => {
console.log('⏰ Buffs expired');
}, duration * 1000);
}
// ========== SPOILAGE ==========
updateSpoilage(delta) {
const now = Date.now();
for (const food of this.foodItems.values()) {
const age = now - food.createdTime;
if (age > food.spoilTime) {
food.spoiled = true;
}
}
}
isSpoiled(food) {
const age = Date.now() - food.createdTime;
return age > food.spoilTime;
}
// ========== RECIPE DISCOVERY ==========
discoverRecipe(recipeId) {
const recipe = this.recipes.get(recipeId);
if (!recipe) return;
recipe.discovered = true;
this.knownRecipes.add(recipeId);
console.log(`📖 Discovered recipe: ${recipe.name}!`);
// Achievement
if (this.scene.uiGraphics && this.knownRecipes.size >= 10) {
this.scene.uiGraphics.unlockAchievement('master_chef');
}
this.saveProgress();
}
tryDiscoverRecipe(ingredients) {
// Try to match ingredients to unknown recipes
for (const [recipeId, recipe] of this.recipes.entries()) {
if (recipe.discovered) continue;
// Check if ingredients match
const matches = this.matchIngredients(ingredients, recipe.ingredients);
if (matches) {
this.discoverRecipe(recipeId);
return recipe;
}
}
return null;
}
matchIngredients(provided, required) {
const providedKeys = Object.keys(provided).sort();
const requiredKeys = Object.keys(required).sort();
if (providedKeys.length !== requiredKeys.length) return false;
for (let i = 0; i < providedKeys.length; i++) {
if (providedKeys[i] !== requiredKeys[i]) return false;
}
return true;
}
// ========== SKILL PROGRESSION ==========
addCookingXP(amount) {
this.cookingXP += amount;
// Level up check
const xpNeeded = this.getCookingXPForLevel(this.cookingLevel + 1);
if (this.cookingXP >= xpNeeded) {
this.levelUpCooking();
}
this.saveProgress();
}
getCookingXPForLevel(level) {
return Math.floor(100 * Math.pow(this.settings.xpScaling, level - 1));
}
levelUpCooking() {
this.cookingLevel++;
this.cookingXP = 0;
console.log(`🎉 Cooking level up! Now level ${this.cookingLevel}`);
// Visual effect
if (this.scene.visualEnhancements) {
const player = this.scene.player;
if (player) {
const pos = player.getPosition();
this.scene.visualEnhancements.createSparkleEffect(pos.x, pos.y);
}
}
this.saveProgress();
}
// ========== UPDATE ==========
update(delta) {
this.updateCooking(delta);
this.updateSpoilage(delta);
}
// ========== PERSISTENCE ==========
saveProgress() {
const data = {
cookingLevel: this.cookingLevel,
cookingXP: this.cookingXP,
knownRecipes: Array.from(this.knownRecipes)
};
localStorage.setItem('novafarma_cooking', JSON.stringify(data));
}
loadProgress() {
const saved = localStorage.getItem('novafarma_cooking');
if (saved) {
try {
const data = JSON.parse(saved);
this.cookingLevel = data.cookingLevel || 1;
this.cookingXP = data.cookingXP || 0;
this.knownRecipes = new Set(data.knownRecipes || []);
console.log('✅ Cooking progress loaded');
} catch (error) {
console.error('Failed to load cooking progress:', error);
}
}
}
destroy() {
this.saveProgress();
console.log('🍳 Cooking System destroyed');
}
}

View File

@@ -0,0 +1,377 @@
/**
* CRAFTING TIERS SYSTEM
* Tool tiers, durability, and repair mechanics
*/
class CraftingTiersSystem {
constructor(scene) {
this.scene = scene;
this.enabled = true;
// Tool tiers
this.tiers = {
wood: { name: 'Wooden', durability: 50, speed: 1.0, damage: 1.0, color: 0x8B4513 },
bronze: { name: 'Bronze', durability: 150, speed: 1.2, damage: 1.3, color: 0xCD7F32 },
iron: { name: 'Iron', durability: 300, speed: 1.5, damage: 1.6, color: 0xC0C0C0 },
steel: { name: 'Steel', durability: 600, speed: 1.8, damage: 2.0, color: 0x4682B4 },
enchanted: { name: 'Enchanted', durability: 1200, speed: 2.5, damage: 3.0, color: 0x9370DB }
};
// Tool types
this.toolTypes = ['sword', 'pickaxe', 'axe', 'hoe', 'shovel'];
// Player's tools
this.playerTools = new Map();
// Crafting recipes
this.recipes = new Map();
this.loadProgress();
this.init();
console.log('✅ Crafting Tiers System initialized');
}
init() {
this.defineRecipes();
console.log('⚒️ Crafting recipes ready');
}
// ========== RECIPE DEFINITIONS ==========
defineRecipes() {
// BRONZE TIER (Copper + Tin)
this.defineRecipe('bronze_sword', {
name: 'Bronze Sword',
tier: 'bronze',
type: 'sword',
materials: { copper: 3, tin: 1 },
unlockLevel: 5
});
this.defineRecipe('bronze_pickaxe', {
name: 'Bronze Pickaxe',
tier: 'bronze',
type: 'pickaxe',
materials: { copper: 3, tin: 1, wood: 2 },
unlockLevel: 5
});
this.defineRecipe('bronze_axe', {
name: 'Bronze Axe',
tier: 'bronze',
type: 'axe',
materials: { copper: 3, tin: 1, wood: 2 },
unlockLevel: 5
});
// IRON TIER
this.defineRecipe('iron_sword', {
name: 'Iron Sword',
tier: 'iron',
type: 'sword',
materials: { iron: 5 },
unlockLevel: 10
});
this.defineRecipe('iron_pickaxe', {
name: 'Iron Pickaxe',
tier: 'iron',
type: 'pickaxe',
materials: { iron: 5, wood: 3 },
unlockLevel: 10
});
this.defineRecipe('iron_axe', {
name: 'Iron Axe',
tier: 'iron',
type: 'axe',
materials: { iron: 5, wood: 3 },
unlockLevel: 10
});
// STEEL TIER (Iron + Coal)
this.defineRecipe('steel_sword', {
name: 'Steel Sword',
tier: 'steel',
type: 'sword',
materials: { iron: 5, coal: 3 },
unlockLevel: 20
});
this.defineRecipe('steel_pickaxe', {
name: 'Steel Pickaxe',
tier: 'steel',
type: 'pickaxe',
materials: { iron: 5, coal: 3, wood: 2 },
unlockLevel: 20
});
// ENCHANTED TIER (Magical)
this.defineRecipe('enchanted_sword', {
name: 'Enchanted Sword',
tier: 'enchanted',
type: 'sword',
materials: { steel_sword: 1, magic_crystal: 5, dragon_scale: 3 },
unlockLevel: 30
});
}
defineRecipe(id, data) {
this.recipes.set(id, {
id,
...data
});
}
// ========== CRAFTING ==========
canCraft(recipeId) {
const recipe = this.recipes.get(recipeId);
if (!recipe) return false;
// Check level requirement
if (this.scene.skillTree && this.scene.skillTree.playerLevel < recipe.unlockLevel) {
return false;
}
// Check materials
if (!this.scene.inventorySystem) return false;
for (const [material, amount] of Object.entries(recipe.materials)) {
const has = this.scene.inventorySystem.getItemCount(material);
if (has < amount) {
return false;
}
}
return true;
}
craft(recipeId) {
if (!this.canCraft(recipeId)) {
console.log('❌ Cannot craft:', recipeId);
return false;
}
const recipe = this.recipes.get(recipeId);
// Consume materials
for (const [material, amount] of Object.entries(recipe.materials)) {
this.scene.inventorySystem.removeItem(material, amount);
}
// Create tool
const tool = this.createTool(recipe.tier, recipe.type);
this.playerTools.set(`${recipe.type}_${recipe.tier}`, tool);
// Add to inventory
if (this.scene.inventorySystem) {
this.scene.inventorySystem.addItem(recipeId, 1);
}
// Unlock achievement
if (this.scene.uiGraphics) {
if (recipe.tier === 'enchanted') {
this.scene.uiGraphics.unlockAchievement('master_crafter');
}
}
this.saveProgress();
console.log(`✅ Crafted: ${recipe.name}`);
return true;
}
// ========== TOOL MANAGEMENT ==========
createTool(tier, type) {
const tierData = this.tiers[tier];
return {
tier,
type,
durability: tierData.durability,
maxDurability: tierData.durability,
speed: tierData.speed,
damage: tierData.damage,
color: tierData.color,
enchantments: []
};
}
getTool(type) {
// Get best available tool of this type
const tierOrder = ['enchanted', 'steel', 'iron', 'bronze', 'wood'];
for (const tier of tierOrder) {
const key = `${type}_${tier}`;
const tool = this.playerTools.get(key);
if (tool && tool.durability > 0) {
return tool;
}
}
return null;
}
useTool(type, amount = 1) {
const tool = this.getTool(type);
if (!tool) return false;
tool.durability -= amount;
// Tool broke
if (tool.durability <= 0) {
tool.durability = 0;
console.log(`💔 ${this.tiers[tool.tier].name} ${tool.type} broke!`);
// Visual effect
if (this.scene.visualEnhancements) {
const player = this.scene.player;
if (player) {
const pos = player.getPosition();
this.scene.visualEnhancements.createSparkleEffect(pos.x, pos.y);
}
}
}
this.saveProgress();
return true;
}
getToolDurabilityPercent(type) {
const tool = this.getTool(type);
if (!tool) return 0;
return (tool.durability / tool.maxDurability) * 100;
}
// ========== TOOL REPAIR ==========
canRepair(type) {
const tool = this.getTool(type);
if (!tool || tool.durability === tool.maxDurability) return false;
// Check materials
const repairCost = this.getRepairCost(tool);
if (!this.scene.inventorySystem) return false;
for (const [material, amount] of Object.entries(repairCost)) {
const has = this.scene.inventorySystem.getItemCount(material);
if (has < amount) {
return false;
}
}
return true;
}
getRepairCost(tool) {
const durabilityLost = tool.maxDurability - tool.durability;
const repairPercent = durabilityLost / tool.maxDurability;
// Cost scales with damage
const baseCost = {
wood: { wood: 2 },
bronze: { copper: 2, tin: 1 },
iron: { iron: 3 },
steel: { iron: 3, coal: 2 },
enchanted: { magic_crystal: 2 }
};
const cost = {};
const tierCost = baseCost[tool.tier];
for (const [material, amount] of Object.entries(tierCost)) {
cost[material] = Math.ceil(amount * repairPercent);
}
return cost;
}
repair(type) {
if (!this.canRepair(type)) {
console.log('❌ Cannot repair:', type);
return false;
}
const tool = this.getTool(type);
const cost = this.getRepairCost(tool);
// Consume materials
for (const [material, amount] of Object.entries(cost)) {
this.scene.inventorySystem.removeItem(material, amount);
}
// Repair tool
tool.durability = tool.maxDurability;
// Visual effect
if (this.scene.visualEnhancements) {
const player = this.scene.player;
if (player) {
const pos = player.getPosition();
this.scene.visualEnhancements.createSparkleEffect(pos.x, pos.y);
}
}
this.saveProgress();
console.log(`🔧 Repaired: ${this.tiers[tool.tier].name} ${tool.type}`);
return true;
}
// ========== ENCHANTMENTS ==========
enchantTool(type, enchantment) {
const tool = this.getTool(type);
if (!tool || tool.tier !== 'enchanted') return false;
tool.enchantments.push(enchantment);
this.saveProgress();
console.log(`✨ Enchanted ${tool.type} with ${enchantment}`);
return true;
}
// ========== PERSISTENCE ==========
saveProgress() {
const data = {
tools: {}
};
for (const [key, tool] of this.playerTools.entries()) {
data.tools[key] = {
tier: tool.tier,
type: tool.type,
durability: tool.durability,
enchantments: tool.enchantments
};
}
localStorage.setItem('novafarma_crafting_tiers', JSON.stringify(data));
}
loadProgress() {
const saved = localStorage.getItem('novafarma_crafting_tiers');
if (saved) {
try {
const data = JSON.parse(saved);
for (const [key, toolData] of Object.entries(data.tools)) {
const tool = this.createTool(toolData.tier, toolData.type);
tool.durability = toolData.durability;
tool.enchantments = toolData.enchantments || [];
this.playerTools.set(key, tool);
}
console.log('✅ Crafting progress loaded');
} catch (error) {
console.error('Failed to load crafting progress:', error);
}
}
}
destroy() {
this.saveProgress();
console.log('⚒️ Crafting Tiers System destroyed');
}
}

View File

@@ -0,0 +1,563 @@
/**
* FARM AUTOMATION SYSTEM
* Complete automation with zombie workers, creature helpers, buildings, and power grid
*/
class FarmAutomationSystem {
constructor(scene) {
this.scene = scene;
this.enabled = true;
// Workers
this.zombieWorkers = [];
this.creatureWorkers = [];
this.taskQueue = [];
// Buildings
this.automationBuildings = new Map();
this.powerGrid = new Map();
// Power system
this.totalPower = 0;
this.powerConsumption = 0;
// Settings
this.settings = {
maxZombieWorkers: 10,
maxCreatureWorkers: 5,
zombieEfficiency: 0.7, // 70% of player speed
powerUpdateInterval: 1000 // ms
};
this.loadProgress();
this.init();
console.log('✅ Farm Automation System initialized');
}
init() {
// Start power update loop
this.startPowerUpdate();
console.log('🤖 Farm automation ready');
}
// ========== ZOMBIE WORKER SYSTEM ==========
hireZombieWorker(name = 'Zombie') {
if (this.zombieWorkers.length >= this.settings.maxZombieWorkers) {
console.log('❌ Max zombie workers reached');
return null;
}
const worker = {
id: `zombie_${Date.now()}`,
name,
type: 'zombie',
level: 1,
xp: 0,
efficiency: this.settings.zombieEfficiency,
currentTask: null,
position: { x: 0, y: 0 },
hunger: 100,
fatigue: 0,
sprite: null
};
this.zombieWorkers.push(worker);
this.saveProgress();
console.log(`🧟 Hired zombie worker: ${name}`);
return worker;
}
assignTask(worker, task) {
if (!worker) return false;
worker.currentTask = {
type: task.type, // 'plant', 'harvest', 'water'
target: task.target,
priority: task.priority || 1,
startTime: Date.now()
};
console.log(`📋 ${worker.name} assigned to ${task.type}`);
return true;
}
addToTaskQueue(task) {
this.taskQueue.push({
...task,
id: `task_${Date.now()}`,
status: 'pending'
});
// Assign to available worker
this.assignNextTask();
}
assignNextTask() {
// Find idle worker
const idleWorker = [...this.zombieWorkers, ...this.creatureWorkers]
.find(w => !w.currentTask);
if (!idleWorker || this.taskQueue.length === 0) return;
// Get highest priority task
this.taskQueue.sort((a, b) => b.priority - a.priority);
const task = this.taskQueue.shift();
this.assignTask(idleWorker, task);
}
completeTask(worker) {
if (!worker || !worker.currentTask) return;
const task = worker.currentTask;
// Give XP
this.addWorkerXP(worker, 10);
// Increase fatigue
worker.fatigue += 10;
// Clear task
worker.currentTask = null;
// Assign next task
this.assignNextTask();
console.log(`${worker.name} completed ${task.type}`);
}
addWorkerXP(worker, amount) {
worker.xp += amount;
// Level up check
const xpNeeded = worker.level * 100;
if (worker.xp >= xpNeeded) {
worker.level++;
worker.xp = 0;
worker.efficiency += 0.05; // 5% faster per level
console.log(`⬆️ ${worker.name} leveled up to ${worker.level}!`);
}
this.saveProgress();
}
// ========== CREATURE WORKER SYSTEM ==========
tameCreature(creatureType, name) {
if (this.creatureWorkers.length >= this.settings.maxCreatureWorkers) {
console.log('❌ Max creature workers reached');
return null;
}
const specialties = {
donkey: { specialty: 'transport', efficiency: 1.0 },
bigfoot: { specialty: 'gathering', efficiency: 1.2 },
yeti: { specialty: 'snow_tasks', efficiency: 1.1 },
elf: { specialty: 'crafting', efficiency: 1.3 }
};
const data = specialties[creatureType] || { specialty: 'general', efficiency: 0.8 };
const worker = {
id: `creature_${Date.now()}`,
name,
type: creatureType,
specialty: data.specialty,
level: 1,
xp: 0,
efficiency: data.efficiency,
currentTask: null,
position: { x: 0, y: 0 },
hunger: 100,
fatigue: 0,
sprite: null
};
this.creatureWorkers.push(worker);
this.saveProgress();
console.log(`🦌 Tamed ${creatureType}: ${name} (${data.specialty})`);
return worker;
}
// ========== AUTOMATION BUILDINGS ==========
buildAutomation(type, x, y) {
const buildings = {
'auto_planter': {
name: 'Auto-Planter',
powerCost: 10,
range: 3,
speed: 2000 // ms per action
},
'auto_harvester': {
name: 'Auto-Harvester',
powerCost: 15,
range: 5,
speed: 1500
},
'irrigation': {
name: 'Irrigation System',
powerCost: 5,
range: 10,
speed: 3000
},
'conveyor': {
name: 'Conveyor Belt',
powerCost: 3,
range: 1,
speed: 500
},
'silo': {
name: 'Storage Silo',
powerCost: 2,
capacity: 1000
},
'sorter': {
name: 'Sorting Machine',
powerCost: 8,
speed: 1000
}
};
const buildingData = buildings[type];
if (!buildingData) return null;
const building = {
id: `${type}_${x}_${y}`,
type,
x, y,
...buildingData,
active: false,
lastAction: 0
};
this.automationBuildings.set(building.id, building);
this.updatePowerConsumption();
this.saveProgress();
console.log(`🏭 Built ${buildingData.name} at (${x}, ${y})`);
return building;
}
activateBuilding(buildingId) {
const building = this.automationBuildings.get(buildingId);
if (!building) return false;
// Check power
if (this.totalPower < this.powerConsumption + building.powerCost) {
console.log('❌ Not enough power!');
return false;
}
building.active = true;
this.updatePowerConsumption();
console.log(`⚡ Activated ${building.name}`);
return true;
}
deactivateBuilding(buildingId) {
const building = this.automationBuildings.get(buildingId);
if (!building) return false;
building.active = false;
this.updatePowerConsumption();
console.log(`🔌 Deactivated ${building.name}`);
return true;
}
// ========== POWER SYSTEM ==========
buildPowerSource(type, x, y) {
const sources = {
'windmill': { name: 'Windmill', power: 20, cost: { wood: 10, iron: 5 } },
'water_wheel': { name: 'Water Wheel', power: 15, cost: { wood: 8, iron: 3 } },
'solar_panel': { name: 'Solar Panel', power: 25, cost: { iron: 10, glass: 5 } },
'zombie_treadmill': { name: 'Zombie Treadmill', power: 10, cost: { wood: 5 } }
};
const sourceData = sources[type];
if (!sourceData) return null;
const source = {
id: `${type}_${x}_${y}`,
type,
x, y,
...sourceData,
active: true,
currentPower: sourceData.power
};
this.powerGrid.set(source.id, source);
this.updateTotalPower();
this.saveProgress();
console.log(`⚡ Built ${sourceData.name} (+${sourceData.power} power)`);
return source;
}
updateTotalPower() {
this.totalPower = 0;
for (const source of this.powerGrid.values()) {
if (source.active) {
// Solar panels only work during day
if (source.type === 'solar_panel') {
const time = this.scene.weatherSystem?.gameTime || 12;
if (time >= 6 && time <= 18) {
this.totalPower += source.currentPower;
}
} else {
this.totalPower += source.currentPower;
}
}
}
}
updatePowerConsumption() {
this.powerConsumption = 0;
for (const building of this.automationBuildings.values()) {
if (building.active) {
this.powerConsumption += building.powerCost;
}
}
}
startPowerUpdate() {
setInterval(() => {
this.updateTotalPower();
this.updatePowerConsumption();
// Deactivate buildings if not enough power
if (this.powerConsumption > this.totalPower) {
this.handlePowerShortage();
}
}, this.settings.powerUpdateInterval);
}
handlePowerShortage() {
console.log('⚠️ Power shortage! Deactivating low-priority buildings...');
// Deactivate buildings until power is sufficient
for (const building of this.automationBuildings.values()) {
if (building.active && this.powerConsumption > this.totalPower) {
this.deactivateBuilding(building.id);
}
}
}
getPowerStatus() {
return {
total: this.totalPower,
consumption: this.powerConsumption,
available: this.totalPower - this.powerConsumption,
percentage: (this.powerConsumption / this.totalPower) * 100
};
}
// ========== WORKER MANAGEMENT ==========
updateWorkers(delta) {
// Update zombie workers
for (const worker of this.zombieWorkers) {
this.updateWorker(worker, delta);
}
// Update creature workers
for (const worker of this.creatureWorkers) {
this.updateWorker(worker, delta);
}
}
updateWorker(worker, delta) {
// Decrease hunger over time
worker.hunger -= delta / 60000; // 1% per minute
// Increase fatigue if working
if (worker.currentTask) {
worker.fatigue += delta / 30000; // 1% per 30 seconds
// Complete task if enough time passed
const taskDuration = 5000 / worker.efficiency; // Base 5 seconds
if (Date.now() - worker.currentTask.startTime > taskDuration) {
this.completeTask(worker);
}
} else {
// Recover fatigue when idle
worker.fatigue -= delta / 60000;
}
// Clamp values
worker.hunger = Math.max(0, Math.min(100, worker.hunger));
worker.fatigue = Math.max(0, Math.min(100, worker.fatigue));
// Worker needs rest
if (worker.fatigue > 80) {
worker.currentTask = null;
console.log(`😴 ${worker.name} is too tired to work`);
}
// Worker needs food
if (worker.hunger < 20) {
worker.efficiency *= 0.5; // 50% slower when hungry
}
}
feedWorker(worker, food) {
if (!worker) return false;
worker.hunger = Math.min(100, worker.hunger + 30);
console.log(`🍖 Fed ${worker.name}`);
return true;
}
restWorker(worker) {
if (!worker) return false;
worker.currentTask = null;
worker.fatigue = Math.max(0, worker.fatigue - 50);
console.log(`😴 ${worker.name} is resting`);
return true;
}
upgradeWorkerTools(worker, toolTier) {
if (!worker) return false;
const tierBonus = {
'bronze': 0.1,
'iron': 0.2,
'steel': 0.3,
'enchanted': 0.5
};
const bonus = tierBonus[toolTier] || 0;
worker.efficiency += bonus;
console.log(`⚒️ ${worker.name} upgraded to ${toolTier} tools (+${bonus * 100}% efficiency)`);
return true;
}
// ========== AUTOMATION UPDATE ==========
updateAutomation(delta) {
const now = Date.now();
for (const building of this.automationBuildings.values()) {
if (!building.active) continue;
// Check if enough time passed
if (now - building.lastAction < building.speed) continue;
// Perform building action
switch (building.type) {
case 'auto_planter':
this.autoPlant(building);
break;
case 'auto_harvester':
this.autoHarvest(building);
break;
case 'irrigation':
this.autoWater(building);
break;
case 'conveyor':
this.moveItems(building);
break;
case 'sorter':
this.sortItems(building);
break;
}
building.lastAction = now;
}
}
autoPlant(building) {
// Plant crops in range
console.log(`🌱 Auto-planter working at (${building.x}, ${building.y})`);
}
autoHarvest(building) {
// Harvest crops in range
console.log(`🌾 Auto-harvester working at (${building.x}, ${building.y})`);
}
autoWater(building) {
// Water crops in range
console.log(`💧 Irrigation system working at (${building.x}, ${building.y})`);
}
moveItems(building) {
// Move items along conveyor
console.log(`📦 Conveyor moving items at (${building.x}, ${building.y})`);
}
sortItems(building) {
// Sort items in storage
console.log(`🔀 Sorter organizing items at (${building.x}, ${building.y})`);
}
// ========== UPDATE ==========
update(delta) {
this.updateWorkers(delta);
this.updateAutomation(delta);
}
// ========== PERSISTENCE ==========
saveProgress() {
const data = {
zombieWorkers: this.zombieWorkers.map(w => ({
id: w.id,
name: w.name,
level: w.level,
xp: w.xp,
efficiency: w.efficiency
})),
creatureWorkers: this.creatureWorkers.map(w => ({
id: w.id,
name: w.name,
type: w.type,
level: w.level,
xp: w.xp
})),
buildings: Array.from(this.automationBuildings.values()).map(b => ({
id: b.id,
type: b.type,
x: b.x,
y: b.y,
active: b.active
})),
powerSources: Array.from(this.powerGrid.values()).map(p => ({
id: p.id,
type: p.type,
x: p.x,
y: p.y
}))
};
localStorage.setItem('novafarma_farm_automation', JSON.stringify(data));
}
loadProgress() {
const saved = localStorage.getItem('novafarma_farm_automation');
if (saved) {
try {
const data = JSON.parse(saved);
// Restore workers (basic data only, full restoration in init)
this.savedData = data;
console.log('✅ Farm automation progress loaded');
} catch (error) {
console.error('Failed to load farm automation:', error);
}
}
}
destroy() {
this.saveProgress();
console.log('🤖 Farm Automation System destroyed');
}
}

View File

@@ -0,0 +1,471 @@
/**
* FISHING SYSTEM
* Complete fishing system with minigame, fish types, bait, and aquarium
*/
class FishingSystem {
constructor(scene) {
this.scene = scene;
this.enabled = true;
// Fishing state
this.isFishing = false;
this.currentCast = null;
this.fishingRod = null;
// Fish types
this.fishTypes = new Map();
// Caught fish
this.caughtFish = [];
this.fishCollection = new Set();
// Bait
this.currentBait = null;
// Aquarium
this.aquarium = [];
this.aquariumCapacity = 10;
// Minigame
this.minigame = null;
// Settings
this.settings = {
castDistance: 5, // tiles
biteChance: 0.3, // 30% per second
minigameTime: 3000, // 3 seconds
greenZoneSize: 0.2 // 20% of bar
};
this.loadProgress();
this.init();
console.log('✅ Fishing System initialized');
}
init() {
this.defineFishTypes();
this.defineRods();
console.log('🎣 Fishing system ready');
}
// ========== FISH TYPES ==========
defineFishTypes() {
// Common fish (70%)
this.defineFish('bass', {
name: 'Bass',
rarity: 'common',
weight: { min: 1, max: 3 },
value: 10,
chance: 0.35
});
this.defineFish('trout', {
name: 'Trout',
rarity: 'common',
weight: { min: 0.5, max: 2 },
value: 8,
chance: 0.35
});
// Rare fish (25%)
this.defineFish('salmon', {
name: 'Salmon',
rarity: 'rare',
weight: { min: 3, max: 8 },
value: 50,
chance: 0.15
});
this.defineFish('tuna', {
name: 'Tuna',
rarity: 'rare',
weight: { min: 10, max: 20 },
value: 75,
chance: 0.10
});
// Legendary fish (5%)
this.defineFish('golden_fish', {
name: 'Golden Fish',
rarity: 'legendary',
weight: { min: 5, max: 10 },
value: 500,
chance: 0.03
});
this.defineFish('sea_dragon', {
name: 'Sea Dragon',
rarity: 'legendary',
weight: { min: 50, max: 100 },
value: 1000,
chance: 0.02
});
}
defineFish(id, data) {
this.fishTypes.set(id, {
id,
...data
});
}
// ========== FISHING RODS ==========
defineRods() {
this.fishingRods = {
basic: {
name: 'Basic Rod',
cost: { wood: 5, string: 2 },
catchBonus: 0,
durability: 50
},
iron: {
name: 'Iron Rod',
cost: { iron: 3, wood: 2, string: 2 },
catchBonus: 0.1,
durability: 100
},
enchanted: {
name: 'Enchanted Rod',
cost: { magic_crystal: 1, iron: 5, string: 3 },
catchBonus: 0.3,
durability: 200
}
};
}
// ========== FISHING ==========
canFish() {
// Check if player has fishing rod
if (!this.fishingRod) {
console.log('❌ No fishing rod equipped');
return false;
}
// Check if near water
if (!this.isNearWater()) {
console.log('❌ Not near water');
return false;
}
return true;
}
isNearWater() {
// Check if player is near water tile
if (!this.scene.player) return false;
const playerPos = this.scene.player.getPosition();
const tileX = Math.floor(playerPos.x);
const tileY = Math.floor(playerPos.y);
// Check surrounding tiles
for (let dx = -2; dx <= 2; dx++) {
for (let dy = -2; dy <= 2; dy++) {
const tile = this.scene.terrainSystem.getTile(tileX + dx, tileY + dy);
if (tile && tile.type === 'water') {
return true;
}
}
}
return false;
}
startFishing() {
if (!this.canFish()) return false;
this.isFishing = true;
// Cast line
this.currentCast = {
startTime: Date.now(),
biteTime: this.calculateBiteTime(),
hasBite: false
};
console.log('🎣 Cast fishing line...');
return true;
}
calculateBiteTime() {
// Random time between 2-5 seconds
const baseTime = 2000 + Math.random() * 3000;
// Bait reduces wait time
if (this.currentBait) {
return baseTime * 0.7;
}
return baseTime;
}
updateFishing(delta) {
if (!this.isFishing || !this.currentCast) return;
const now = Date.now();
const elapsed = now - this.currentCast.startTime;
// Check for bite
if (!this.currentCast.hasBite && elapsed >= this.currentCast.biteTime) {
this.triggerBite();
}
}
triggerBite() {
this.currentCast.hasBite = true;
// Visual indicator
console.log('🐟 BITE! Press SPACE to reel!');
// Show minigame
this.startMinigame();
}
// ========== MINIGAME ==========
startMinigame() {
this.minigame = {
startTime: Date.now(),
duration: this.settings.minigameTime,
barPosition: 0.5, // 0-1
targetPosition: Math.random(), // 0-1
greenZoneStart: 0,
greenZoneEnd: 0,
success: false
};
// Calculate green zone
this.minigame.greenZoneStart = this.minigame.targetPosition - this.settings.greenZoneSize / 2;
this.minigame.greenZoneEnd = this.minigame.targetPosition + this.settings.greenZoneSize / 2;
console.log('🎮 Minigame started! Keep bar in green zone!');
}
updateMinigame(delta) {
if (!this.minigame) return;
const now = Date.now();
const elapsed = now - this.minigame.startTime;
// Check if time's up
if (elapsed >= this.minigame.duration) {
this.endMinigame();
return;
}
// Move target (makes it harder)
this.minigame.targetPosition += (Math.random() - 0.5) * 0.01;
this.minigame.targetPosition = Math.max(0, Math.min(1, this.minigame.targetPosition));
// Update green zone
this.minigame.greenZoneStart = this.minigame.targetPosition - this.settings.greenZoneSize / 2;
this.minigame.greenZoneEnd = this.minigame.targetPosition + this.settings.greenZoneSize / 2;
// Check if bar is in green zone
if (this.minigame.barPosition >= this.minigame.greenZoneStart &&
this.minigame.barPosition <= this.minigame.greenZoneEnd) {
this.minigame.success = true;
}
}
moveBar(direction) {
if (!this.minigame) return;
// Move bar left or right
this.minigame.barPosition += direction * 0.05;
this.minigame.barPosition = Math.max(0, Math.min(1, this.minigame.barPosition));
}
endMinigame() {
if (!this.minigame) return;
if (this.minigame.success) {
// Success! Catch fish
this.catchFish();
} else {
// Failed
console.log('❌ Fish got away!');
}
this.minigame = null;
this.isFishing = false;
this.currentCast = null;
}
// ========== CATCHING ==========
catchFish() {
// Determine which fish was caught
const fish = this.rollFish();
if (!fish) {
console.log('❌ Nothing caught');
return;
}
// Generate weight
const weight = fish.weight.min + Math.random() * (fish.weight.max - fish.weight.min);
// Create caught fish
const caughtFish = {
id: fish.id,
name: fish.name,
rarity: fish.rarity,
weight: Math.round(weight * 10) / 10,
value: fish.value,
caughtTime: Date.now()
};
this.caughtFish.push(caughtFish);
this.fishCollection.add(fish.id);
// Add to inventory
if (this.scene.inventorySystem) {
this.scene.inventorySystem.addItem(`fish_${fish.id}`, 1);
}
// Visual effect
if (this.scene.visualEnhancements) {
const player = this.scene.player;
if (player) {
const pos = player.getPosition();
const color = fish.rarity === 'legendary' ? 0xFFD700 :
fish.rarity === 'rare' ? 0x9370DB : 0x4169E1;
this.scene.visualEnhancements.createSparkleEffect(pos.x, pos.y);
this.scene.visualEnhancements.screenFlash(color, 300);
}
}
// Achievement
if (this.scene.uiGraphics) {
if (fish.rarity === 'legendary') {
this.scene.uiGraphics.unlockAchievement('legendary_fisher');
}
if (this.fishCollection.size >= 6) {
this.scene.uiGraphics.unlockAchievement('fish_collector');
}
}
console.log(`🎣 Caught ${fish.name}! (${caughtFish.weight}kg)`);
this.saveProgress();
}
rollFish() {
// Roll for fish type based on chances
const roll = Math.random();
let cumulative = 0;
// Apply rod bonus
const bonus = this.fishingRod ? this.fishingRods[this.fishingRod].catchBonus : 0;
for (const fish of this.fishTypes.values()) {
cumulative += fish.chance * (1 + bonus);
if (roll <= cumulative) {
return fish;
}
}
return null;
}
// ========== BAIT ==========
useBait(baitType) {
this.currentBait = baitType;
console.log(`🪱 Using ${baitType} bait`);
}
// ========== AQUARIUM ==========
addToAquarium(fishId) {
if (this.aquarium.length >= this.aquariumCapacity) {
console.log('❌ Aquarium is full');
return false;
}
const fish = this.caughtFish.find(f => f.id === fishId);
if (!fish) {
console.log('❌ Fish not found');
return false;
}
this.aquarium.push(fish);
console.log(`🐠 Added ${fish.name} to aquarium`);
this.saveProgress();
return true;
}
// ========== KEYBOARD CONTROLS ==========
setupKeyboard() {
// Press 'R' to start fishing
this.scene.input.keyboard.on('keydown-R', () => {
if (!this.isFishing) {
this.startFishing();
}
});
// Press 'SPACE' during minigame
this.scene.input.keyboard.on('keydown-SPACE', () => {
if (this.minigame) {
this.moveBar(0.1);
}
});
// Arrow keys for minigame
this.scene.input.keyboard.on('keydown-LEFT', () => {
if (this.minigame) {
this.moveBar(-0.1);
}
});
this.scene.input.keyboard.on('keydown-RIGHT', () => {
if (this.minigame) {
this.moveBar(0.1);
}
});
}
// ========== UPDATE ==========
update(delta) {
this.updateFishing(delta);
this.updateMinigame(delta);
}
// ========== PERSISTENCE ==========
saveProgress() {
const data = {
caughtFish: this.caughtFish,
fishCollection: Array.from(this.fishCollection),
aquarium: this.aquarium
};
localStorage.setItem('novafarma_fishing', JSON.stringify(data));
}
loadProgress() {
const saved = localStorage.getItem('novafarma_fishing');
if (saved) {
try {
const data = JSON.parse(saved);
this.caughtFish = data.caughtFish || [];
this.fishCollection = new Set(data.fishCollection || []);
this.aquarium = data.aquarium || [];
console.log('✅ Fishing progress loaded');
} catch (error) {
console.error('Failed to load fishing progress:', error);
}
}
}
destroy() {
this.saveProgress();
console.log('🎣 Fishing System destroyed');
}
}

View File

@@ -0,0 +1,456 @@
/**
* FOG OF WAR SYSTEM
* Exploration and visibility system for unexplored areas
*/
class FogOfWarSystem {
constructor(scene) {
this.scene = scene;
this.enabled = true;
// Fog grid (matches terrain grid)
this.gridWidth = 100;
this.gridHeight = 100;
this.tileSize = 64;
// Fog states: 0 = unexplored, 1 = explored, 2 = visible
this.fogGrid = [];
this.fogSprites = new Map();
// Settings
this.settings = {
enabled: true,
fogColor: 0x000000,
fogAlpha: 0.8,
exploredAlpha: 0.3,
visibleRadius: 5, // tiles
smoothEdges: true,
persistMemory: true,
refogDungeons: true
};
// Fog layer
this.fogLayer = null;
this.fogGraphics = null;
// Memory of explored areas
this.exploredAreas = new Set();
this.loadSettings();
this.init();
console.log('✅ Fog of War System initialized');
}
init() {
if (!this.settings.enabled) return;
// Initialize fog grid
this.initFogGrid();
// Create fog layer
this.createFogLayer();
// Load explored areas from memory
this.loadExploredAreas();
console.log('🌫️ Fog of War active');
}
/**
* Initialize fog grid
*/
initFogGrid() {
for (let y = 0; y < this.gridHeight; y++) {
this.fogGrid[y] = [];
for (let x = 0; x < this.gridWidth; x++) {
this.fogGrid[y][x] = 0; // Unexplored
}
}
}
/**
* Create fog layer
*/
createFogLayer() {
// Create layer for fog
this.fogLayer = this.scene.add.layer();
this.fogLayer.setDepth(9000); // Above game, below UI
// Create fog graphics
this.fogGraphics = this.scene.add.graphics();
this.fogGraphics.setDepth(9001);
// Initial full fog
this.renderFullFog();
}
/**
* Render full fog (all unexplored)
*/
renderFullFog() {
if (!this.fogGraphics) return;
this.fogGraphics.clear();
this.fogGraphics.fillStyle(this.settings.fogColor, this.settings.fogAlpha);
// Cover entire map
const width = this.scene.cameras.main.width;
const height = this.scene.cameras.main.height;
this.fogGraphics.fillRect(
-width,
-height,
width * 3,
height * 3
);
}
/**
* Update fog based on player position
*/
updateFog(playerX, playerY) {
if (!this.settings.enabled) return;
const gridX = Math.floor(playerX);
const gridY = Math.floor(playerY);
// Reveal area around player
this.revealArea(gridX, gridY, this.settings.visibleRadius);
// Update fog rendering
this.renderFog();
}
/**
* Reveal area around a point
*/
revealArea(centerX, centerY, radius) {
const radiusSq = radius * radius;
for (let y = centerY - radius; y <= centerY + radius; y++) {
for (let x = centerX - radius; x <= centerX + radius; x++) {
// Check if within grid bounds
if (x < 0 || x >= this.gridWidth || y < 0 || y >= this.gridHeight) {
continue;
}
// Check if within circular radius
const dx = x - centerX;
const dy = y - centerY;
const distSq = dx * dx + dy * dy;
if (distSq <= radiusSq) {
// Mark as explored
if (this.fogGrid[y][x] === 0) {
this.fogGrid[y][x] = 1; // Explored
this.exploredAreas.add(`${x},${y}`);
}
// Mark as currently visible
this.fogGrid[y][x] = 2; // Visible
}
}
}
// Save explored areas
if (this.settings.persistMemory) {
this.saveExploredAreas();
}
}
/**
* Render fog based on current state
*/
renderFog() {
if (!this.fogGraphics) return;
this.fogGraphics.clear();
// Get camera bounds
const cam = this.scene.cameras.main;
const offsetX = this.scene.terrainOffsetX || 0;
const offsetY = this.scene.terrainOffsetY || 0;
// Render fog tiles
for (let y = 0; y < this.gridHeight; y++) {
for (let x = 0; x < this.gridWidth; x++) {
const state = this.fogGrid[y][x];
// Convert grid to screen coordinates
const iso = this.scene.iso || { toScreen: (x, y) => ({ x: x * 32, y: y * 32 }) };
const screenPos = iso.toScreen(x, y);
const screenX = screenPos.x + offsetX;
const screenY = screenPos.y + offsetY;
// Only render if on screen
if (screenX < cam.scrollX - 100 || screenX > cam.scrollX + cam.width + 100) continue;
if (screenY < cam.scrollY - 100 || screenY > cam.scrollY + cam.height + 100) continue;
if (state === 0) {
// Unexplored - full fog
this.fogGraphics.fillStyle(this.settings.fogColor, this.settings.fogAlpha);
this.fogGraphics.fillRect(screenX - 32, screenY - 16, 64, 32);
} else if (state === 1) {
// Explored but not visible - light fog
this.fogGraphics.fillStyle(this.settings.fogColor, this.settings.exploredAlpha);
this.fogGraphics.fillRect(screenX - 32, screenY - 16, 64, 32);
}
// state === 2 (visible) - no fog
}
}
// Smooth edges if enabled
if (this.settings.smoothEdges) {
this.fogGraphics.setBlendMode(Phaser.BlendModes.NORMAL);
}
}
/**
* Reset fog in area (for dungeons/caves)
*/
refogArea(x, y, width, height) {
if (!this.settings.refogDungeons) return;
for (let gy = y; gy < y + height; gy++) {
for (let gx = x; gx < x + width; gx++) {
if (gx >= 0 && gx < this.gridWidth && gy >= 0 && gy < this.gridHeight) {
this.fogGrid[gy][gx] = 0; // Back to unexplored
this.exploredAreas.delete(`${gx},${gy}`);
}
}
}
this.renderFog();
}
/**
* Clear all fog (reveal entire map)
*/
revealAll() {
for (let y = 0; y < this.gridHeight; y++) {
for (let x = 0; x < this.gridWidth; x++) {
this.fogGrid[y][x] = 2; // All visible
this.exploredAreas.add(`${x},${y}`);
}
}
this.renderFog();
}
/**
* Reset all fog (hide entire map)
*/
resetAll() {
for (let y = 0; y < this.gridHeight; y++) {
for (let x = 0; x < this.gridWidth; x++) {
this.fogGrid[y][x] = 0; // All unexplored
}
}
this.exploredAreas.clear();
this.renderFullFog();
}
/**
* Check if area is explored
*/
isExplored(x, y) {
if (x < 0 || x >= this.gridWidth || y < 0 || y >= this.gridHeight) {
return false;
}
return this.fogGrid[y][x] > 0;
}
/**
* Check if area is visible
*/
isVisible(x, y) {
if (x < 0 || x >= this.gridWidth || y < 0 || y >= this.gridHeight) {
return false;
}
return this.fogGrid[y][x] === 2;
}
/**
* Get exploration percentage
*/
getExplorationPercentage() {
let explored = 0;
const total = this.gridWidth * this.gridHeight;
for (let y = 0; y < this.gridHeight; y++) {
for (let x = 0; x < this.gridWidth; x++) {
if (this.fogGrid[y][x] > 0) {
explored++;
}
}
}
return (explored / total) * 100;
}
/**
* Enable fog of war
*/
enable() {
this.settings.enabled = true;
if (!this.fogLayer) {
this.createFogLayer();
}
this.fogLayer.setVisible(true);
this.saveSettings();
}
/**
* Disable fog of war
*/
disable() {
this.settings.enabled = false;
if (this.fogLayer) {
this.fogLayer.setVisible(false);
}
this.saveSettings();
}
/**
* Set visible radius
*/
setVisibleRadius(radius) {
this.settings.visibleRadius = Math.max(1, Math.min(20, radius));
this.saveSettings();
}
/**
* Set fog color
*/
setFogColor(color) {
this.settings.fogColor = color;
this.renderFog();
this.saveSettings();
}
/**
* Set fog alpha
*/
setFogAlpha(alpha) {
this.settings.fogAlpha = Phaser.Math.Clamp(alpha, 0, 1);
this.renderFog();
this.saveSettings();
}
/**
* Set explored alpha
*/
setExploredAlpha(alpha) {
this.settings.exploredAlpha = Phaser.Math.Clamp(alpha, 0, 1);
this.renderFog();
this.saveSettings();
}
/**
* Update (called every frame)
*/
update() {
if (!this.settings.enabled) return;
// Update fog based on player position
if (this.scene.player) {
const pos = this.scene.player.getPosition();
this.updateFog(pos.x, pos.y);
}
// Fade out visible areas that are no longer in range
this.fadeDistantAreas();
}
/**
* Fade distant areas back to explored state
*/
fadeDistantAreas() {
if (!this.scene.player) return;
const pos = this.scene.player.getPosition();
const playerX = Math.floor(pos.x);
const playerY = Math.floor(pos.y);
const radius = this.settings.visibleRadius;
const radiusSq = radius * radius;
for (let y = 0; y < this.gridHeight; y++) {
for (let x = 0; x < this.gridWidth; x++) {
if (this.fogGrid[y][x] === 2) {
// Check if still in visible range
const dx = x - playerX;
const dy = y - playerY;
const distSq = dx * dx + dy * dy;
if (distSq > radiusSq) {
// Fade back to explored
this.fogGrid[y][x] = 1;
}
}
}
}
}
/**
* Save explored areas to localStorage
*/
saveExploredAreas() {
if (!this.settings.persistMemory) return;
const data = Array.from(this.exploredAreas);
localStorage.setItem('novafarma_explored_areas', JSON.stringify(data));
}
/**
* Load explored areas from localStorage
*/
loadExploredAreas() {
if (!this.settings.persistMemory) return;
const saved = localStorage.getItem('novafarma_explored_areas');
if (saved) {
try {
const data = JSON.parse(saved);
this.exploredAreas = new Set(data);
// Apply to fog grid
for (const key of this.exploredAreas) {
const [x, y] = key.split(',').map(Number);
if (x >= 0 && x < this.gridWidth && y >= 0 && y < this.gridHeight) {
this.fogGrid[y][x] = 1; // Explored
}
}
console.log(`🗺️ Loaded ${this.exploredAreas.size} explored tiles`);
} catch (error) {
console.error('Failed to load explored areas:', error);
}
}
}
/**
* Save settings
*/
saveSettings() {
localStorage.setItem('novafarma_fog_of_war', JSON.stringify(this.settings));
}
/**
* Load settings
*/
loadSettings() {
const saved = localStorage.getItem('novafarma_fog_of_war');
if (saved) {
this.settings = { ...this.settings, ...JSON.parse(saved) };
}
}
/**
* Destroy system
*/
destroy() {
if (this.fogLayer) this.fogLayer.destroy();
if (this.fogGraphics) this.fogGraphics.destroy();
this.saveExploredAreas();
console.log('🌫️ Fog of War System destroyed');
}
}

View File

@@ -0,0 +1,407 @@
/**
* MINING & DUNGEONS SYSTEM
* Underground cave generation, mining, and dungeon exploration
*/
class MiningDungeonsSystem {
constructor(scene) {
this.scene = scene;
this.enabled = true;
// Caves & dungeons
this.caves = new Map();
this.currentCave = null;
// Mining
this.oreVeins = new Map();
this.minedOres = [];
// Elevators
this.elevators = new Map();
// Enemies
this.caveEnemies = [];
// Bosses
this.dungeonBosses = new Map();
// Settings
this.settings = {
maxDepth: 50,
roomSize: { min: 5, max: 15 },
tunnelWidth: 2,
oreChance: 0.1
};
this.loadProgress();
this.init();
console.log('✅ Mining & Dungeons System initialized');
}
init() {
this.defineOreTypes();
this.defineEnemyTypes();
console.log('⛏️ Mining & Dungeons ready');
}
// ========== ORE TYPES ==========
defineOreTypes() {
this.oreTypes = {
// Depth 0-10
copper: { depth: [0, 10], value: 5, rarity: 0.4 },
tin: { depth: [0, 10], value: 5, rarity: 0.4 },
// Depth 10-20
iron: { depth: [10, 20], value: 15, rarity: 0.3 },
coal: { depth: [10, 20], value: 10, rarity: 0.35 },
// Depth 20-30
gold: { depth: [20, 30], value: 50, rarity: 0.15 },
silver: { depth: [20, 30], value: 30, rarity: 0.2 },
// Depth 30+
diamond: { depth: [30, 50], value: 200, rarity: 0.05 },
mythril: { depth: [30, 50], value: 500, rarity: 0.02 }
};
}
// ========== ENEMY TYPES ==========
defineEnemyTypes() {
this.enemyTypes = {
bat: {
name: 'Cave Bat',
hp: 20,
damage: 5,
speed: 1.5,
xp: 10,
loot: ['bat_wing', 'guano']
},
spider: {
name: 'Giant Spider',
hp: 50,
damage: 15,
speed: 1.0,
xp: 25,
loot: ['spider_silk', 'venom']
},
mole: {
name: 'Mutant Mole',
hp: 80,
damage: 20,
speed: 0.8,
xp: 40,
loot: ['mole_claw', 'earth_essence']
},
golem: {
name: 'Stone Golem',
hp: 200,
damage: 40,
speed: 0.5,
xp: 100,
loot: ['stone_core', 'ancient_rune']
}
};
}
// ========== CAVE GENERATION ==========
generateCave(depth, seed) {
const cave = {
id: `cave_${depth}_${seed}`,
depth,
seed,
rooms: [],
tunnels: [],
oreVeins: [],
enemies: [],
boss: null,
explored: false
};
// Generate rooms
const numRooms = 5 + Math.floor(depth / 10);
for (let i = 0; i < numRooms; i++) {
cave.rooms.push(this.generateRoom(depth));
}
// Connect rooms with tunnels
cave.tunnels = this.connectRooms(cave.rooms);
// Place ore veins
cave.oreVeins = this.placeOres(depth, cave.rooms);
// Spawn enemies
cave.enemies = this.spawnEnemies(depth, cave.rooms);
// Boss every 10 levels
if (depth % 10 === 0) {
cave.boss = this.createBoss(depth);
}
this.caves.set(cave.id, cave);
return cave;
}
generateRoom(depth) {
const size = this.settings.roomSize;
const width = size.min + Math.floor(Math.random() * (size.max - size.min));
const height = size.min + Math.floor(Math.random() * (size.max - size.min));
return {
x: Math.floor(Math.random() * 100),
y: Math.floor(Math.random() * 100),
width,
height,
type: this.getRoomType(depth)
};
}
getRoomType(depth) {
const types = ['cave', 'crystal_cavern', 'lava_chamber', 'ice_cave', 'mushroom_grove'];
const index = Math.floor(depth / 10) % types.length;
return types[index];
}
connectRooms(rooms) {
const tunnels = [];
for (let i = 0; i < rooms.length - 1; i++) {
const room1 = rooms[i];
const room2 = rooms[i + 1];
tunnels.push({
from: { x: room1.x + room1.width / 2, y: room1.y + room1.height / 2 },
to: { x: room2.x + room2.width / 2, y: room2.y + room2.height / 2 },
width: this.settings.tunnelWidth
});
}
return tunnels;
}
// ========== ORE PLACEMENT ==========
placeOres(depth, rooms) {
const oreVeins = [];
for (const room of rooms) {
const numVeins = 2 + Math.floor(Math.random() * 5);
for (let i = 0; i < numVeins; i++) {
const ore = this.selectOre(depth);
if (!ore) continue;
oreVeins.push({
type: ore,
x: room.x + Math.floor(Math.random() * room.width),
y: room.y + Math.floor(Math.random() * room.height),
amount: 5 + Math.floor(Math.random() * 10),
mined: false
});
}
}
return oreVeins;
}
selectOre(depth) {
const validOres = Object.entries(this.oreTypes)
.filter(([_, ore]) => depth >= ore.depth[0] && depth <= ore.depth[1]);
if (validOres.length === 0) return null;
// Weighted random selection
const totalRarity = validOres.reduce((sum, [_, ore]) => sum + ore.rarity, 0);
let roll = Math.random() * totalRarity;
for (const [oreName, ore] of validOres) {
roll -= ore.rarity;
if (roll <= 0) return oreName;
}
return validOres[0][0];
}
// ========== ENEMY SPAWNING ==========
spawnEnemies(depth, rooms) {
const enemies = [];
const enemiesPerRoom = 1 + Math.floor(depth / 5);
for (const room of rooms) {
for (let i = 0; i < enemiesPerRoom; i++) {
const enemyType = this.selectEnemy(depth);
const enemyData = this.enemyTypes[enemyType];
enemies.push({
type: enemyType,
name: enemyData.name,
hp: enemyData.hp * (1 + depth * 0.1),
maxHp: enemyData.hp * (1 + depth * 0.1),
damage: enemyData.damage * (1 + depth * 0.1),
speed: enemyData.speed,
x: room.x + Math.floor(Math.random() * room.width),
y: room.y + Math.floor(Math.random() * room.height),
xp: enemyData.xp,
loot: enemyData.loot
});
}
}
return enemies;
}
selectEnemy(depth) {
if (depth < 10) return 'bat';
if (depth < 20) return Math.random() < 0.5 ? 'bat' : 'spider';
if (depth < 30) return Math.random() < 0.3 ? 'spider' : 'mole';
return Math.random() < 0.5 ? 'mole' : 'golem';
}
// ========== BOSS CREATION ==========
createBoss(depth) {
const bossTypes = {
10: { name: 'Crystal Guardian', hp: 500, damage: 50 },
20: { name: 'Lava Titan', hp: 1000, damage: 80 },
30: { name: 'Ice Dragon', hp: 2000, damage: 120 },
40: { name: 'Shadow Demon', hp: 3500, damage: 150 },
50: { name: 'Ancient Wyrm', hp: 5000, damage: 200 }
};
const bossData = bossTypes[depth] || bossTypes[50];
return {
name: bossData.name,
hp: bossData.hp,
maxHp: bossData.hp,
damage: bossData.damage,
phase: 1,
maxPhases: 3,
defeated: false,
loot: this.generateBossLoot(depth)
};
}
generateBossLoot(depth) {
return [
{ item: 'legendary_sword', chance: 0.1 },
{ item: 'boss_trophy', chance: 1.0 },
{ item: 'rare_gem', chance: 0.5 },
{ item: 'gold', amount: depth * 100, chance: 1.0 }
];
}
// ========== MINING ==========
mineOre(oreVeinId) {
const vein = this.oreVeins.get(oreVeinId);
if (!vein || vein.mined) return null;
// Mine ore
vein.amount--;
if (vein.amount <= 0) {
vein.mined = true;
}
// Add to inventory
if (this.scene.inventorySystem) {
this.scene.inventorySystem.addItem(vein.type, 1);
}
// Track mined ores
this.minedOres.push({
type: vein.type,
time: Date.now()
});
console.log(`⛏️ Mined ${vein.type}!`);
return vein.type;
}
// ========== ELEVATOR ==========
buildElevator(x, y) {
const elevator = {
id: `elevator_${x}_${y}`,
x, y,
currentDepth: 0,
maxDepth: 0,
active: true
};
this.elevators.set(elevator.id, elevator);
console.log(`🛗 Built elevator at (${x}, ${y})`);
return elevator;
}
useElevator(elevatorId, targetDepth) {
const elevator = this.elevators.get(elevatorId);
if (!elevator) return false;
if (targetDepth > elevator.maxDepth) {
console.log('❌ Depth not unlocked yet');
return false;
}
// Generate cave if not exists
let cave = Array.from(this.caves.values()).find(c => c.depth === targetDepth);
if (!cave) {
cave = this.generateCave(targetDepth, Date.now());
}
this.currentCave = cave;
elevator.currentDepth = targetDepth;
console.log(`🛗 Descended to depth ${targetDepth}`);
return true;
}
// ========== MINE CART ==========
placeMinecart(x, y) {
console.log(`🛤️ Placed minecart at (${x}, ${y})`);
// Minecart for fast transport through tunnels
}
// ========== UPDATE ==========
update(delta) {
// Update cave enemies, etc.
}
// ========== PERSISTENCE ==========
saveProgress() {
const data = {
caves: Array.from(this.caves.values()).map(c => ({
id: c.id,
depth: c.depth,
explored: c.explored
})),
minedOres: this.minedOres.length
};
localStorage.setItem('novafarma_mining', JSON.stringify(data));
}
loadProgress() {
const saved = localStorage.getItem('novafarma_mining');
if (saved) {
try {
const data = JSON.parse(saved);
console.log('✅ Mining progress loaded');
} catch (error) {
console.error('Failed to load mining progress:', error);
}
}
}
destroy() {
this.saveProgress();
console.log('⛏️ Mining & Dungeons System destroyed');
}
}

View File

@@ -0,0 +1,467 @@
/**
* MULTIPLAYER & SOCIAL SYSTEM
* Co-op mode, trading, leaderboards, and social features
*/
class MultiplayerSocialSystem {
constructor(scene) {
this.scene = scene;
this.enabled = true;
// Multiplayer
this.isHost = false;
this.isConnected = false;
this.players = new Map();
this.maxPlayers = 4;
// Trading
this.tradeOffers = new Map();
this.activeTrade = null;
// Leaderboards
this.leaderboards = new Map();
// Social
this.friends = new Set();
this.gifts = [];
// Events
this.activeEvent = null;
this.loadProgress();
this.init();
console.log('✅ Multiplayer & Social System initialized');
}
init() {
this.defineLeaderboards();
this.defineEvents();
console.log('🌐 Multiplayer & Social ready');
}
// ========== CO-OP MODE ==========
hostGame() {
this.isHost = true;
this.isConnected = true;
// Add host player
this.players.set('host', {
id: 'host',
name: 'Player 1',
x: 50,
y: 50,
isHost: true
});
console.log('🎮 Hosting game...');
return true;
}
joinGame(hostId) {
this.isHost = false;
this.isConnected = true;
console.log(`🎮 Joining game ${hostId}...`);
return true;
}
addPlayer(playerId, playerData) {
if (this.players.size >= this.maxPlayers) {
console.log('❌ Game is full');
return false;
}
this.players.set(playerId, {
id: playerId,
name: playerData.name || `Player ${this.players.size + 1}`,
x: playerData.x || 50,
y: playerData.y || 50,
isHost: false
});
console.log(`✅ Player joined: ${playerData.name}`);
return true;
}
removePlayer(playerId) {
this.players.delete(playerId);
console.log(`👋 Player left: ${playerId}`);
}
syncWorldState() {
// Sync game state between players
const worldState = {
time: this.scene.weatherSystem?.currentTime || 0,
weather: this.scene.weatherSystem?.currentWeather || 'clear',
players: Array.from(this.players.values())
};
return worldState;
}
updatePlayerPosition(playerId, x, y) {
const player = this.players.get(playerId);
if (player) {
player.x = x;
player.y = y;
}
}
// ========== CO-OP QUESTS ==========
startCoopQuest(questId) {
console.log(`🤝 Co-op quest started: ${questId}`);
const coopQuests = {
'farm_together': {
name: 'Farm Together',
objective: 'Harvest 100 crops as a team',
reward: { xp: 500, gold: 1000 }
},
'boss_raid': {
name: 'Boss Raid',
objective: 'Defeat boss together',
reward: { xp: 2000, legendary_item: 1 }
}
};
return coopQuests[questId];
}
// ========== TRADING ==========
createTradeOffer(targetPlayerId, offeredItems, requestedItems) {
const tradeId = `trade_${Date.now()}`;
this.tradeOffers.set(tradeId, {
id: tradeId,
from: 'local_player',
to: targetPlayerId,
offered: offeredItems,
requested: requestedItems,
status: 'pending',
createdAt: Date.now()
});
console.log(`💱 Trade offer created: ${tradeId}`);
return tradeId;
}
acceptTrade(tradeId) {
const trade = this.tradeOffers.get(tradeId);
if (!trade || trade.status !== 'pending') return false;
// Execute trade
this.executeTrade(trade);
trade.status = 'completed';
console.log(`✅ Trade completed: ${tradeId}`);
return true;
}
rejectTrade(tradeId) {
const trade = this.tradeOffers.get(tradeId);
if (!trade) return false;
trade.status = 'rejected';
console.log(`❌ Trade rejected: ${tradeId}`);
return true;
}
executeTrade(trade) {
// Transfer items between players
console.log(`💱 Executing trade...`);
// Remove offered items from local player
if (this.scene.inventorySystem) {
for (const [item, amount] of Object.entries(trade.offered)) {
this.scene.inventorySystem.removeItem(item, amount);
}
// Add requested items to local player
for (const [item, amount] of Object.entries(trade.requested)) {
this.scene.inventorySystem.addItem(item, amount);
}
}
}
// ========== GLOBAL MARKETPLACE ==========
listItemOnMarket(item, amount, price) {
console.log(`🏪 Listed ${amount}x ${item} for ${price} gold`);
const listing = {
id: `listing_${Date.now()}`,
seller: 'local_player',
item,
amount,
price,
listedAt: Date.now()
};
return listing;
}
buyFromMarket(listingId) {
console.log(`💰 Purchased item from market: ${listingId}`);
}
// ========== AUCTION HOUSE ==========
createAuction(item, startingBid, duration) {
console.log(`🔨 Auction created: ${item} starting at ${startingBid} gold`);
const auction = {
id: `auction_${Date.now()}`,
seller: 'local_player',
item,
currentBid: startingBid,
highestBidder: null,
endsAt: Date.now() + duration,
bids: []
};
return auction;
}
placeBid(auctionId, bidAmount) {
console.log(`💰 Bid placed: ${bidAmount} gold on ${auctionId}`);
}
// ========== PRICE FLUCTUATION ==========
updateMarketPrices() {
// Simulate market price changes
const priceChanges = {
wheat: 1.0 + (Math.random() - 0.5) * 0.2,
iron: 1.0 + (Math.random() - 0.5) * 0.3,
gold: 1.0 + (Math.random() - 0.5) * 0.1
};
return priceChanges;
}
// ========== LEADERBOARDS ==========
defineLeaderboards() {
this.leaderboards.set('productivity', {
name: 'Farm Productivity',
entries: []
});
this.leaderboards.set('speedrun', {
name: 'Fastest Speedruns',
entries: []
});
this.leaderboards.set('survival', {
name: 'Highest Survival Days',
entries: []
});
this.leaderboards.set('wealth', {
name: 'Richest Players',
entries: []
});
this.leaderboards.set('boss_kills', {
name: 'Boss Kill Times',
entries: []
});
}
submitScore(leaderboardId, score) {
const leaderboard = this.leaderboards.get(leaderboardId);
if (!leaderboard) return false;
leaderboard.entries.push({
player: 'local_player',
score,
timestamp: Date.now()
});
// Sort by score (descending)
leaderboard.entries.sort((a, b) => b.score - a.score);
// Keep top 100
leaderboard.entries = leaderboard.entries.slice(0, 100);
console.log(`🏆 Score submitted to ${leaderboard.name}: ${score}`);
return true;
}
getLeaderboard(leaderboardId) {
return this.leaderboards.get(leaderboardId);
}
// ========== SOCIAL INTEGRATION ==========
shareScreenshot() {
console.log('📸 Screenshot shared!');
// Steam overlay integration
}
visitFarm(playerId) {
console.log(`🚜 Visiting ${playerId}'s farm...`);
}
sendGift(playerId, item, amount) {
const gift = {
id: `gift_${Date.now()}`,
from: 'local_player',
to: playerId,
item,
amount,
message: '',
sentAt: Date.now()
};
console.log(`🎁 Gift sent to ${playerId}: ${amount}x ${item}`);
return gift;
}
receiveGift(giftId) {
console.log(`🎁 Gift received: ${giftId}`);
// Add to inventory
if (this.scene.inventorySystem) {
// this.scene.inventorySystem.addItem(gift.item, gift.amount);
}
}
addFriend(playerId) {
this.friends.add(playerId);
console.log(`👥 Added friend: ${playerId}`);
this.saveProgress();
}
removeFriend(playerId) {
this.friends.delete(playerId);
console.log(`👋 Removed friend: ${playerId}`);
this.saveProgress();
}
// ========== COMMUNITY EVENTS ==========
defineEvents() {
this.events = {
'harvest_festival': {
name: 'Harvest Festival',
duration: 604800000, // 7 days
bonuses: { crop_yield: 2.0, xp: 1.5 }
},
'zombie_invasion': {
name: 'Zombie Invasion',
duration: 259200000, // 3 days
bonuses: { zombie_spawn: 3.0, loot: 2.0 }
},
'winter_wonderland': {
name: 'Winter Wonderland',
duration: 1209600000, // 14 days
bonuses: { snow_items: true, special_decorations: true }
}
};
}
startEvent(eventId) {
const event = this.events[eventId];
if (!event) return false;
this.activeEvent = {
id: eventId,
...event,
startTime: Date.now(),
endTime: Date.now() + event.duration
};
console.log(`🎉 Event started: ${event.name}`);
return true;
}
endEvent() {
if (!this.activeEvent) return;
console.log(`🎉 Event ended: ${this.activeEvent.name}`);
this.activeEvent = null;
}
// ========== SEASONAL CHALLENGES ==========
getWeeklyChallenges() {
return [
{ name: 'Harvest 500 crops', reward: { gold: 1000 } },
{ name: 'Defeat 50 zombies', reward: { xp: 500 } },
{ name: 'Craft 20 items', reward: { blueprint: 'rare_item' } }
];
}
getMonthlyChallenges() {
return [
{ name: 'Reach level 50', reward: { legendary_item: 1 } },
{ name: 'Complete all quests', reward: { title: 'Quest Master' } },
{ name: 'Defeat all bosses', reward: { mount: 'dragon' } }
];
}
completeChallenge(challengeId) {
console.log(`✅ Challenge completed: ${challengeId}`);
}
// ========== UPDATE ==========
update(delta) {
// Update active event
if (this.activeEvent) {
const now = Date.now();
if (now >= this.activeEvent.endTime) {
this.endEvent();
}
}
// Update market prices periodically
// this.updateMarketPrices();
}
// ========== PERSISTENCE ==========
saveProgress() {
const data = {
friends: Array.from(this.friends),
leaderboards: Array.from(this.leaderboards.entries()).map(([id, lb]) => ({
id,
entries: lb.entries
}))
};
localStorage.setItem('novafarma_multiplayer', JSON.stringify(data));
}
loadProgress() {
const saved = localStorage.getItem('novafarma_multiplayer');
if (saved) {
try {
const data = JSON.parse(saved);
this.friends = new Set(data.friends || []);
if (data.leaderboards) {
data.leaderboards.forEach(lb => {
const leaderboard = this.leaderboards.get(lb.id);
if (leaderboard) {
leaderboard.entries = lb.entries;
}
});
}
console.log('✅ Multiplayer progress loaded');
} catch (error) {
console.error('Failed to load multiplayer progress:', error);
}
}
}
destroy() {
this.saveProgress();
console.log('🌐 Multiplayer & Social System destroyed');
}
}

View File

@@ -0,0 +1,424 @@
/**
* PLATFORM SUPPORT SYSTEM
* Cross-platform compatibility: Mobile, Controller, Steam Deck, Linux, Mac
*/
class PlatformSupportSystem {
constructor(scene) {
this.scene = scene;
this.enabled = true;
// Platform detection
this.platform = this.detectPlatform();
this.isMobile = this.platform === 'mobile';
this.isController = false;
// Mobile controls
this.virtualJoystick = null;
this.actionButtons = new Map();
this.touchControls = {
enabled: false,
joystickSize: 'medium',
buttonOpacity: 0.7,
leftHanded: false
};
// Controller support
this.connectedControllers = [];
this.controllerMapping = new Map();
// Steam Deck
this.isSteamDeck = this.detectSteamDeck();
this.steamDeckSettings = {
performanceMode: '60fps',
uiScale: 1.2
};
this.init();
console.log('✅ Platform Support System initialized');
console.log(`📱 Platform: ${this.platform}`);
}
init() {
if (this.isMobile) {
this.setupMobileControls();
}
this.setupControllerSupport();
if (this.isSteamDeck) {
this.setupSteamDeck();
}
console.log('🎮 Platform support ready');
}
// ========== PLATFORM DETECTION ==========
detectPlatform() {
const ua = navigator.userAgent.toLowerCase();
if (/android|webos|iphone|ipad|ipod|blackberry|iemobile|opera mini/i.test(ua)) {
return 'mobile';
}
if (ua.includes('steamdeck')) {
return 'steamdeck';
}
if (ua.includes('linux')) {
return 'linux';
}
if (ua.includes('mac')) {
return 'mac';
}
return 'windows';
}
detectSteamDeck() {
return navigator.userAgent.toLowerCase().includes('steamdeck');
}
// ========== MOBILE CONTROLS ==========
setupMobileControls() {
this.createVirtualJoystick();
this.createActionButtons();
this.createTopHUD();
this.createBottomActionBar();
this.setupGestureControls();
console.log('📱 Mobile controls initialized');
}
createVirtualJoystick() {
const sizes = { small: 80, medium: 100, large: 120 };
const size = sizes[this.touchControls.joystickSize];
this.virtualJoystick = {
x: this.touchControls.leftHanded ? window.innerWidth - 150 : 150,
y: window.innerHeight - 150,
size,
active: false,
touchId: null,
direction: { x: 0, y: 0 }
};
console.log('🕹️ Virtual joystick created');
}
createActionButtons() {
const rightX = this.touchControls.leftHanded ? 150 : window.innerWidth - 150;
// Primary action button
this.actionButtons.set('primary', {
x: rightX,
y: window.innerHeight - 150,
size: 70,
label: 'A',
action: 'interact'
});
// Special ability button
this.actionButtons.set('special', {
x: rightX - 80,
y: window.innerHeight - 200,
size: 60,
label: 'B',
action: 'dash'
});
// Auto-aim toggle
this.actionButtons.set('autoaim', {
x: rightX + 80,
y: window.innerHeight - 200,
size: 50,
label: '🎯',
action: 'toggle_autoaim'
});
console.log('🎮 Action buttons created');
}
createTopHUD() {
// Health bar (top-left)
// Hunger bar (below health)
// Gold/Resources (top-right)
// Mini-map (top-right corner)
// Day/Season indicator (top-center)
console.log('📊 Top HUD created');
}
createBottomActionBar() {
// Weapon/Tool switcher
// Building mode toggle
// Crafting quick access
// Pause button
console.log('🔧 Bottom action bar created');
}
setupGestureControls() {
// Pinch to zoom
// Two-finger pan
// Swipe to dodge
// Double-tap for special action
console.log('👆 Gesture controls setup');
}
handleTouch(touchEvent) {
// Handle touch input for virtual joystick and buttons
}
updateVirtualJoystick(delta) {
if (!this.virtualJoystick.active) return;
// Update player movement based on joystick direction
const { x, y } = this.virtualJoystick.direction;
if (this.scene.player) {
// Apply movement
}
}
// ========== CONTROLLER SUPPORT ==========
setupControllerSupport() {
window.addEventListener('gamepadconnected', (e) => this.onControllerConnected(e));
window.addEventListener('gamepaddisconnected', (e) => this.onControllerDisconnected(e));
this.defineControllerMappings();
console.log('🎮 Controller support initialized');
}
defineControllerMappings() {
// Xbox controller
this.controllerMapping.set('xbox', {
buttons: {
0: 'A',
1: 'B',
2: 'X',
3: 'Y',
4: 'LB',
5: 'RB',
6: 'LT',
7: 'RT',
8: 'Back',
9: 'Start',
10: 'LS',
11: 'RS',
12: 'Up',
13: 'Down',
14: 'Left',
15: 'Right'
},
axes: {
0: 'LS_X',
1: 'LS_Y',
2: 'RS_X',
3: 'RS_Y'
}
});
// PlayStation controller
this.controllerMapping.set('playstation', {
buttons: {
0: 'Cross',
1: 'Circle',
2: 'Square',
3: 'Triangle',
4: 'L1',
5: 'R1',
6: 'L2',
7: 'R2',
8: 'Share',
9: 'Options',
10: 'L3',
11: 'R3',
12: 'Up',
13: 'Down',
14: 'Left',
15: 'Right'
}
});
// Nintendo Switch Pro
this.controllerMapping.set('switch', {
buttons: {
0: 'B',
1: 'A',
2: 'Y',
3: 'X',
4: 'L',
5: 'R',
6: 'ZL',
7: 'ZR',
8: 'Minus',
9: 'Plus',
10: 'LS',
11: 'RS',
12: 'Up',
13: 'Down',
14: 'Left',
15: 'Right'
}
});
}
onControllerConnected(event) {
const gamepad = event.gamepad;
this.connectedControllers.push(gamepad);
this.isController = true;
console.log(`🎮 Controller connected: ${gamepad.id}`);
}
onControllerDisconnected(event) {
const gamepad = event.gamepad;
const index = this.connectedControllers.indexOf(gamepad);
if (index > -1) {
this.connectedControllers.splice(index, 1);
}
this.isController = this.connectedControllers.length > 0;
console.log(`🎮 Controller disconnected: ${gamepad.id}`);
}
updateControllers() {
const gamepads = navigator.getGamepads();
for (const gamepad of gamepads) {
if (!gamepad) continue;
// Read buttons
gamepad.buttons.forEach((button, index) => {
if (button.pressed) {
this.handleControllerButton(index);
}
});
// Read axes (joysticks)
const leftStickX = gamepad.axes[0];
const leftStickY = gamepad.axes[1];
if (Math.abs(leftStickX) > 0.1 || Math.abs(leftStickY) > 0.1) {
this.handleControllerMovement(leftStickX, leftStickY);
}
}
}
handleControllerButton(buttonIndex) {
// Map button to action
console.log(`🎮 Button pressed: ${buttonIndex}`);
}
handleControllerMovement(x, y) {
// Move player based on joystick input
if (this.scene.player) {
// Apply movement
}
}
// ========== STEAM DECK ==========
setupSteamDeck() {
// Adjust UI scale for Steam Deck screen
this.applyUIScale(this.steamDeckSettings.uiScale);
// Set performance mode
this.setPerformanceMode(this.steamDeckSettings.performanceMode);
console.log('🎮 Steam Deck optimizations applied');
}
applyUIScale(scale) {
// Scale UI elements for better visibility
console.log(`📏 UI scale: ${scale}x`);
}
setPerformanceMode(mode) {
const targetFPS = mode === '60fps' ? 60 : 30;
if (this.scene.game.config) {
this.scene.game.config.fps = { target: targetFPS };
}
console.log(`⚡ Performance mode: ${mode}`);
}
// ========== LINUX BUILD ==========
setupLinux() {
// Linux-specific optimizations
console.log('🐧 Linux optimizations applied');
}
// ========== MAC BUILD ==========
setupMac() {
// macOS-specific optimizations
// Metal API support
console.log('🍎 macOS optimizations applied');
}
checkM1M2Chip() {
// Detect Apple Silicon
return navigator.userAgent.includes('Macintosh') &&
navigator.userAgent.includes('AppleWebKit');
}
// ========== MOBILE OPTIMIZATION ==========
optimizeForMobile() {
// Reduce particle count
// Lower texture quality
// Disable shadows
// Reduce draw distance
console.log('📱 Mobile optimizations applied');
}
optimizeBattery() {
// Reduce FPS when inactive
// Disable non-essential effects
console.log('🔋 Battery optimizations applied');
}
// ========== CUSTOMIZATION ==========
saveControlLayout(profileName) {
const layout = {
joystickSize: this.touchControls.joystickSize,
buttonOpacity: this.touchControls.buttonOpacity,
leftHanded: this.touchControls.leftHanded,
buttons: Array.from(this.actionButtons.entries())
};
localStorage.setItem(`control_layout_${profileName}`, JSON.stringify(layout));
console.log(`💾 Control layout saved: ${profileName}`);
}
loadControlLayout(profileName) {
const saved = localStorage.getItem(`control_layout_${profileName}`);
if (saved) {
const layout = JSON.parse(saved);
this.touchControls = layout;
console.log(`📂 Control layout loaded: ${profileName}`);
}
}
// ========== UPDATE ==========
update(delta) {
if (this.isMobile && this.virtualJoystick) {
this.updateVirtualJoystick(delta);
}
if (this.isController) {
this.updateControllers();
}
}
destroy() {
console.log('🎮 Platform Support System destroyed');
}
}

View File

@@ -0,0 +1,427 @@
/**
* SAVE SYSTEM EXPANSION
* Advanced save/load with cloud sync, multiple slots, and auto-save
*/
class SaveSystemExpansion {
constructor(scene) {
this.scene = scene;
this.enabled = true;
// Save slots
this.maxSlots = 5;
this.currentSlot = 1;
this.saveSlots = new Map();
// Cloud sync
this.cloudSyncEnabled = false;
this.lastCloudSync = 0;
this.syncInterval = 300000; // 5 minutes
// Auto-save
this.autoSaveEnabled = true;
this.autoSaveInterval = 300000; // 5 minutes
this.lastAutoSave = 0;
this.preventSaveDuringCombat = true;
// Backup
this.backupEnabled = true;
this.maxBackups = 3;
this.loadSaveSlots();
this.init();
console.log('✅ Save System Expansion initialized');
}
init() {
this.setupAutoSave();
console.log('💾 Save system ready');
}
// ========== SAVE SLOTS ==========
createSaveSlot(slotNumber, saveName) {
if (slotNumber < 1 || slotNumber > this.maxSlots) {
console.log('❌ Invalid slot number');
return false;
}
const saveData = this.gatherSaveData();
const slot = {
slotNumber,
name: saveName || `Save ${slotNumber}`,
timestamp: Date.now(),
playTime: this.calculatePlayTime(),
thumbnail: this.generateThumbnail(),
data: saveData
};
this.saveSlots.set(slotNumber, slot);
this.saveToDisk(slotNumber);
console.log(`💾 Save created: Slot ${slotNumber} - ${slot.name}`);
return true;
}
loadSaveSlot(slotNumber) {
const slot = this.saveSlots.get(slotNumber);
if (!slot) {
console.log('❌ Save slot not found');
return false;
}
this.applySaveData(slot.data);
this.currentSlot = slotNumber;
console.log(`📂 Save loaded: Slot ${slotNumber} - ${slot.name}`);
return true;
}
deleteSaveSlot(slotNumber) {
if (!this.saveSlots.has(slotNumber)) {
console.log('❌ Save slot not found');
return false;
}
this.saveSlots.delete(slotNumber);
localStorage.removeItem(`novafarma_save_${slotNumber}`);
console.log(`🗑️ Save deleted: Slot ${slotNumber}`);
return true;
}
renameSaveSlot(slotNumber, newName) {
const slot = this.saveSlots.get(slotNumber);
if (!slot) return false;
slot.name = newName;
this.saveToDisk(slotNumber);
console.log(`✏️ Save renamed: Slot ${slotNumber}${newName}`);
return true;
}
// ========== SAVE DATA ==========
gatherSaveData() {
const data = {
version: '3.0.0',
timestamp: Date.now(),
// Player data
player: this.getPlayerData(),
// World data
world: this.getWorldData(),
// Systems data
systems: this.getSystemsData(),
// Progress
progress: this.getProgressData()
};
return data;
}
getPlayerData() {
if (!this.scene.player) return null;
return {
position: this.scene.player.getPosition(),
health: this.scene.statsSystem?.health || 100,
hunger: this.scene.statsSystem?.hunger || 100,
level: this.scene.skillTree?.level || 1,
xp: this.scene.skillTree?.xp || 0
};
}
getWorldData() {
return {
time: this.scene.weatherSystem?.currentTime || 0,
day: this.scene.weatherSystem?.currentDay || 1,
weather: this.scene.weatherSystem?.currentWeather || 'clear',
season: this.scene.weatherSystem?.currentSeason || 'spring'
};
}
getSystemsData() {
return {
inventory: this.scene.inventorySystem?.items || {},
skills: this.scene.skillTree?.skills || {},
quests: {
active: Array.from(this.scene.storyQuest?.activeQuests || []),
completed: Array.from(this.scene.storyQuest?.completedQuests || [])
},
automation: {
workers: this.scene.farmAutomation?.zombieWorkers.length || 0,
buildings: this.scene.farmAutomation?.automationBuildings.size || 0
}
};
}
getProgressData() {
return {
achievements: this.scene.uiGraphics?.unlockedAchievements || [],
bossesDefeated: Array.from(this.scene.bossBattles?.defeatedBosses || []),
recipesDiscovered: Array.from(this.scene.cooking?.knownRecipes || [])
};
}
applySaveData(data) {
// Restore player
if (data.player && this.scene.player) {
this.scene.player.setPosition(data.player.position.x, data.player.position.y);
if (this.scene.statsSystem) {
this.scene.statsSystem.health = data.player.health;
this.scene.statsSystem.hunger = data.player.hunger;
}
}
// Restore world
if (data.world && this.scene.weatherSystem) {
this.scene.weatherSystem.currentTime = data.world.time;
this.scene.weatherSystem.currentDay = data.world.day;
this.scene.weatherSystem.setWeather(data.world.weather);
}
// Restore systems
if (data.systems) {
if (this.scene.inventorySystem && data.systems.inventory) {
this.scene.inventorySystem.items = data.systems.inventory;
}
}
console.log('✅ Save data applied');
}
// ========== AUTO-SAVE ==========
setupAutoSave() {
if (!this.autoSaveEnabled) return;
setInterval(() => {
this.performAutoSave();
}, this.autoSaveInterval);
console.log(`⏰ Auto-save enabled (every ${this.autoSaveInterval / 1000}s)`);
}
performAutoSave() {
if (!this.canAutoSave()) return;
this.quickSave();
this.lastAutoSave = Date.now();
console.log('💾 Auto-save performed');
}
canAutoSave() {
// Don't save during combat
if (this.preventSaveDuringCombat && this.isInCombat()) {
return false;
}
return true;
}
isInCombat() {
// Check if player is in combat
return false; // Placeholder
}
// ========== QUICK SAVE/LOAD ==========
quickSave() {
return this.createSaveSlot(this.currentSlot, `Quick Save`);
}
quickLoad() {
return this.loadSaveSlot(this.currentSlot);
}
// ========== CLOUD SYNC ==========
enableCloudSync() {
this.cloudSyncEnabled = true;
console.log('☁️ Cloud sync enabled');
}
disableCloudSync() {
this.cloudSyncEnabled = false;
console.log('☁️ Cloud sync disabled');
}
syncToCloud(slotNumber) {
if (!this.cloudSyncEnabled) {
console.log('❌ Cloud sync is disabled');
return false;
}
const slot = this.saveSlots.get(slotNumber);
if (!slot) return false;
// Upload to Steam Cloud
console.log(`☁️ Uploading save to cloud: Slot ${slotNumber}`);
// Simulate cloud upload
this.lastCloudSync = Date.now();
return true;
}
syncFromCloud(slotNumber) {
if (!this.cloudSyncEnabled) {
console.log('❌ Cloud sync is disabled');
return false;
}
console.log(`☁️ Downloading save from cloud: Slot ${slotNumber}`);
// Simulate cloud download
return true;
}
resolveConflict(localSlot, cloudSlot) {
// Show UI to let player choose which save to keep
console.log('⚠️ Save conflict detected');
if (localSlot.timestamp > cloudSlot.timestamp) {
console.log('📤 Local save is newer - uploading');
return 'upload';
} else {
console.log('📥 Cloud save is newer - downloading');
return 'download';
}
}
// ========== BACKUP SYSTEM ==========
createBackup(slotNumber) {
if (!this.backupEnabled) return false;
const slot = this.saveSlots.get(slotNumber);
if (!slot) return false;
const backupKey = `novafarma_backup_${slotNumber}_${Date.now()}`;
localStorage.setItem(backupKey, JSON.stringify(slot));
// Clean old backups
this.cleanOldBackups(slotNumber);
console.log(`💾 Backup created: ${backupKey}`);
return true;
}
cleanOldBackups(slotNumber) {
const backups = this.getBackups(slotNumber);
if (backups.length > this.maxBackups) {
// Remove oldest backups
const toRemove = backups.slice(0, backups.length - this.maxBackups);
toRemove.forEach(backup => {
localStorage.removeItem(backup.key);
});
}
}
getBackups(slotNumber) {
const backups = [];
const prefix = `novafarma_backup_${slotNumber}_`;
for (let i = 0; i < localStorage.length; i++) {
const key = localStorage.key(i);
if (key && key.startsWith(prefix)) {
const timestamp = parseInt(key.split('_').pop());
backups.push({ key, timestamp });
}
}
return backups.sort((a, b) => a.timestamp - b.timestamp);
}
restoreBackup(backupKey) {
const backup = localStorage.getItem(backupKey);
if (!backup) {
console.log('❌ Backup not found');
return false;
}
const slot = JSON.parse(backup);
this.saveSlots.set(slot.slotNumber, slot);
console.log(`📂 Backup restored: ${backupKey}`);
return true;
}
// ========== THUMBNAILS ==========
generateThumbnail() {
// Generate screenshot thumbnail
return {
width: 160,
height: 90,
data: null // Base64 image data
};
}
// ========== PLAY TIME ==========
calculatePlayTime() {
// Calculate total play time in seconds
return 0; // Placeholder
}
formatPlayTime(seconds) {
const hours = Math.floor(seconds / 3600);
const minutes = Math.floor((seconds % 3600) / 60);
return `${hours}h ${minutes}m`;
}
// ========== PERSISTENCE ==========
saveToDisk(slotNumber) {
const slot = this.saveSlots.get(slotNumber);
if (!slot) return;
localStorage.setItem(`novafarma_save_${slotNumber}`, JSON.stringify(slot));
// Create backup
if (this.backupEnabled) {
this.createBackup(slotNumber);
}
}
loadSaveSlots() {
for (let i = 1; i <= this.maxSlots; i++) {
const saved = localStorage.getItem(`novafarma_save_${i}`);
if (saved) {
try {
const slot = JSON.parse(saved);
this.saveSlots.set(i, slot);
} catch (error) {
console.error(`Failed to load save slot ${i}:`, error);
}
}
}
console.log(`✅ Loaded ${this.saveSlots.size} save slots`);
}
// ========== UPDATE ==========
update(delta) {
// Auto cloud sync
if (this.cloudSyncEnabled) {
const now = Date.now();
if (now - this.lastCloudSync > this.syncInterval) {
this.syncToCloud(this.currentSlot);
}
}
}
destroy() {
console.log('💾 Save System Expansion destroyed');
}
}

View File

@@ -0,0 +1,484 @@
/**
* SKILL TREE SYSTEM
* Player progression with farming, combat, and survival branches
*/
class SkillTreeSystem {
constructor(scene) {
this.scene = scene;
this.enabled = true;
// Player stats
this.playerLevel = 1;
this.playerXP = 0;
this.skillPoints = 0;
// Skill trees
this.skills = {
farming: new Map(),
combat: new Map(),
survival: new Map()
};
// Active abilities
this.activeAbilities = new Map();
this.abilityCooldowns = new Map();
// Settings
this.settings = {
xpPerLevel: 100,
xpScaling: 1.5, // Each level requires 50% more XP
skillPointsPerLevel: 1,
maxLevel: 50
};
this.loadProgress();
this.init();
console.log('✅ Skill Tree System initialized');
}
init() {
this.defineSkills();
console.log('🌳 Skill trees ready');
}
// ========== SKILL DEFINITIONS ==========
defineSkills() {
// FARMING TREE
this.defineSkill('farming', 'green_thumb', {
name: 'Green Thumb',
description: 'Crops grow 10% faster',
maxLevel: 5,
cost: 1,
requires: null,
bonus: { type: 'crop_speed', value: 0.1 }
});
this.defineSkill('farming', 'efficient_harvest', {
name: 'Efficient Harvest',
description: '+20% crop yield',
maxLevel: 3,
cost: 1,
requires: 'green_thumb',
bonus: { type: 'crop_yield', value: 0.2 }
});
this.defineSkill('farming', 'area_harvest', {
name: 'Area Harvest',
description: 'Harvest 3x3 area at once',
maxLevel: 1,
cost: 2,
requires: 'efficient_harvest',
bonus: { type: 'ability', value: 'area_harvest' }
});
this.defineSkill('farming', 'master_farmer', {
name: 'Master Farmer',
description: 'Crops never wither',
maxLevel: 1,
cost: 3,
requires: 'area_harvest',
bonus: { type: 'crop_immortal', value: true }
});
// COMBAT TREE
this.defineSkill('combat', 'strength', {
name: 'Strength',
description: '+15% melee damage',
maxLevel: 5,
cost: 1,
requires: null,
bonus: { type: 'melee_damage', value: 0.15 }
});
this.defineSkill('combat', 'critical_strike', {
name: 'Critical Strike',
description: '10% chance for 2x damage',
maxLevel: 3,
cost: 1,
requires: 'strength',
bonus: { type: 'crit_chance', value: 0.1 }
});
this.defineSkill('combat', 'dash', {
name: 'Dash',
description: 'Quick dash ability (cooldown: 5s)',
maxLevel: 1,
cost: 2,
requires: 'strength',
bonus: { type: 'ability', value: 'dash' }
});
this.defineSkill('combat', 'berserker', {
name: 'Berserker',
description: '+50% damage when below 30% HP',
maxLevel: 1,
cost: 3,
requires: 'critical_strike',
bonus: { type: 'berserker', value: 0.5 }
});
// SURVIVAL TREE
this.defineSkill('survival', 'vitality', {
name: 'Vitality',
description: '+20 max health',
maxLevel: 5,
cost: 1,
requires: null,
bonus: { type: 'max_health', value: 20 }
});
this.defineSkill('survival', 'regeneration', {
name: 'Regeneration',
description: 'Heal 1 HP every 5 seconds',
maxLevel: 3,
cost: 1,
requires: 'vitality',
bonus: { type: 'health_regen', value: 1 }
});
this.defineSkill('survival', 'iron_skin', {
name: 'Iron Skin',
description: 'Reduce damage taken by 15%',
maxLevel: 3,
cost: 1,
requires: 'vitality',
bonus: { type: 'damage_reduction', value: 0.15 }
});
this.defineSkill('survival', 'second_wind', {
name: 'Second Wind',
description: 'Survive fatal damage once (cooldown: 60s)',
maxLevel: 1,
cost: 3,
requires: 'regeneration',
bonus: { type: 'ability', value: 'second_wind' }
});
}
defineSkill(tree, id, data) {
this.skills[tree].set(id, {
id,
tree,
currentLevel: 0,
...data
});
}
// ========== SKILL MANAGEMENT ==========
unlockSkill(tree, skillId) {
const skill = this.skills[tree].get(skillId);
if (!skill) return false;
// Check requirements
if (skill.requires) {
const required = this.skills[tree].get(skill.requires);
if (!required || required.currentLevel === 0) {
console.log('❌ Requirement not met:', skill.requires);
return false;
}
}
// Check skill points
if (this.skillPoints < skill.cost) {
console.log('❌ Not enough skill points');
return false;
}
// Check max level
if (skill.currentLevel >= skill.maxLevel) {
console.log('❌ Skill already maxed');
return false;
}
// Unlock skill
skill.currentLevel++;
this.skillPoints -= skill.cost;
// Apply bonus
this.applySkillBonus(skill);
// Unlock achievement
if (this.scene.uiGraphics) {
if (skill.currentLevel === skill.maxLevel) {
this.scene.uiGraphics.unlockAchievement('skill_master');
}
}
this.saveProgress();
console.log(`✅ Unlocked: ${skill.name} (Level ${skill.currentLevel})`);
return true;
}
applySkillBonus(skill) {
const bonus = skill.bonus;
switch (bonus.type) {
case 'ability':
this.activeAbilities.set(bonus.value, {
name: skill.name,
cooldown: 0,
ready: true
});
break;
case 'max_health':
if (this.scene.statsSystem) {
this.scene.statsSystem.maxHealth += bonus.value;
}
break;
case 'melee_damage':
case 'crit_chance':
case 'damage_reduction':
case 'crop_speed':
case 'crop_yield':
// These are passive bonuses checked when needed
break;
}
}
// ========== EXPERIENCE & LEVELING ==========
addXP(amount) {
this.playerXP += amount;
// Check for level up
const xpNeeded = this.getXPForLevel(this.playerLevel + 1);
if (this.playerXP >= xpNeeded && this.playerLevel < this.settings.maxLevel) {
this.levelUp();
}
this.saveProgress();
}
getXPForLevel(level) {
return Math.floor(
this.settings.xpPerLevel * Math.pow(this.settings.xpScaling, level - 1)
);
}
levelUp() {
this.playerLevel++;
this.skillPoints += this.settings.skillPointsPerLevel;
// Visual effect
if (this.scene.visualEnhancements) {
const player = this.scene.player;
if (player) {
const pos = player.getPosition();
this.scene.visualEnhancements.createSparkleEffect(pos.x, pos.y);
}
}
// Notification
if (this.scene.screenReader) {
this.scene.screenReader.speak(`Level up! You are now level ${this.playerLevel}!`);
}
console.log(`🎉 Level Up! Now level ${this.playerLevel}`);
this.saveProgress();
}
// ========== ACTIVE ABILITIES ==========
useAbility(abilityName) {
const ability = this.activeAbilities.get(abilityName);
if (!ability || !ability.ready) return false;
switch (abilityName) {
case 'dash':
this.performDash();
this.setAbilityCooldown(abilityName, 5000);
break;
case 'area_harvest':
this.performAreaHarvest();
this.setAbilityCooldown(abilityName, 10000);
break;
case 'second_wind':
// Triggered automatically on fatal damage
break;
}
return true;
}
performDash() {
if (!this.scene.player) return;
const player = this.scene.player;
const direction = player.facing || 'down';
const distance = 3;
let dx = 0, dy = 0;
switch (direction) {
case 'up': dy = -distance; break;
case 'down': dy = distance; break;
case 'left': dx = -distance; break;
case 'right': dx = distance; break;
}
const pos = player.getPosition();
player.setPosition(pos.x + dx, pos.y + dy);
// Dash effect
if (this.scene.visualEnhancements) {
this.scene.visualEnhancements.createSparkleEffect(pos.x, pos.y);
}
console.log('💨 Dash!');
}
performAreaHarvest() {
if (!this.scene.player || !this.scene.farmingSystem) return;
const pos = this.scene.player.getPosition();
const x = Math.floor(pos.x);
const y = Math.floor(pos.y);
// Harvest 3x3 area
let harvested = 0;
for (let dy = -1; dy <= 1; dy++) {
for (let dx = -1; dx <= 1; dx++) {
if (this.scene.farmingSystem.harvestCrop(x + dx, y + dy)) {
harvested++;
}
}
}
if (harvested > 0) {
console.log(`🌾 Area harvest: ${harvested} crops`);
}
}
setAbilityCooldown(abilityName, duration) {
const ability = this.activeAbilities.get(abilityName);
if (!ability) return;
ability.ready = false;
ability.cooldown = duration;
setTimeout(() => {
ability.ready = true;
ability.cooldown = 0;
}, duration);
}
// ========== SKILL BONUSES ==========
getSkillBonus(bonusType) {
let total = 0;
for (const tree of Object.values(this.skills)) {
for (const skill of tree.values()) {
if (skill.currentLevel > 0 && skill.bonus.type === bonusType) {
total += skill.bonus.value * skill.currentLevel;
}
}
}
return total;
}
hasSkill(tree, skillId) {
const skill = this.skills[tree].get(skillId);
return skill && skill.currentLevel > 0;
}
// ========== SKILL RESET ==========
resetSkills(cost = 1000) {
// Check if player has enough gold
if (this.scene.inventorySystem && this.scene.inventorySystem.gold < cost) {
console.log('❌ Not enough gold to reset skills');
return false;
}
// Deduct cost
if (this.scene.inventorySystem) {
this.scene.inventorySystem.gold -= cost;
}
// Reset all skills
let pointsRefunded = 0;
for (const tree of Object.values(this.skills)) {
for (const skill of tree.values()) {
pointsRefunded += skill.currentLevel * skill.cost;
skill.currentLevel = 0;
}
}
this.skillPoints = pointsRefunded;
this.activeAbilities.clear();
this.saveProgress();
console.log(`🔄 Skills reset! ${pointsRefunded} points refunded`);
return true;
}
// ========== PERSISTENCE ==========
saveProgress() {
const data = {
level: this.playerLevel,
xp: this.playerXP,
skillPoints: this.skillPoints,
skills: {}
};
// Save skill levels
for (const [treeName, tree] of Object.entries(this.skills)) {
data.skills[treeName] = {};
for (const [skillId, skill] of tree.entries()) {
if (skill.currentLevel > 0) {
data.skills[treeName][skillId] = skill.currentLevel;
}
}
}
localStorage.setItem('novafarma_skill_tree', JSON.stringify(data));
}
loadProgress() {
const saved = localStorage.getItem('novafarma_skill_tree');
if (saved) {
try {
const data = JSON.parse(saved);
this.playerLevel = data.level || 1;
this.playerXP = data.xp || 0;
this.skillPoints = data.skillPoints || 0;
// Load skill levels after skills are defined
this.savedSkills = data.skills || {};
console.log('✅ Skill progress loaded');
} catch (error) {
console.error('Failed to load skill progress:', error);
}
}
}
applyLoadedProgress() {
if (!this.savedSkills) return;
for (const [treeName, skills] of Object.entries(this.savedSkills)) {
for (const [skillId, level] of Object.entries(skills)) {
const skill = this.skills[treeName]?.get(skillId);
if (skill) {
skill.currentLevel = level;
this.applySkillBonus(skill);
}
}
}
this.savedSkills = null;
}
destroy() {
this.saveProgress();
console.log('🌳 Skill Tree System destroyed');
}
}

View File

@@ -0,0 +1,506 @@
/**
* STORY & QUEST SYSTEM
* Complete quest system with story acts, dialogue, cutscenes, and multiple endings
*/
class StoryQuestSystem {
constructor(scene) {
this.scene = scene;
this.enabled = true;
// Quests
this.quests = new Map();
this.activeQuests = new Set();
this.completedQuests = new Set();
// Story progress
this.currentAct = 1;
this.storyFlags = new Set();
// Characters
this.characters = new Map();
// Dialogue
this.currentDialogue = null;
// Endings
this.playerChoices = [];
this.ending = null;
this.loadProgress();
this.init();
console.log('✅ Story & Quest System initialized');
}
init() {
this.defineCharacters();
this.defineQuests();
console.log('📖 Story & Quest system ready');
}
// ========== CHARACTERS ==========
defineCharacters() {
this.characters.set('jakob', {
name: 'Old Jakob',
role: 'Merchant',
relationship: 0,
dialogues: new Map()
});
this.characters.set('lyra', {
name: 'Lyra',
role: 'Mutant Elf',
relationship: 0,
dialogues: new Map()
});
this.characters.set('grok', {
name: 'Grok',
role: 'Troll Guardian',
relationship: 0,
dialogues: new Map()
});
this.characters.set('dr_chen', {
name: 'Dr. Chen',
role: 'Radio Voice',
relationship: 0,
dialogues: new Map()
});
}
// ========== QUESTS ==========
defineQuests() {
// ACT 1: Survival (Day 1-10)
this.defineQuest('first_harvest', {
name: 'Prvi Pridelek',
act: 1,
description: 'Harvest 10 wheat to survive',
objectives: [
{ type: 'harvest', item: 'wheat', amount: 10, current: 0 }
],
rewards: { xp: 100, item: 'iron_hoe' },
unlocks: ['safe_haven']
});
this.defineQuest('safe_haven', {
name: 'Varno Zatočišče',
act: 1,
description: 'Build fence around farm',
objectives: [
{ type: 'build', item: 'fence', amount: 20, current: 0 }
],
rewards: { xp: 150, blueprint: 'reinforced_fence' },
unlocks: ['night_watch']
});
this.defineQuest('night_watch', {
name: 'Nočna Straža',
act: 1,
description: 'Survive first zombie night',
objectives: [
{ type: 'survive', nights: 1, current: 0 }
],
rewards: { xp: 200, item: 'torch_pack' },
unlocks: ['meet_merchant']
});
this.defineQuest('meet_merchant', {
name: 'Meet the Merchant',
act: 1,
description: 'Find Jakob the trader',
objectives: [
{ type: 'talk', npc: 'jakob' }
],
rewards: { xp: 100, unlocks: 'trading' },
unlocks: ['strange_transmission']
});
// ACT 2: Discovery (Day 11-20)
this.defineQuest('strange_transmission', {
name: 'Strange Transmission',
act: 2,
description: 'Find radio in city',
objectives: [
{ type: 'find', item: 'radio', location: 'city_ruins' }
],
rewards: { xp: 300, item: 'radio' },
unlocks: ['first_tame']
});
this.defineQuest('first_tame', {
name: 'Prvi Poskus',
act: 2,
description: 'Tame first zombie',
objectives: [
{ type: 'tame', creature: 'zombie', amount: 1 }
],
rewards: { xp: 250, unlocks: 'zombie_workers' },
unlocks: ['lab_ruins']
});
this.defineQuest('lab_ruins', {
name: 'Lab Ruins',
act: 2,
description: 'Explore abandoned research facility',
objectives: [
{ type: 'explore', location: 'research_lab' }
],
rewards: { xp: 400, item: 'lab_key' },
unlocks: ['mutant_contact']
});
this.defineQuest('mutant_contact', {
name: 'Mutant Contact',
act: 2,
description: 'Meet friendly mutant Lyra',
objectives: [
{ type: 'talk', npc: 'lyra' }
],
rewards: { xp: 300, unlocks: 'mutation_research' },
unlocks: ['lab_notes']
});
// ACT 3: The Truth (Day 21-30)
this.defineQuest('lab_notes', {
name: 'Lab Notes',
act: 3,
description: 'Collect 5 research documents',
objectives: [
{ type: 'collect', item: 'research_document', amount: 5, current: 0 }
],
rewards: { xp: 500 },
unlocks: ['patient_zero']
});
this.defineQuest('patient_zero', {
name: 'Patient Zero',
act: 3,
description: 'Find virus source',
objectives: [
{ type: 'find', item: 'virus_sample', location: 'deep_lab' }
],
rewards: { xp: 600 },
unlocks: ['difficult_choice']
});
this.defineQuest('difficult_choice', {
name: 'Difficult Choice',
act: 3,
description: 'Choose faction',
objectives: [
{ type: 'choice', options: ['human', 'zombie', 'hybrid'] }
],
rewards: { xp: 1000 },
unlocks: ['final_confrontation']
});
this.defineQuest('final_confrontation', {
name: 'Final Confrontation',
act: 3,
description: 'Boss battle',
objectives: [
{ type: 'defeat', boss: 'zombie_king' }
],
rewards: { xp: 2000 },
ending: true
});
}
defineQuest(id, data) {
this.quests.set(id, {
id,
active: false,
completed: false,
...data
});
}
// ========== QUEST MANAGEMENT ==========
startQuest(questId) {
const quest = this.quests.get(questId);
if (!quest || quest.active || quest.completed) return false;
quest.active = true;
this.activeQuests.add(questId);
console.log(`📜 Quest started: ${quest.name}`);
return true;
}
updateQuestProgress(questId, objectiveIndex, progress) {
const quest = this.quests.get(questId);
if (!quest || !quest.active) return;
const objective = quest.objectives[objectiveIndex];
if (!objective) return;
objective.current = progress;
// Check if objective complete
if (this.isObjectiveComplete(objective)) {
console.log(`✅ Objective complete: ${objective.type}`);
// Check if all objectives complete
if (quest.objectives.every(obj => this.isObjectiveComplete(obj))) {
this.completeQuest(questId);
}
}
}
isObjectiveComplete(objective) {
switch (objective.type) {
case 'harvest':
case 'build':
case 'collect':
return objective.current >= objective.amount;
case 'talk':
case 'find':
case 'explore':
case 'defeat':
return objective.current === true;
case 'survive':
return objective.current >= objective.nights;
default:
return false;
}
}
completeQuest(questId) {
const quest = this.quests.get(questId);
if (!quest) return;
quest.active = false;
quest.completed = true;
this.activeQuests.delete(questId);
this.completedQuests.add(questId);
// Grant rewards
this.grantQuestRewards(quest);
// Unlock next quests
if (quest.unlocks) {
const unlocks = Array.isArray(quest.unlocks) ? quest.unlocks : [quest.unlocks];
unlocks.forEach(nextQuest => this.startQuest(nextQuest));
}
// Check for ending
if (quest.ending) {
this.triggerEnding();
}
console.log(`🎉 Quest completed: ${quest.name}!`);
this.saveProgress();
}
grantQuestRewards(quest) {
const rewards = quest.rewards;
if (rewards.xp && this.scene.skillTree) {
this.scene.skillTree.addXP(rewards.xp);
}
if (rewards.item && this.scene.inventorySystem) {
this.scene.inventorySystem.addItem(rewards.item, 1);
}
if (rewards.blueprint) {
console.log(`📋 Unlocked blueprint: ${rewards.blueprint}`);
}
}
// ========== DIALOGUE SYSTEM ==========
startDialogue(npcId, dialogueId) {
const character = this.characters.get(npcId);
if (!character) return false;
this.currentDialogue = {
npc: npcId,
dialogueId,
currentNode: 0,
choices: []
};
console.log(`💬 Dialogue started with ${character.name}`);
return true;
}
selectDialogueChoice(choiceIndex) {
if (!this.currentDialogue) return;
const choice = this.currentDialogue.choices[choiceIndex];
if (!choice) return;
// Track player choice
this.playerChoices.push({
npc: this.currentDialogue.npc,
choice: choice.text,
consequence: choice.consequence
});
// Update relationship
const character = this.characters.get(this.currentDialogue.npc);
if (character && choice.relationshipDelta) {
character.relationship += choice.relationshipDelta;
}
// Apply consequences
if (choice.consequence) {
this.applyChoiceConsequence(choice.consequence);
}
console.log(`💬 Choice selected: ${choice.text}`);
}
applyChoiceConsequence(consequence) {
// Set story flags
if (consequence.flag) {
this.storyFlags.add(consequence.flag);
}
// Unlock quests
if (consequence.unlockQuest) {
this.startQuest(consequence.unlockQuest);
}
// Change faction
if (consequence.faction) {
this.playerChoices.push({ type: 'faction', value: consequence.faction });
}
}
endDialogue() {
this.currentDialogue = null;
}
// ========== CUTSCENES ==========
playCutscene(cutsceneId) {
console.log(`🎬 Playing cutscene: ${cutsceneId}`);
const cutscenes = {
'arrival': this.cutsceneArrival.bind(this),
'first_zombie': this.cutsceneFirstZombie.bind(this),
'city_discovery': this.cutsceneCityDiscovery.bind(this),
'boss_reveal': this.cutsceneBossReveal.bind(this)
};
const cutscene = cutscenes[cutsceneId];
if (cutscene) {
cutscene();
}
}
cutsceneArrival() {
console.log('🎬 Arrival cutscene - Farm overview');
}
cutsceneFirstZombie() {
console.log('🎬 First zombie encounter - Tutorial');
}
cutsceneCityDiscovery() {
console.log('🎬 City discovery - Ruins pan');
}
cutsceneBossReveal() {
console.log('🎬 Boss reveal - Zombie King emergence');
}
// ========== ENDINGS ==========
triggerEnding() {
// Determine ending based on player choices
const faction = this.getPlayerFaction();
const relationships = this.getRelationships();
if (faction === 'human' && relationships.jakob > 50) {
this.ending = 'cure';
this.playCutscene('cure_ending');
} else if (faction === 'zombie') {
this.ending = 'zombie_king';
this.playCutscene('zombie_king_ending');
} else if (faction === 'hybrid') {
this.ending = 'mutation';
this.playCutscene('mutation_ending');
} else if (relationships.lyra > 70) {
this.ending = 'escape';
this.playCutscene('escape_ending');
} else {
this.ending = 'farmer';
this.playCutscene('farmer_ending');
}
console.log(`🎬 Ending: ${this.ending}`);
this.saveProgress();
}
getPlayerFaction() {
const factionChoice = this.playerChoices.find(c => c.type === 'faction');
return factionChoice ? factionChoice.value : null;
}
getRelationships() {
const relationships = {};
for (const [id, character] of this.characters.entries()) {
relationships[id] = character.relationship;
}
return relationships;
}
// ========== PERSISTENCE ==========
saveProgress() {
const data = {
currentAct: this.currentAct,
activeQuests: Array.from(this.activeQuests),
completedQuests: Array.from(this.completedQuests),
storyFlags: Array.from(this.storyFlags),
playerChoices: this.playerChoices,
ending: this.ending,
characters: Array.from(this.characters.entries()).map(([id, char]) => ({
id,
relationship: char.relationship
}))
};
localStorage.setItem('novafarma_story', JSON.stringify(data));
}
loadProgress() {
const saved = localStorage.getItem('novafarma_story');
if (saved) {
try {
const data = JSON.parse(saved);
this.currentAct = data.currentAct || 1;
this.activeQuests = new Set(data.activeQuests || []);
this.completedQuests = new Set(data.completedQuests || []);
this.storyFlags = new Set(data.storyFlags || []);
this.playerChoices = data.playerChoices || [];
this.ending = data.ending || null;
if (data.characters) {
data.characters.forEach(char => {
const character = this.characters.get(char.id);
if (character) {
character.relationship = char.relationship;
}
});
}
console.log('✅ Story progress loaded');
} catch (error) {
console.error('Failed to load story progress:', error);
}
}
}
destroy() {
this.saveProgress();
console.log('📖 Story & Quest System destroyed');
}
}

View File

@@ -0,0 +1,429 @@
/**
* TECHNICAL & PERFORMANCE SYSTEM
* Performance optimization, mod support, replay system, and debug tools
*/
class TechnicalPerformanceSystem {
constructor(scene) {
this.scene = scene;
this.enabled = true;
// Performance monitoring
this.fpsHistory = [];
this.memoryHistory = [];
this.performanceStats = {
fps: 60,
memory: 0,
drawCalls: 0,
entities: 0
};
// Entity pooling
this.entityPools = new Map();
// Mod support
this.loadedMods = new Map();
this.modAPI = {};
// Replay system
this.isRecording = false;
this.isPlaying = false;
this.replayData = [];
this.currentReplayFrame = 0;
// Debug tools
this.debugMode = false;
this.debugCommands = new Map();
this.init();
console.log('✅ Technical & Performance System initialized');
}
init() {
this.setupEntityPools();
this.setupDebugCommands();
this.setupModAPI();
console.log('⚡ Technical & Performance ready');
}
// ========== PERFORMANCE MONITORING ==========
updatePerformanceStats() {
// FPS
this.performanceStats.fps = Math.round(this.scene.game.loop.actualFps);
this.fpsHistory.push(this.performanceStats.fps);
if (this.fpsHistory.length > 60) this.fpsHistory.shift();
// Memory (if available)
if (performance.memory) {
this.performanceStats.memory = Math.round(performance.memory.usedJSHeapSize / 1048576); // MB
this.memoryHistory.push(this.performanceStats.memory);
if (this.memoryHistory.length > 60) this.memoryHistory.shift();
}
// Entity count
this.performanceStats.entities = this.scene.children.list.length;
}
getPerformanceReport() {
const avgFps = this.fpsHistory.reduce((a, b) => a + b, 0) / this.fpsHistory.length;
const avgMemory = this.memoryHistory.reduce((a, b) => a + b, 0) / this.memoryHistory.length;
return {
fps: {
current: this.performanceStats.fps,
average: Math.round(avgFps),
min: Math.min(...this.fpsHistory),
max: Math.max(...this.fpsHistory)
},
memory: {
current: this.performanceStats.memory,
average: Math.round(avgMemory)
},
entities: this.performanceStats.entities
};
}
// ========== ENTITY POOLING ==========
setupEntityPools() {
// Create pools for frequently spawned entities
this.createPool('particle', 100);
this.createPool('projectile', 50);
this.createPool('enemy', 30);
this.createPool('item', 50);
}
createPool(type, size) {
const pool = {
available: [],
active: []
};
for (let i = 0; i < size; i++) {
pool.available.push(this.createEntity(type));
}
this.entityPools.set(type, pool);
console.log(`🔄 Created pool for ${type}: ${size} entities`);
}
createEntity(type) {
// Create entity based on type
return { type, active: false };
}
getFromPool(type) {
const pool = this.entityPools.get(type);
if (!pool || pool.available.length === 0) {
return this.createEntity(type);
}
const entity = pool.available.pop();
pool.active.push(entity);
entity.active = true;
return entity;
}
returnToPool(type, entity) {
const pool = this.entityPools.get(type);
if (!pool) return;
const index = pool.active.indexOf(entity);
if (index > -1) {
pool.active.splice(index, 1);
pool.available.push(entity);
entity.active = false;
}
}
// ========== CHUNK LOADING ==========
loadChunk(chunkX, chunkY) {
console.log(`📦 Loading chunk (${chunkX}, ${chunkY})`);
// Load terrain, entities, etc. for chunk
}
unloadChunk(chunkX, chunkY) {
console.log(`📦 Unloading chunk (${chunkX}, ${chunkY})`);
// Unload chunk to free memory
}
// ========== MOD SUPPORT ==========
setupModAPI() {
this.modAPI = {
registerItem: (id, data) => this.registerModItem(id, data),
registerRecipe: (id, data) => this.registerModRecipe(id, data),
registerEnemy: (id, data) => this.registerModEnemy(id, data),
addCommand: (name, callback) => this.addDebugCommand(name, callback)
};
}
loadMod(modId, modData) {
if (this.loadedMods.has(modId)) {
console.log(`❌ Mod already loaded: ${modId}`);
return false;
}
// Validate mod
if (!this.validateMod(modData)) {
console.log(`❌ Invalid mod: ${modId}`);
return false;
}
// Load mod
this.loadedMods.set(modId, modData);
// Execute mod init
if (modData.init) {
modData.init(this.modAPI);
}
console.log(`✅ Mod loaded: ${modId}`);
return true;
}
validateMod(modData) {
// Check required fields
return modData.name && modData.version;
}
registerModItem(id, data) {
console.log(`📦 Registered mod item: ${id}`);
}
registerModRecipe(id, data) {
console.log(`🔨 Registered mod recipe: ${id}`);
}
registerModEnemy(id, data) {
console.log(`👹 Registered mod enemy: ${id}`);
}
detectModConflicts() {
const conflicts = [];
// Check for conflicts between mods
return conflicts;
}
// ========== REPLAY SYSTEM ==========
startRecording() {
this.isRecording = true;
this.replayData = [];
console.log('🎬 Recording started');
}
stopRecording() {
this.isRecording = false;
console.log('🎬 Recording stopped');
return this.replayData;
}
recordFrame() {
if (!this.isRecording) return;
const frame = {
time: Date.now(),
inputs: this.captureInputs(),
state: this.captureGameState()
};
this.replayData.push(frame);
}
captureInputs() {
// Capture keyboard/mouse inputs
return {
keys: {},
mouse: { x: 0, y: 0, buttons: [] }
};
}
captureGameState() {
// Capture minimal game state
return {
playerPos: { x: 0, y: 0 },
time: 0
};
}
playReplay(replayData) {
this.isPlaying = true;
this.replayData = replayData;
this.currentReplayFrame = 0;
console.log('▶️ Playing replay');
}
stopReplay() {
this.isPlaying = false;
this.currentReplayFrame = 0;
console.log('⏹️ Replay stopped');
}
updateReplay() {
if (!this.isPlaying) return;
if (this.currentReplayFrame >= this.replayData.length) {
this.stopReplay();
return;
}
const frame = this.replayData[this.currentReplayFrame];
this.applyReplayFrame(frame);
this.currentReplayFrame++;
}
applyReplayFrame(frame) {
// Apply inputs and state from replay frame
}
saveReplay(filename) {
const data = JSON.stringify(this.replayData);
localStorage.setItem(`replay_${filename}`, data);
console.log(`💾 Replay saved: ${filename}`);
}
loadReplay(filename) {
const data = localStorage.getItem(`replay_${filename}`);
if (data) {
this.replayData = JSON.parse(data);
console.log(`📂 Replay loaded: ${filename}`);
return true;
}
return false;
}
// ========== DEBUG TOOLS ==========
setupDebugCommands() {
this.addDebugCommand('help', () => this.showDebugHelp());
this.addDebugCommand('spawn', (entity, x, y) => this.spawnEntity(entity, x, y));
this.addDebugCommand('tp', (x, y) => this.teleportPlayer(x, y));
this.addDebugCommand('give', (item, amount) => this.giveItem(item, amount));
this.addDebugCommand('time', (hours) => this.setTime(hours));
this.addDebugCommand('weather', (type) => this.setWeather(type));
this.addDebugCommand('god', () => this.toggleGodMode());
this.addDebugCommand('noclip', () => this.toggleNoclip());
this.addDebugCommand('kill', (radius) => this.killEnemies(radius));
this.addDebugCommand('clear', () => this.clearInventory());
}
addDebugCommand(name, callback) {
this.debugCommands.set(name, callback);
}
executeCommand(commandString) {
const parts = commandString.split(' ');
const command = parts[0];
const args = parts.slice(1);
const callback = this.debugCommands.get(command);
if (callback) {
callback(...args);
} else {
console.log(`❌ Unknown command: ${command}`);
}
}
showDebugHelp() {
console.log('📋 Available commands:');
for (const [name] of this.debugCommands.entries()) {
console.log(` - ${name}`);
}
}
spawnEntity(entity, x, y) {
console.log(`👾 Spawned ${entity} at (${x}, ${y})`);
}
teleportPlayer(x, y) {
if (this.scene.player) {
this.scene.player.setPosition(parseFloat(x), parseFloat(y));
console.log(`🚀 Teleported to (${x}, ${y})`);
}
}
giveItem(item, amount) {
if (this.scene.inventorySystem) {
this.scene.inventorySystem.addItem(item, parseInt(amount) || 1);
console.log(`🎁 Gave ${amount || 1}x ${item}`);
}
}
setTime(hours) {
if (this.scene.weatherSystem) {
this.scene.weatherSystem.currentTime = parseFloat(hours);
console.log(`⏰ Time set to ${hours}:00`);
}
}
setWeather(type) {
if (this.scene.weatherSystem) {
this.scene.weatherSystem.setWeather(type);
console.log(`🌦️ Weather set to ${type}`);
}
}
toggleGodMode() {
console.log('⚡ God mode toggled');
}
toggleNoclip() {
console.log('👻 Noclip toggled');
}
killEnemies(radius) {
console.log(`💀 Killed all enemies in ${radius || 'infinite'} radius`);
}
clearInventory() {
if (this.scene.inventorySystem) {
this.scene.inventorySystem.clear();
console.log('🗑️ Inventory cleared');
}
}
toggleDebugMode() {
this.debugMode = !this.debugMode;
console.log(`🐛 Debug mode: ${this.debugMode ? 'ON' : 'OFF'}`);
}
// ========== AUTO-UPDATE ==========
checkForUpdates() {
console.log('🔍 Checking for updates...');
// Check version against server
return { available: false, version: '3.0.0' };
}
downloadUpdate(version) {
console.log(`⬇️ Downloading update ${version}...`);
}
installUpdate() {
console.log('📦 Installing update...');
}
rollbackUpdate() {
console.log('⏪ Rolling back update...');
}
// ========== UPDATE ==========
update(delta) {
this.updatePerformanceStats();
if (this.isRecording) {
this.recordFrame();
}
if (this.isPlaying) {
this.updateReplay();
}
}
destroy() {
console.log('⚡ Technical & Performance System destroyed');
}
}

View File

@@ -0,0 +1,574 @@
/**
* UI GRAPHICS ENHANCEMENT SYSTEM
* High-resolution icons, animated UI elements, custom cursors, and achievements
*/
class UIGraphicsSystem {
constructor(scene) {
this.scene = scene;
this.enabled = true;
// Icon resolution
this.iconSize = 64; // 64x64 (upgraded from 32x32)
this.iconCache = new Map();
// Animated UI elements
this.animatedElements = [];
this.pulsingElements = [];
this.glowingElements = [];
// Custom cursors
this.cursors = {
'default': 'default',
'pointer': 'pointer',
'grab': 'grab',
'grabbing': 'grabbing',
'sword': 'url(data:image/png;base64,...) 16 16, auto',
'pickaxe': 'url(data:image/png;base64,...) 16 16, auto'
};
this.currentCursor = 'default';
// Achievement system
this.achievements = new Map();
this.unlockedAchievements = new Set();
// Loading screen
this.loadingScreen = null;
this.loadingProgress = 0;
// Settings
this.settings = {
highResIcons: true,
animatedUI: true,
customCursors: true,
achievementNotifications: true,
loadingArtwork: true
};
this.loadSettings();
this.init();
console.log('✅ UI Graphics System initialized');
}
init() {
// Generate high-res icons
if (this.settings.highResIcons) {
this.generateHighResIcons();
}
// Set up custom cursors
if (this.settings.customCursors) {
this.setupCustomCursors();
}
// Initialize achievements
this.initAchievements();
console.log('🎨 UI Graphics enhanced');
}
// ========== HIGH-RES ICONS ==========
generateHighResIcons() {
// Generate 64x64 icons for common items
const items = [
'wood', 'stone', 'iron', 'gold', 'diamond',
'wheat', 'carrot', 'potato', 'apple',
'sword', 'pickaxe', 'axe', 'hoe',
'health_potion', 'mana_potion'
];
for (const item of items) {
this.createHighResIcon(item);
}
console.log(`🖼️ Generated ${items.length} high-res icons (64x64)`);
}
createHighResIcon(itemName) {
const graphics = this.scene.add.graphics();
const size = this.iconSize;
// Icon background
graphics.fillStyle(0x333333, 1);
graphics.fillRoundedRect(0, 0, size, size, 8);
// Icon border
graphics.lineStyle(2, 0x666666, 1);
graphics.strokeRoundedRect(0, 0, size, size, 8);
// Item-specific graphics
switch (itemName) {
case 'wood':
graphics.fillStyle(0x8B4513, 1);
graphics.fillRect(16, 16, 32, 32);
break;
case 'stone':
graphics.fillStyle(0x808080, 1);
graphics.fillCircle(32, 32, 16);
break;
case 'gold':
graphics.fillStyle(0xFFD700, 1);
graphics.fillCircle(32, 32, 16);
break;
case 'diamond':
graphics.fillStyle(0x00FFFF, 1);
graphics.fillTriangle(32, 16, 16, 48, 48, 48);
break;
case 'sword':
graphics.fillStyle(0xC0C0C0, 1);
graphics.fillRect(28, 16, 8, 32);
graphics.fillTriangle(32, 16, 24, 24, 40, 24);
break;
case 'health_potion':
graphics.fillStyle(0xFF0000, 1);
graphics.fillCircle(32, 32, 16);
graphics.fillStyle(0xFFFFFF, 0.5);
graphics.fillCircle(28, 28, 4);
break;
default:
graphics.fillStyle(0x666666, 1);
graphics.fillRect(20, 20, 24, 24);
}
// Generate texture
graphics.generateTexture(`icon_${itemName}_64`, size, size);
graphics.destroy();
this.iconCache.set(itemName, `icon_${itemName}_64`);
}
getIcon(itemName) {
return this.iconCache.get(itemName) || 'icon_default_64';
}
// ========== ANIMATED UI ELEMENTS ==========
addPulsingElement(element, minScale = 0.95, maxScale = 1.05, duration = 1000) {
if (!this.settings.animatedUI) return;
const tween = this.scene.tweens.add({
targets: element,
scale: { from: minScale, to: maxScale },
duration: duration,
yoyo: true,
repeat: -1,
ease: 'Sine.easeInOut'
});
this.pulsingElements.push({ element, tween });
return tween;
}
addGlowingElement(element, color = 0xffff00, intensity = 0.5) {
if (!this.settings.animatedUI) return;
// Create glow effect
const glow = this.scene.add.circle(
element.x,
element.y,
element.width * 0.6,
color,
intensity
);
glow.setBlendMode(Phaser.BlendModes.ADD);
glow.setDepth(element.depth - 1);
// Pulsing glow
this.scene.tweens.add({
targets: glow,
alpha: { from: intensity, to: 0 },
scale: { from: 1, to: 1.5 },
duration: 1500,
yoyo: true,
repeat: -1
});
this.glowingElements.push({ element, glow });
return glow;
}
addHoverEffect(element, callback) {
if (!this.settings.animatedUI) return;
element.setInteractive();
element.on('pointerover', () => {
this.scene.tweens.add({
targets: element,
scale: 1.1,
duration: 200,
ease: 'Back.easeOut'
});
if (callback) callback('over');
});
element.on('pointerout', () => {
this.scene.tweens.add({
targets: element,
scale: 1.0,
duration: 200,
ease: 'Back.easeIn'
});
if (callback) callback('out');
});
element.on('pointerdown', () => {
this.scene.tweens.add({
targets: element,
scale: 0.95,
duration: 100
});
if (callback) callback('down');
});
element.on('pointerup', () => {
this.scene.tweens.add({
targets: element,
scale: 1.1,
duration: 100
});
if (callback) callback('up');
});
}
// ========== CUSTOM CURSORS ==========
setupCustomCursors() {
// Create custom cursor sprites
this.createCursorSprites();
}
createCursorSprites() {
// Sword cursor
const sword = this.scene.add.graphics();
sword.fillStyle(0xC0C0C0, 1);
sword.fillRect(0, 0, 4, 16);
sword.fillTriangle(2, 0, 0, 4, 4, 4);
sword.generateTexture('cursor_sword', 16, 16);
sword.destroy();
// Pickaxe cursor
const pickaxe = this.scene.add.graphics();
pickaxe.fillStyle(0x8B4513, 1);
pickaxe.fillRect(6, 8, 4, 8);
pickaxe.fillStyle(0x808080, 1);
pickaxe.fillRect(0, 0, 12, 8);
pickaxe.generateTexture('cursor_pickaxe', 16, 16);
pickaxe.destroy();
console.log('🖱️ Custom cursors created');
}
setCursor(cursorType) {
if (!this.settings.customCursors) return;
this.currentCursor = cursorType;
if (this.cursors[cursorType]) {
document.body.style.cursor = this.cursors[cursorType];
}
}
resetCursor() {
this.setCursor('default');
}
// ========== LOADING SCREEN ==========
showLoadingScreen(text = 'Loading...') {
if (!this.settings.loadingArtwork) return;
// Create loading screen container
this.loadingScreen = this.scene.add.container(0, 0);
this.loadingScreen.setDepth(10000);
this.loadingScreen.setScrollFactor(0);
const width = this.scene.cameras.main.width;
const height = this.scene.cameras.main.height;
// Background
const bg = this.scene.add.rectangle(
width / 2,
height / 2,
width,
height,
0x000000,
0.9
);
this.loadingScreen.add(bg);
// Logo/Title
const title = this.scene.add.text(
width / 2,
height / 2 - 100,
'NovaFarma',
{
fontSize: '64px',
fontFamily: 'Arial',
color: '#00ff00',
fontStyle: 'bold'
}
);
title.setOrigin(0.5);
this.loadingScreen.add(title);
// Loading text
const loadingText = this.scene.add.text(
width / 2,
height / 2,
text,
{
fontSize: '24px',
fontFamily: 'Arial',
color: '#ffffff'
}
);
loadingText.setOrigin(0.5);
this.loadingScreen.add(loadingText);
// Progress bar background
const barBg = this.scene.add.rectangle(
width / 2,
height / 2 + 50,
400,
30,
0x333333
);
this.loadingScreen.add(barBg);
// Progress bar fill
const barFill = this.scene.add.rectangle(
width / 2 - 200,
height / 2 + 50,
0,
30,
0x00ff00
);
barFill.setOrigin(0, 0.5);
this.loadingScreen.add(barFill);
this.loadingScreen.barFill = barFill;
// Pulsing animation
this.scene.tweens.add({
targets: loadingText,
alpha: { from: 1, to: 0.5 },
duration: 800,
yoyo: true,
repeat: -1
});
}
updateLoadingProgress(progress) {
if (!this.loadingScreen || !this.loadingScreen.barFill) return;
this.loadingProgress = Phaser.Math.Clamp(progress, 0, 100);
this.scene.tweens.add({
targets: this.loadingScreen.barFill,
width: (this.loadingProgress / 100) * 400,
duration: 300,
ease: 'Power2'
});
}
hideLoadingScreen() {
if (!this.loadingScreen) return;
this.scene.tweens.add({
targets: this.loadingScreen,
alpha: 0,
duration: 500,
onComplete: () => {
this.loadingScreen.destroy();
this.loadingScreen = null;
}
});
}
// ========== ACHIEVEMENTS ==========
initAchievements() {
// Define achievements
this.defineAchievement('first_harvest', {
name: 'First Harvest',
description: 'Harvest your first crop',
icon: '🌾',
points: 10
});
this.defineAchievement('master_farmer', {
name: 'Master Farmer',
description: 'Harvest 1000 crops',
icon: '👨‍🌾',
points: 50
});
this.defineAchievement('explorer', {
name: 'Explorer',
description: 'Explore 50% of the map',
icon: '🗺️',
points: 25
});
this.defineAchievement('rich', {
name: 'Wealthy',
description: 'Accumulate 10,000 gold',
icon: '💰',
points: 30
});
// Load unlocked achievements
this.loadUnlockedAchievements();
}
defineAchievement(id, data) {
this.achievements.set(id, {
id,
...data,
unlocked: false,
unlockedAt: null
});
}
unlockAchievement(id) {
const achievement = this.achievements.get(id);
if (!achievement || achievement.unlocked) return;
achievement.unlocked = true;
achievement.unlockedAt = Date.now();
this.unlockedAchievements.add(id);
// Show notification
if (this.settings.achievementNotifications) {
this.showAchievementNotification(achievement);
}
// Save
this.saveUnlockedAchievements();
console.log(`🏆 Achievement unlocked: ${achievement.name}`);
}
showAchievementNotification(achievement) {
const width = this.scene.cameras.main.width;
// Create notification
const notification = this.scene.add.container(width + 300, 100);
notification.setDepth(10001);
notification.setScrollFactor(0);
// Background
const bg = this.scene.add.rectangle(0, 0, 300, 100, 0x000000, 0.9);
bg.setStrokeStyle(2, 0xFFD700);
notification.add(bg);
// Icon
const icon = this.scene.add.text(-120, 0, achievement.icon, {
fontSize: '48px'
});
icon.setOrigin(0.5);
notification.add(icon);
// Text
const title = this.scene.add.text(-50, -20, 'Achievement Unlocked!', {
fontSize: '16px',
color: '#FFD700',
fontStyle: 'bold'
});
title.setOrigin(0, 0.5);
notification.add(title);
const name = this.scene.add.text(-50, 5, achievement.name, {
fontSize: '20px',
color: '#ffffff',
fontStyle: 'bold'
});
name.setOrigin(0, 0.5);
notification.add(name);
const points = this.scene.add.text(-50, 25, `+${achievement.points} points`, {
fontSize: '14px',
color: '#00ff00'
});
points.setOrigin(0, 0.5);
notification.add(points);
// Slide in
this.scene.tweens.add({
targets: notification,
x: width - 170,
duration: 500,
ease: 'Back.easeOut',
onComplete: () => {
// Wait, then slide out
this.scene.time.delayedCall(3000, () => {
this.scene.tweens.add({
targets: notification,
x: width + 300,
duration: 500,
ease: 'Back.easeIn',
onComplete: () => notification.destroy()
});
});
}
});
// Sparkle effect
if (this.scene.visualEnhancements) {
this.scene.visualEnhancements.createSparkleEffect(
notification.x,
notification.y
);
}
}
getAchievementProgress() {
const total = this.achievements.size;
const unlocked = this.unlockedAchievements.size;
return {
total,
unlocked,
percentage: (unlocked / total) * 100
};
}
// ========== PERSISTENCE ==========
saveUnlockedAchievements() {
const data = Array.from(this.unlockedAchievements);
localStorage.setItem('novafarma_achievements', JSON.stringify(data));
}
loadUnlockedAchievements() {
const saved = localStorage.getItem('novafarma_achievements');
if (saved) {
const data = JSON.parse(saved);
this.unlockedAchievements = new Set(data);
// Mark achievements as unlocked
for (const id of this.unlockedAchievements) {
const achievement = this.achievements.get(id);
if (achievement) {
achievement.unlocked = true;
}
}
}
}
saveSettings() {
localStorage.setItem('novafarma_ui_graphics', JSON.stringify(this.settings));
}
loadSettings() {
const saved = localStorage.getItem('novafarma_ui_graphics');
if (saved) {
this.settings = { ...this.settings, ...JSON.parse(saved) };
}
}
destroy() {
this.saveUnlockedAchievements();
console.log('🎨 UI Graphics System destroyed');
}
}

View File

@@ -8,11 +8,11 @@ class VisualEnhancementSystem {
this.enabled = true;
// Sub-systems
this.animatedTextures = null;
this.weatherEffects = null;
this.lightingSystem = null;
this.shadowSystem = null;
this.fogOfWar = null;
this.animatedTextures = new Map();
this.weatherEffects = [];
this.lightSources = [];
this.shadows = [];
this.particles = [];
// Settings
this.settings = {
@@ -22,9 +22,16 @@ class VisualEnhancementSystem {
shadows: true,
fogOfWar: false,
particleQuality: 'high', // low, medium, high, ultra
animationQuality: 'high'
animationQuality: 'high',
screenShake: true,
transitions: true
};
// Animation timers
this.waterAnimTime = 0;
this.treeAnimTime = 0;
this.fireAnimTime = 0;
this.loadSettings();
this.init();
@@ -32,161 +39,277 @@ class VisualEnhancementSystem {
}
init() {
// Initialize sub-systems
this.initAnimatedTextures();
this.initWeatherEffects();
this.initLightingSystem();
this.initShadowSystem();
this.initParticleSystem();
}
/**
* Initialize animated textures
*/
// ========== ANIMATED TEXTURES ==========
initAnimatedTextures() {
if (!this.settings.animatedTextures) return;
// Crop growth animations
this.createCropAnimations();
// Water flow
// Create water animation frames
this.createWaterAnimation();
// Tree leaves
this.createTreeAnimations();
// Create fire animation
this.createFireAnimation();
// Fire effects
this.createFireAnimations();
// Create tree leaf animation
this.createTreeAnimation();
console.log('🎬 Animated textures initialized');
}
/**
* Create crop growth animations
*/
createCropAnimations() {
// Smooth transitions between growth stages
console.log('🌱 Creating crop animations...');
}
/**
* Create water animation
*/
createWaterAnimation() {
// Flowing water effect
console.log('💧 Creating water animation...');
// Water flow animation (4 frames)
const frames = [];
for (let i = 0; i < 4; i++) {
const graphics = this.scene.add.graphics();
graphics.fillStyle(0x4488ff, 1);
graphics.fillRect(0, 0, 64, 64);
// Add wave pattern
graphics.lineStyle(2, 0x6699ff, 0.5);
for (let y = 0; y < 64; y += 8) {
const offset = Math.sin((y + i * 16) * 0.1) * 4;
graphics.lineBetween(0, y + offset, 64, y + offset);
}
graphics.generateTexture('water_anim_' + i, 64, 64);
graphics.destroy();
frames.push('water_anim_' + i);
}
this.animatedTextures.set('water', {
frames,
currentFrame: 0,
speed: 200 // ms per frame
});
}
/**
* Create tree animations
*/
createTreeAnimations() {
// Leaf rustling
console.log('🌳 Creating tree animations...');
createFireAnimation() {
// Fire flickering (3 frames)
const frames = [];
const colors = [0xff6600, 0xff8800, 0xffaa00];
for (let i = 0; i < 3; i++) {
const graphics = this.scene.add.graphics();
graphics.fillStyle(colors[i], 1);
graphics.fillCircle(16, 16, 12 + i * 2);
graphics.generateTexture('fire_anim_' + i, 32, 32);
graphics.destroy();
frames.push('fire_anim_' + i);
}
this.animatedTextures.set('fire', {
frames,
currentFrame: 0,
speed: 150
});
}
/**
* Create fire animations
*/
createFireAnimations() {
// Flickering flames
console.log('🔥 Creating fire animations...');
createTreeAnimation() {
// Tree leaf rustling (subtle movement)
console.log('🌳 Tree animation ready');
}
/**
* Initialize weather effects
*/
updateAnimatedTextures(delta) {
if (!this.settings.animatedTextures) return;
this.waterAnimTime += delta;
this.fireAnimTime += delta;
// Update water
const water = this.animatedTextures.get('water');
if (water && this.waterAnimTime > water.speed) {
water.currentFrame = (water.currentFrame + 1) % water.frames.length;
this.waterAnimTime = 0;
}
// Update fire
const fire = this.animatedTextures.get('fire');
if (fire && this.fireAnimTime > fire.speed) {
fire.currentFrame = (fire.currentFrame + 1) % fire.frames.length;
this.fireAnimTime = 0;
}
}
// ========== WEATHER EFFECTS ==========
initWeatherEffects() {
if (!this.settings.weatherEffects) return;
console.log('🌦️ Initializing weather effects...');
// Snow accumulation
// Rain splashes
// Wind indicators
// Lightning
// Fog
console.log('🌦️ Weather effects initialized');
}
/**
* Initialize lighting system
*/
createSnowEffect() {
const emitter = this.scene.add.particles(0, 0, 'particle_white', {
x: { min: 0, max: this.scene.cameras.main.width },
y: -10,
speedY: { min: 50, max: 100 },
speedX: { min: -20, max: 20 },
scale: { min: 0.3, max: 0.8 },
alpha: { min: 0.5, max: 1 },
lifespan: 10000,
frequency: 50,
quantity: 2
});
emitter.setScrollFactor(0);
this.weatherEffects.push(emitter);
return emitter;
}
createRainEffect() {
const emitter = this.scene.add.particles(0, 0, 'particle_white', {
x: { min: 0, max: this.scene.cameras.main.width },
y: -10,
speedY: { min: 400, max: 600 },
speedX: { min: -50, max: -30 },
scaleX: 0.1,
scaleY: 0.5,
alpha: 0.6,
lifespan: 2000,
frequency: 10,
quantity: 5,
tint: 0x88ccff
});
emitter.setScrollFactor(0);
this.weatherEffects.push(emitter);
return emitter;
}
createLightningFlash() {
const flash = this.scene.add.rectangle(
this.scene.cameras.main.centerX,
this.scene.cameras.main.centerY,
this.scene.cameras.main.width,
this.scene.cameras.main.height,
0xffffff,
0.8
);
flash.setScrollFactor(0);
flash.setDepth(10000);
this.scene.tweens.add({
targets: flash,
alpha: 0,
duration: 200,
onComplete: () => flash.destroy()
});
}
// ========== LIGHTING SYSTEM ==========
initLightingSystem() {
if (!this.settings.dynamicLighting) return;
console.log('💡 Initializing lighting system...');
// Create lighting layer
this.lightingLayer = this.scene.add.layer();
this.lightingLayer.setDepth(5000);
// Light sources
this.lightSources = [];
console.log('💡 Lighting system initialized');
}
/**
* Add light source
*/
addLight(x, y, radius, color, intensity) {
const light = {
addLight(x, y, radius = 100, color = 0xffaa00, intensity = 0.6) {
if (!this.settings.dynamicLighting) return null;
// Create radial gradient light
const light = this.scene.add.graphics();
const gradient = light.createRadialGradient(
radius, radius, 0,
radius, radius, radius
);
gradient.addColorStop(0, `rgba(${(color >> 16) & 0xff}, ${(color >> 8) & 0xff}, ${color & 0xff}, ${intensity})`);
gradient.addColorStop(1, 'rgba(0, 0, 0, 0)');
light.fillStyle(color, intensity);
light.fillCircle(radius, radius, radius);
light.setPosition(x - radius, y - radius);
light.setBlendMode(Phaser.BlendModes.ADD);
light.setDepth(5001);
const lightObj = {
graphics: light,
x, y, radius, color, intensity,
sprite: null
flickering: false
};
// Create light sprite
const graphics = this.scene.add.graphics();
graphics.fillStyle(color, intensity);
graphics.fillCircle(0, 0, radius);
graphics.generateTexture('light_' + this.lightSources.length, radius * 2, radius * 2);
graphics.destroy();
light.sprite = this.scene.add.sprite(x, y, 'light_' + this.lightSources.length);
light.sprite.setBlendMode(Phaser.BlendModes.ADD);
light.sprite.setAlpha(intensity);
this.lightSources.push(light);
return light;
this.lightSources.push(lightObj);
return lightObj;
}
/**
* Initialize shadow system
*/
addTorch(x, y) {
const torch = this.addLight(x, y, 80, 0xff6600, 0.5);
if (torch) {
torch.flickering = true;
}
return torch;
}
updateLighting(delta) {
if (!this.settings.dynamicLighting) return;
// Update flickering lights
for (const light of this.lightSources) {
if (light.flickering) {
const flicker = 0.4 + Math.random() * 0.2;
light.graphics.setAlpha(flicker);
}
}
// Update ambient lighting based on time of day
if (this.scene.weatherSystem) {
const time = this.scene.weatherSystem.gameTime;
const isNight = time < 6 || time > 18;
if (isNight) {
// Darker at night
this.scene.cameras.main.setAlpha(0.7);
} else {
this.scene.cameras.main.setAlpha(1.0);
}
}
}
// ========== SHADOW SYSTEM ==========
initShadowSystem() {
if (!this.settings.shadows) return;
console.log('🌑 Initializing shadow system...');
this.shadows = [];
console.log('🌑 Shadow system initialized');
}
/**
* Add shadow to entity
*/
addShadow(entity, offsetX = 0, offsetY = 10) {
addShadow(entity, offsetX = 0, offsetY = 10, width = 40, height = 15) {
if (!this.settings.shadows) return null;
const shadow = this.scene.add.ellipse(
entity.x + offsetX,
entity.y + offsetY,
entity.width * 0.8,
entity.height * 0.3,
width,
height,
0x000000,
0.3
);
shadow.setDepth(entity.depth - 1);
shadow.setDepth(0);
this.shadows.push({ entity, shadow, offsetX, offsetY });
const shadowObj = { entity, shadow, offsetX, offsetY };
this.shadows.push(shadowObj);
return shadow;
}
/**
* Update shadows based on time of day
*/
updateShadows() {
if (!this.settings.shadows) return;
// Get time of day
const timeOfDay = this.scene.weatherSystem ? this.scene.weatherSystem.gameTime : 12;
// Get time of day for shadow opacity
let opacity = 0.3;
if (this.scene.weatherSystem) {
const time = this.scene.weatherSystem.gameTime;
// Darker shadows at noon, lighter at dawn/dusk
opacity = 0.2 + Math.abs(Math.sin((time / 24) * Math.PI * 2)) * 0.3;
}
// Calculate shadow opacity (darker at noon, lighter at dawn/dusk)
const opacity = Math.abs(Math.sin((timeOfDay / 24) * Math.PI)) * 0.5;
// Update all shadows
// Update shadow positions
for (const { entity, shadow, offsetX, offsetY } of this.shadows) {
if (entity.sprite) {
shadow.x = entity.sprite.x + offsetX;
@@ -196,47 +319,225 @@ class VisualEnhancementSystem {
}
}
/**
* Create screen shake effect
*/
// ========== PARTICLE SYSTEM ==========
initParticleSystem() {
// Create particle textures
this.createParticleTextures();
console.log('✨ Particle system initialized');
}
createParticleTextures() {
// White particle
const white = this.scene.add.graphics();
white.fillStyle(0xffffff, 1);
white.fillCircle(4, 4, 4);
white.generateTexture('particle_white', 8, 8);
white.destroy();
// Sparkle
const sparkle = this.scene.add.graphics();
sparkle.fillStyle(0xffff00, 1);
sparkle.fillCircle(3, 3, 3);
sparkle.generateTexture('particle_sparkle', 6, 6);
sparkle.destroy();
// Heart
const heart = this.scene.add.graphics();
heart.fillStyle(0xff0066, 1);
heart.fillCircle(3, 3, 3);
heart.fillCircle(5, 3, 3);
heart.fillTriangle(1, 4, 7, 4, 4, 8);
heart.generateTexture('particle_heart', 8, 8);
heart.destroy();
}
createHeartParticles(x, y) {
const emitter = this.scene.add.particles(x, y, 'particle_heart', {
speed: { min: 20, max: 50 },
angle: { min: -120, max: -60 },
scale: { start: 1, end: 0 },
alpha: { start: 1, end: 0 },
lifespan: 1000,
quantity: 5,
blendMode: 'ADD'
});
this.scene.time.delayedCall(1000, () => emitter.destroy());
return emitter;
}
createSparkleEffect(x, y) {
const emitter = this.scene.add.particles(x, y, 'particle_sparkle', {
speed: { min: 10, max: 30 },
scale: { start: 1, end: 0 },
alpha: { start: 1, end: 0 },
lifespan: 800,
quantity: 10,
blendMode: 'ADD'
});
this.scene.time.delayedCall(800, () => emitter.destroy());
return emitter;
}
createCheckmarkEffect(x, y) {
const checkmark = this.scene.add.text(x, y, '✓', {
fontSize: '32px',
color: '#00ff00',
fontStyle: 'bold'
});
checkmark.setOrigin(0.5);
checkmark.setDepth(10000);
this.scene.tweens.add({
targets: checkmark,
y: y - 50,
alpha: 0,
scale: 2,
duration: 1000,
ease: 'Power2',
onComplete: () => checkmark.destroy()
});
}
// ========== SCREEN EFFECTS ==========
screenShake(intensity = 10, duration = 300) {
if (!this.settings.screenShake) return;
this.scene.cameras.main.shake(duration, intensity / 1000);
}
/**
* Create fade transition
*/
screenFlash(color = 0xffffff, duration = 200) {
this.scene.cameras.main.flash(duration,
(color >> 16) & 0xff,
(color >> 8) & 0xff,
color & 0xff
);
}
fadeOut(duration = 500, callback) {
if (!this.settings.transitions) {
if (callback) callback();
return;
}
this.scene.cameras.main.fadeOut(duration, 0, 0, 0);
this.scene.cameras.main.once('camerafadeoutcomplete', callback);
}
/**
* Fade in
*/
fadeIn(duration = 500) {
this.scene.cameras.main.fadeIn(duration, 0, 0, 0);
}
/**
* Update (called every frame)
*/
update(delta) {
if (this.settings.shadows) {
this.updateShadows();
if (callback) {
this.scene.cameras.main.once('camerafadeoutcomplete', callback);
}
}
/**
* Save settings
*/
fadeIn(duration = 500) {
if (!this.settings.transitions) return;
this.scene.cameras.main.fadeIn(duration, 0, 0, 0);
}
// ========== BUILDING EFFECTS ==========
createConstructionEffect(x, y) {
// Dust particles during construction
const emitter = this.scene.add.particles(x, y, 'particle_white', {
speed: { min: 20, max: 40 },
scale: { start: 0.5, end: 0 },
alpha: { start: 0.5, end: 0 },
lifespan: 1000,
quantity: 3,
frequency: 100,
tint: 0x996633
});
return emitter;
}
createSmokeEffect(x, y) {
// Chimney smoke
const emitter = this.scene.add.particles(x, y, 'particle_white', {
speedY: { min: -30, max: -50 },
speedX: { min: -10, max: 10 },
scale: { start: 0.3, end: 1 },
alpha: { start: 0.5, end: 0 },
lifespan: 2000,
frequency: 500,
quantity: 1,
tint: 0x888888
});
return emitter;
}
// ========== FARM AUTOMATION VISUALS ==========
createPowerGridEffect(x1, y1, x2, y2) {
// Electric arc between power sources
const graphics = this.scene.add.graphics();
graphics.lineStyle(2, 0x00ffff, 0.8);
// Draw lightning-like connection
const steps = 5;
const points = [];
for (let i = 0; i <= steps; i++) {
const t = i / steps;
const x = x1 + (x2 - x1) * t + (Math.random() - 0.5) * 10;
const y = y1 + (y2 - y1) * t + (Math.random() - 0.5) * 10;
points.push({ x, y });
}
graphics.beginPath();
graphics.moveTo(points[0].x, points[0].y);
for (let i = 1; i < points.length; i++) {
graphics.lineTo(points[i].x, points[i].y);
}
graphics.strokePath();
// Fade out
this.scene.tweens.add({
targets: graphics,
alpha: 0,
duration: 200,
onComplete: () => graphics.destroy()
});
}
createMutantGlow(entity, color = 0x00ff00) {
// Radioactive glow for mutants
const glow = this.scene.add.circle(
entity.x,
entity.y,
30,
color,
0.3
);
glow.setBlendMode(Phaser.BlendModes.ADD);
glow.setDepth(entity.depth - 1);
// Pulsing animation
this.scene.tweens.add({
targets: glow,
scale: { from: 1, to: 1.2 },
alpha: { from: 0.3, to: 0.1 },
duration: 1000,
yoyo: true,
repeat: -1
});
return glow;
}
// ========== UPDATE ==========
update(delta) {
this.updateAnimatedTextures(delta);
this.updateLighting(delta);
this.updateShadows();
}
// ========== SETTINGS ==========
saveSettings() {
localStorage.setItem('novafarma_visual_enhancements', JSON.stringify(this.settings));
}
/**
* Load settings
*/
loadSettings() {
const saved = localStorage.getItem('novafarma_visual_enhancements');
if (saved) {
@@ -244,14 +545,14 @@ class VisualEnhancementSystem {
}
}
/**
* Destroy system
*/
destroy() {
if (this.lightingLayer) this.lightingLayer.destroy();
for (const { shadow } of this.shadows) {
shadow.destroy();
}
for (const effect of this.weatherEffects) {
effect.destroy();
}
console.log('✨ Visual Enhancement System destroyed');
}
}

View File

@@ -0,0 +1,444 @@
/**
* WORKER CREATURES SYSTEM
* Specialized creature workers with unique abilities
*/
class WorkerCreaturesSystem {
constructor(scene) {
this.scene = scene;
this.enabled = true;
// Worker creatures
this.workers = new Map();
// Creature types
this.creatureTypes = new Map();
// Active tasks
this.activeTasks = [];
this.init();
console.log('✅ Worker Creatures System initialized');
}
init() {
this.defineCreatureTypes();
console.log('🦌 Worker creatures ready');
}
// ========== CREATURE TYPES ==========
defineCreatureTypes() {
// Donkey - Transport specialist
this.defineCreature('donkey', {
name: 'Donkey',
specialty: 'transport',
efficiency: 0.8,
abilities: ['carry_items', 'cart_transport', 'long_distance'],
carryCapacity: 50,
speed: 1.2,
tamingDifficulty: 'easy',
cost: { carrot: 10, apple: 5 }
});
// Bigfoot - Forest gathering specialist
this.defineCreature('bigfoot', {
name: 'Bigfoot',
specialty: 'gathering',
efficiency: 1.0,
abilities: ['tree_chopping', 'berry_picking', 'mushroom_finding', 'forest_navigation'],
gatherBonus: 1.5,
speed: 0.9,
tamingDifficulty: 'medium',
cost: { honey: 5, berries: 20 }
});
// Yeti - Snow biome specialist
this.defineCreature('yeti', {
name: 'Yeti',
specialty: 'snow_tasks',
efficiency: 1.2,
abilities: ['ice_mining', 'snow_clearing', 'cold_resistance', 'ice_fishing'],
coldBonus: 2.0,
speed: 0.8,
tamingDifficulty: 'hard',
cost: { frozen_meat: 10, ice_crystal: 3 }
});
// Elf - Crafting specialist
this.defineCreature('elf', {
name: 'Elf',
specialty: 'crafting',
efficiency: 1.5,
abilities: ['auto_craft', 'enchanting', 'potion_making', 'tool_repair'],
craftingSpeed: 2.0,
speed: 1.0,
tamingDifficulty: 'hard',
cost: { magic_dust: 5, golden_apple: 2 }
});
// Gnome - Mining specialist
this.defineCreature('gnome', {
name: 'Gnome',
specialty: 'mining',
efficiency: 1.3,
abilities: ['ore_detection', 'tunnel_digging', 'gem_finding', 'cave_navigation'],
miningBonus: 1.8,
speed: 0.7,
tamingDifficulty: 'medium',
cost: { gold_nugget: 5, diamond: 1 }
});
// Fairy - Plant care specialist
this.defineCreature('fairy', {
name: 'Fairy',
specialty: 'plant_care',
efficiency: 1.4,
abilities: ['instant_growth', 'disease_cure', 'crop_blessing', 'flower_magic'],
growthBonus: 2.5,
speed: 1.5,
tamingDifficulty: 'very_hard',
cost: { rainbow_flower: 3, fairy_dust: 10 }
});
// Golem - Heavy labor specialist
this.defineCreature('golem', {
name: 'Golem',
specialty: 'heavy_labor',
efficiency: 0.9,
abilities: ['boulder_moving', 'building_construction', 'land_clearing', 'defense'],
strengthBonus: 3.0,
speed: 0.5,
tamingDifficulty: 'very_hard',
cost: { stone: 100, iron: 50, magic_core: 1 }
});
// Dragon - Ultimate worker
this.defineCreature('dragon', {
name: 'Dragon',
specialty: 'all',
efficiency: 2.0,
abilities: ['flight', 'fire_breath', 'treasure_finding', 'all_tasks'],
allBonus: 2.0,
speed: 2.0,
tamingDifficulty: 'legendary',
cost: { dragon_egg: 1, legendary_meat: 10, gold: 1000 }
});
}
defineCreature(id, data) {
this.creatureTypes.set(id, {
id,
...data
});
}
// ========== TAMING ==========
canTame(creatureType) {
const creature = this.creatureTypes.get(creatureType);
if (!creature) return false;
// Check if player has required items
if (!this.scene.inventorySystem) return false;
for (const [item, amount] of Object.entries(creature.cost)) {
const has = this.scene.inventorySystem.getItemCount(item);
if (has < amount) {
console.log(`❌ Missing ${item}: ${has}/${amount}`);
return false;
}
}
return true;
}
tameCreature(creatureType, x, y) {
if (!this.canTame(creatureType)) return false;
const creatureData = this.creatureTypes.get(creatureType);
// Consume taming items
for (const [item, amount] of Object.entries(creatureData.cost)) {
this.scene.inventorySystem.removeItem(item, amount);
}
// Create worker
const worker = {
id: `worker_${creatureType}_${Date.now()}`,
type: creatureType,
name: creatureData.name,
specialty: creatureData.specialty,
efficiency: creatureData.efficiency,
abilities: creatureData.abilities,
x, y,
currentTask: null,
level: 1,
xp: 0,
loyalty: 50,
sprite: null
};
this.workers.set(worker.id, worker);
// Notify automation tier system
if (this.scene.automationTiers) {
this.scene.automationTiers.befriendCreature();
}
// Visual effect
if (this.scene.visualEnhancements) {
this.scene.visualEnhancements.createSparkleEffect(x, y);
this.scene.visualEnhancements.screenFlash(0x00ff00, 500);
}
console.log(`✅ Tamed ${creatureData.name}!`);
return worker;
}
// ========== TASK ASSIGNMENT ==========
assignTask(workerId, task) {
const worker = this.workers.get(workerId);
if (!worker) return false;
const creatureData = this.creatureTypes.get(worker.type);
// Check if creature can do this task
if (!this.canDoTask(worker, task)) {
console.log(`${worker.name} cannot do ${task.type}`);
return false;
}
// Assign task
worker.currentTask = {
...task,
startTime: Date.now(),
efficiency: this.calculateEfficiency(worker, task)
};
console.log(`📋 ${worker.name} assigned to ${task.type}`);
return true;
}
canDoTask(worker, task) {
const creatureData = this.creatureTypes.get(worker.type);
// Dragons can do everything
if (worker.type === 'dragon') return true;
// Check specialty
const taskSpecialties = {
'transport': ['donkey'],
'gather_wood': ['bigfoot'],
'gather_berries': ['bigfoot'],
'mine_ice': ['yeti'],
'ice_fishing': ['yeti'],
'craft_item': ['elf'],
'enchant_item': ['elf'],
'mine_ore': ['gnome'],
'find_gems': ['gnome'],
'water_crops': ['fairy'],
'grow_crops': ['fairy'],
'build': ['golem'],
'clear_land': ['golem']
};
const validTypes = taskSpecialties[task.type] || [];
return validTypes.includes(worker.type);
}
calculateEfficiency(worker, task) {
const creatureData = this.creatureTypes.get(worker.type);
let efficiency = creatureData.efficiency;
// Apply specialty bonuses
if (task.type.includes('gather') && creatureData.gatherBonus) {
efficiency *= creatureData.gatherBonus;
}
if (task.type.includes('mine') && creatureData.miningBonus) {
efficiency *= creatureData.miningBonus;
}
if (task.type.includes('craft') && creatureData.craftingSpeed) {
efficiency *= creatureData.craftingSpeed;
}
if (task.type.includes('grow') && creatureData.growthBonus) {
efficiency *= creatureData.growthBonus;
}
// Apply level bonus
efficiency *= (1 + worker.level * 0.1);
return efficiency;
}
// ========== TASK EXECUTION ==========
updateWorkers(delta) {
for (const worker of this.workers.values()) {
if (!worker.currentTask) continue;
const elapsed = Date.now() - worker.currentTask.startTime;
const taskTime = worker.currentTask.duration / worker.currentTask.efficiency;
if (elapsed >= taskTime) {
this.completeTask(worker);
}
}
}
completeTask(worker) {
const task = worker.currentTask;
// Execute task
this.executeTask(worker, task);
// Grant XP
this.addWorkerXP(worker, task.xp || 10);
// Increase loyalty
worker.loyalty = Math.min(100, worker.loyalty + 1);
// Clear task
worker.currentTask = null;
console.log(`${worker.name} completed ${task.type}!`);
}
executeTask(worker, task) {
switch (task.type) {
case 'transport':
this.transportItems(worker, task);
break;
case 'gather_wood':
this.gatherResource(worker, 'wood', task.amount);
break;
case 'gather_berries':
this.gatherResource(worker, 'berries', task.amount);
break;
case 'mine_ore':
this.gatherResource(worker, 'ore', task.amount);
break;
case 'craft_item':
this.craftItem(worker, task.item);
break;
case 'grow_crops':
this.growCrops(worker, task.crops);
break;
default:
console.log(`Unknown task: ${task.type}`);
}
}
transportItems(worker, task) {
// Move items from A to B
console.log(`🚚 ${worker.name} transported items`);
}
gatherResource(worker, resource, amount) {
// Add resource to inventory
if (this.scene.inventorySystem) {
const bonus = this.workers.get(worker.id).currentTask.efficiency;
const finalAmount = Math.floor(amount * bonus);
this.scene.inventorySystem.addItem(resource, finalAmount);
console.log(`📦 Gathered ${finalAmount} ${resource}`);
}
}
craftItem(worker, item) {
// Craft item
if (this.scene.inventorySystem) {
this.scene.inventorySystem.addItem(item, 1);
console.log(`🔨 Crafted ${item}`);
}
}
growCrops(worker, crops) {
// Instantly grow crops
console.log(`🌱 Grew ${crops.length} crops`);
}
// ========== LEVELING ==========
addWorkerXP(worker, amount) {
worker.xp += amount;
const xpNeeded = this.getXPForLevel(worker.level + 1);
if (worker.xp >= xpNeeded) {
this.levelUpWorker(worker);
}
}
getXPForLevel(level) {
return Math.floor(100 * Math.pow(1.5, level - 1));
}
levelUpWorker(worker) {
worker.level++;
worker.xp = 0;
console.log(`🎉 ${worker.name} leveled up to ${worker.level}!`);
// Visual effect
if (this.scene.visualEnhancements) {
this.scene.visualEnhancements.createSparkleEffect(worker.x, worker.y);
}
}
// ========== SPECIAL ABILITIES ==========
useAbility(workerId, abilityName) {
const worker = this.workers.get(workerId);
if (!worker) return false;
const creatureData = this.creatureTypes.get(worker.type);
if (!creatureData.abilities.includes(abilityName)) {
console.log(`${worker.name} doesn't have ${abilityName}`);
return false;
}
// Execute ability
switch (abilityName) {
case 'instant_growth':
this.instantGrowth(worker);
break;
case 'fire_breath':
this.fireBreath(worker);
break;
case 'treasure_finding':
this.findTreasure(worker);
break;
default:
console.log(`${worker.name} used ${abilityName}!`);
}
return true;
}
instantGrowth(worker) {
// Fairy ability - instantly grow all nearby crops
console.log('🌸 Fairy magic! All crops instantly grown!');
}
fireBreath(worker) {
// Dragon ability - clear area with fire
console.log('🔥 Dragon fire breath!');
}
findTreasure(worker) {
// Dragon ability - find hidden treasure
console.log('💎 Found treasure!');
if (this.scene.inventorySystem) {
this.scene.inventorySystem.addItem('gold', 100);
}
}
// ========== UPDATE ==========
update(delta) {
this.updateWorkers(delta);
}
destroy() {
console.log('🦌 Worker Creatures System destroyed');
}
}