narejeno
This commit is contained in:
591
src/systems/AnimalBreedingSystem.js
Normal file
591
src/systems/AnimalBreedingSystem.js
Normal 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');
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user