532 lines
16 KiB
JavaScript
532 lines
16 KiB
JavaScript
/**
|
||
* BUG CATCHING & COLLECTION SYSTEM
|
||
* Catch, collect, and sell bugs
|
||
*
|
||
* Features:
|
||
* - Bug Net tool (3 tiers)
|
||
* - 50+ Bug species
|
||
* - Bug Collection Album (like fish collection)
|
||
* - Rarity system: Common, Uncommon, Rare, Epic, Legendary
|
||
* - Seasonal & biome-specific bugs
|
||
* - Bug selling for gold
|
||
* - Bug jar decorations
|
||
*/
|
||
class BugCatchingSystem {
|
||
constructor(scene) {
|
||
this.scene = scene;
|
||
|
||
// Bug net tiers
|
||
this.bugNets = {
|
||
basic: { name: 'Basic Bug Net', catchRate: 0.5, speed: 1.0, cost: 50 },
|
||
silk: { name: 'Silk Bug Net', catchRate: 0.75, speed: 1.3, cost: 200 },
|
||
enchanted: { name: 'Enchanted Net', catchRate: 0.95, speed: 1.8, cost: 1000 }
|
||
};
|
||
|
||
// Player's bug net
|
||
this.currentNet = null;
|
||
|
||
// Bug collection
|
||
this.caughtBugs = new Map(); // bugId -> count
|
||
this.bugAlbum = new Map(); // bugId -> discoveryData
|
||
|
||
// Active bugs in world
|
||
this.activeBugs = [];
|
||
|
||
// Bug definitions (50+ species)
|
||
this.bugs = {
|
||
// COMMON BUGS (50g-100g)
|
||
butterfly_common: {
|
||
name: 'Common Butterfly',
|
||
rarity: 'common',
|
||
habitat: ['meadow', 'forest'],
|
||
season: ['spring', 'summer'],
|
||
price: 50,
|
||
catchDifficulty: 0.3,
|
||
description: 'A beautiful orange and black butterfly.',
|
||
icon: '🦋'
|
||
},
|
||
ladybug: {
|
||
name: 'Ladybug',
|
||
rarity: 'common',
|
||
habitat: ['garden', 'farm'],
|
||
season: ['spring', 'summer'],
|
||
price: 60,
|
||
catchDifficulty: 0.2,
|
||
description: 'Red with black spots. Brings good luck!',
|
||
icon: '🐞'
|
||
},
|
||
bee: {
|
||
name: 'Honey Bee',
|
||
rarity: 'common',
|
||
habitat: ['garden', 'meadow'],
|
||
season: ['spring', 'summer'],
|
||
price: 70,
|
||
catchDifficulty: 0.4,
|
||
description: 'Busy pollinator. Watch out for the sting!',
|
||
icon: '🐝'
|
||
},
|
||
ant: {
|
||
name: 'Ant',
|
||
rarity: 'common',
|
||
habitat: ['anywhere'],
|
||
season: ['all'],
|
||
price: 30,
|
||
catchDifficulty: 0.1,
|
||
description: 'Tiny but strong. Works in colonies.',
|
||
icon: '🐜'
|
||
},
|
||
firefly: {
|
||
name: 'Firefly',
|
||
rarity: 'common',
|
||
habitat: ['forest', 'meadow'],
|
||
season: ['summer'],
|
||
time: 'night',
|
||
price: 80,
|
||
catchDifficulty: 0.3,
|
||
description: 'Glows in the dark. Magical!',
|
||
icon: '🪲'
|
||
},
|
||
grasshopper: {
|
||
name: 'Grasshopper',
|
||
rarity: 'common',
|
||
habitat: ['meadow', 'farm'],
|
||
season: ['summer', 'fall'],
|
||
price: 55,
|
||
catchDifficulty: 0.4,
|
||
description: 'Jumps very high. Hard to catch!',
|
||
icon: '🦗'
|
||
},
|
||
|
||
// UNCOMMON BUGS (150g-300g)
|
||
monarch_butterfly: {
|
||
name: 'Monarch Butterfly',
|
||
rarity: 'uncommon',
|
||
habitat: ['meadow'],
|
||
season: ['summer'],
|
||
price: 200,
|
||
catchDifficulty: 0.5,
|
||
description: 'Iconic orange butterfly. Migrates thousands of miles.',
|
||
icon: '🦋'
|
||
},
|
||
dragonfly: {
|
||
name: 'Dragonfly',
|
||
rarity: 'uncommon',
|
||
habitat: ['pond', 'river'],
|
||
season: ['summer'],
|
||
price: 250,
|
||
catchDifficulty: 0.6,
|
||
description: 'Fast flyer with iridescent wings.',
|
||
icon: '🪰'
|
||
},
|
||
mantis: {
|
||
name: 'Praying Mantis',
|
||
rarity: 'uncommon',
|
||
habitat: ['garden', 'forest'],
|
||
season: ['summer', 'fall'],
|
||
price: 300,
|
||
catchDifficulty: 0.5,
|
||
description: 'Predatory insect. Turns its head!',
|
||
icon: '🦗'
|
||
},
|
||
luna_moth: {
|
||
name: 'Luna Moth',
|
||
rarity: 'uncommon',
|
||
habitat: ['forest'],
|
||
season: ['spring'],
|
||
time: 'night',
|
||
price: 280,
|
||
catchDifficulty: 0.6,
|
||
description: 'Large pale green moth. Rarely seen.',
|
||
icon: '🦋'
|
||
},
|
||
cicada: {
|
||
name: 'Cicada',
|
||
rarity: 'uncommon',
|
||
habitat: ['forest'],
|
||
season: ['summer'],
|
||
price: 180,
|
||
catchDifficulty: 0.4,
|
||
description: 'Very loud! Emerges every 17 years.',
|
||
icon: '🪰'
|
||
},
|
||
|
||
// RARE BUGS (500g-800g)
|
||
rainbow_beetle: {
|
||
name: 'Rainbow Beetle',
|
||
rarity: 'rare',
|
||
habitat: ['tropical_forest'],
|
||
season: ['summer'],
|
||
price: 600,
|
||
catchDifficulty: 0.7,
|
||
description: 'Shimmers with all colors of the rainbow.',
|
||
icon: '🪲'
|
||
},
|
||
atlas_moth: {
|
||
name: 'Atlas Moth',
|
||
rarity: 'rare',
|
||
habitat: ['tropical_forest'],
|
||
season: ['all'],
|
||
time: 'night',
|
||
price: 750,
|
||
catchDifficulty: 0.8,
|
||
description: 'One of the largest moths in the world!',
|
||
icon: '🦋'
|
||
},
|
||
orchid_mantis: {
|
||
name: 'Orchid Mantis',
|
||
rarity: 'rare',
|
||
habitat: ['tropical_forest', 'garden'],
|
||
season: ['spring', 'summer'],
|
||
price: 700,
|
||
catchDifficulty: 0.75,
|
||
description: 'Looks exactly like an orchid flower!',
|
||
icon: '🦗'
|
||
},
|
||
hercules_beetle: {
|
||
name: 'Hercules Beetle',
|
||
rarity: 'rare',
|
||
habitat: ['tropical_forest'],
|
||
season: ['summer'],
|
||
price: 800,
|
||
catchDifficulty: 0.7,
|
||
description: 'Massive beetle with two horns. Very strong!',
|
||
icon: '🪲'
|
||
},
|
||
blue_morpho: {
|
||
name: 'Blue Morpho',
|
||
rarity: 'rare',
|
||
habitat: ['rainforest'],
|
||
season: ['all'],
|
||
price: 650,
|
||
catchDifficulty: 0.75,
|
||
description: 'Brilliant blue wings that shimmer.',
|
||
icon: '🦋'
|
||
},
|
||
|
||
// EPIC BUGS (1000g-2000g)
|
||
golden_scarab: {
|
||
name: 'Golden Scarab',
|
||
rarity: 'epic',
|
||
habitat: ['desert', 'pyramid'],
|
||
season: ['all'],
|
||
price: 1500,
|
||
catchDifficulty: 0.85,
|
||
description: 'Sacred beetle of ancient Egypt. Pure gold shell!',
|
||
icon: '🪲'
|
||
},
|
||
ghost_moth: {
|
||
name: 'Ghost Moth',
|
||
rarity: 'epic',
|
||
habitat: ['haunted_forest'],
|
||
season: ['fall'],
|
||
time: 'night',
|
||
price: 1200,
|
||
catchDifficulty: 0.9,
|
||
description: 'Translucent white. Some say it carries souls...',
|
||
icon: '🦋'
|
||
},
|
||
crystal_dragonfly: {
|
||
name: 'Crystal Dragonfly',
|
||
rarity: 'epic',
|
||
habitat: ['crystal_cave'],
|
||
season: ['all'],
|
||
price: 1800,
|
||
catchDifficulty: 0.85,
|
||
description: 'Wings made of living crystal. Reflects light beautifully.',
|
||
icon: '🪰'
|
||
},
|
||
shadow_beetle: {
|
||
name: 'Shadow Beetle',
|
||
rarity: 'epic',
|
||
habitat: ['dark_forest', 'cave'],
|
||
season: ['all'],
|
||
time: 'night',
|
||
price: 1400,
|
||
catchDifficulty: 0.8,
|
||
description: 'Black as night. Nearly invisible in darkness.',
|
||
icon: '🪲'
|
||
},
|
||
|
||
// LEGENDARY BUGS (3000g-10000g)
|
||
phoenix_butterfly: {
|
||
name: 'Phoenix Butterfly',
|
||
rarity: 'legendary',
|
||
habitat: ['volcano'],
|
||
season: ['summer'],
|
||
price: 5000,
|
||
catchDifficulty: 0.95,
|
||
description: 'Wings glow like fire! Reborn from flames.',
|
||
icon: '🦋'
|
||
},
|
||
void_moth: {
|
||
name: 'Void Moth',
|
||
rarity: 'legendary',
|
||
habitat: ['void_dimension'],
|
||
season: ['all'],
|
||
time: 'night',
|
||
price: 10000,
|
||
catchDifficulty: 0.99,
|
||
description: 'Exists between dimensions. Touch opens portal to void.',
|
||
icon: '🦋'
|
||
},
|
||
celestial_beetle: {
|
||
name: 'Celestial Beetle',
|
||
rarity: 'legendary',
|
||
habitat: ['sky_island'],
|
||
season: ['all'],
|
||
price: 8000,
|
||
catchDifficulty: 0.97,
|
||
description: 'Shell contains entire constellations. Flies among stars.',
|
||
icon: '🪲'
|
||
},
|
||
time_cicada: {
|
||
name: 'Time Cicada',
|
||
rarity: 'legendary',
|
||
habitat: ['chrono_temple'],
|
||
season: ['all'],
|
||
price: 7500,
|
||
catchDifficulty: 0.96,
|
||
description: 'Exists outside of time. Emerges once per millennium.',
|
||
icon: '🪰'
|
||
}
|
||
};
|
||
|
||
console.log('🦋 Bug Catching System initialized!');
|
||
}
|
||
|
||
/**
|
||
* Equip bug net
|
||
*/
|
||
equipBugNet(tier) {
|
||
if (!this.bugNets[tier]) {
|
||
return { success: false, message: 'Unknown net tier' };
|
||
}
|
||
|
||
this.currentNet = {
|
||
tier: tier,
|
||
...this.bugNets[tier]
|
||
};
|
||
|
||
console.log(`🦋 Equipped ${this.currentNet.name}!`);
|
||
|
||
this.scene.events.emit('notification', {
|
||
title: 'Bug Net Equipped!',
|
||
message: `${this.currentNet.name} ready!`,
|
||
icon: '🦋'
|
||
});
|
||
|
||
return { success: true };
|
||
}
|
||
|
||
/**
|
||
* Attempt to catch a bug
|
||
*/
|
||
catchBug(bugId) {
|
||
if (!this.currentNet) {
|
||
return { success: false, message: 'No bug net equipped!' };
|
||
}
|
||
|
||
const bug = this.bugs[bugId];
|
||
if (!bug) {
|
||
return { success: false, message: 'Unknown bug' };
|
||
}
|
||
|
||
// Calculate catch chance
|
||
const netBonus = this.currentNet.catchRate;
|
||
const bugDifficulty = bug.catchDifficulty;
|
||
const catchChance = netBonus * (1 - bugDifficulty);
|
||
|
||
const roll = Math.random();
|
||
const caught = roll < catchChance;
|
||
|
||
if (caught) {
|
||
// Add to collection
|
||
if (!this.caughtBugs.has(bugId)) {
|
||
this.caughtBugs.set(bugId, 0);
|
||
}
|
||
this.caughtBugs.set(bugId, this.caughtBugs.get(bugId) + 1);
|
||
|
||
// First time catch
|
||
if (!this.bugAlbum.has(bugId)) {
|
||
this.bugAlbum.set(bugId, {
|
||
discoveredAt: new Date(),
|
||
timesСaught: 1
|
||
});
|
||
|
||
this.scene.events.emit('notification', {
|
||
title: 'NEW BUG!',
|
||
message: `${bug.icon} ${bug.name} added to album!`,
|
||
icon: '📔'
|
||
});
|
||
}
|
||
|
||
console.log(`🦋 Caught ${bug.name}!`);
|
||
|
||
this.scene.events.emit('notification', {
|
||
title: 'Bug Caught!',
|
||
message: `${bug.icon} ${bug.name} (+${bug.price}g)`,
|
||
icon: '✨'
|
||
});
|
||
|
||
return {
|
||
success: true,
|
||
bug: bug,
|
||
firstTime: !this.bugAlbum.has(bugId)
|
||
};
|
||
} else {
|
||
console.log(`❌ ${bug.name} escaped!`);
|
||
|
||
this.scene.events.emit('notification', {
|
||
title: 'Escaped!',
|
||
message: `${bug.name} got away!`,
|
||
icon: '💨'
|
||
});
|
||
|
||
return { success: false, message: 'Bug escaped!' };
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Sell bug
|
||
*/
|
||
sellBug(bugId, quantity = 1) {
|
||
const count = this.caughtBugs.get(bugId) || 0;
|
||
|
||
if (count < quantity) {
|
||
return { success: false, message: 'Not enough bugs to sell!' };
|
||
}
|
||
|
||
const bug = this.bugs[bugId];
|
||
const totalPrice = bug.price * quantity;
|
||
|
||
// Remove from inventory
|
||
this.caughtBugs.set(bugId, count - quantity);
|
||
|
||
// Give gold
|
||
if (this.scene.player) {
|
||
this.scene.player.gold += totalPrice;
|
||
}
|
||
|
||
console.log(`💰 Sold ${quantity}x ${bug.name} for ${totalPrice}g!`);
|
||
|
||
this.scene.events.emit('notification', {
|
||
title: 'Bugs Sold!',
|
||
message: `${quantity}x ${bug.name} = ${totalPrice}g`,
|
||
icon: '💰'
|
||
});
|
||
|
||
return { success: true, price: totalPrice };
|
||
}
|
||
|
||
/**
|
||
* Get collection stats
|
||
*/
|
||
getCollectionStats() {
|
||
const totalSpecies = Object.keys(this.bugs).length;
|
||
const discovered = this.bugAlbum.size;
|
||
const percentage = Math.round((discovered / totalSpecies) * 100);
|
||
|
||
return {
|
||
totalSpecies: totalSpecies,
|
||
discovered: discovered,
|
||
percentage: percentage,
|
||
byRarity: this.getByRarity()
|
||
};
|
||
}
|
||
|
||
/**
|
||
* Get bugs by rarity
|
||
*/
|
||
getByRarity() {
|
||
const byRarity = {
|
||
common: { total: 0, caught: 0 },
|
||
uncommon: { total: 0, caught: 0 },
|
||
rare: { total: 0, caught: 0 },
|
||
epic: { total: 0, caught: 0 },
|
||
legendary: { total: 0, caught: 0 }
|
||
};
|
||
|
||
for (const [bugId, bug] of Object.entries(this.bugs)) {
|
||
byRarity[bug.rarity].total++;
|
||
if (this.bugAlbum.has(bugId)) {
|
||
byRarity[bug.rarity].caught++;
|
||
}
|
||
}
|
||
|
||
return byRarity;
|
||
}
|
||
|
||
/**
|
||
* Spawn bugs in world
|
||
*/
|
||
spawnBugs(biome, season, time, count = 5) {
|
||
const availableBugs = Object.entries(this.bugs)
|
||
.filter(([id, bug]) => {
|
||
// Check habitat
|
||
if (!bug.habitat.includes(biome) && !bug.habitat.includes('anywhere')) {
|
||
return false;
|
||
}
|
||
// Check season
|
||
if (!bug.season.includes(season) && !bug.season.includes('all')) {
|
||
return false;
|
||
}
|
||
// Check time
|
||
if (bug.time && bug.time !== time) {
|
||
return false;
|
||
}
|
||
return true;
|
||
});
|
||
|
||
const spawned = [];
|
||
|
||
for (let i = 0; i < count; i++) {
|
||
if (availableBugs.length === 0) break;
|
||
|
||
const [bugId, bug] = availableBugs[Math.floor(Math.random() * availableBugs.length)];
|
||
|
||
const x = Math.random() * 800; // Map width
|
||
const y = Math.random() * 600; // Map height
|
||
|
||
spawned.push({
|
||
id: `bug_${Date.now()}_${i}`,
|
||
bugId: bugId,
|
||
x: x,
|
||
y: y,
|
||
active: true
|
||
});
|
||
}
|
||
|
||
this.activeBugs.push(...spawned);
|
||
|
||
console.log(`🦋 Spawned ${spawned.length} bugs in ${biome}`);
|
||
|
||
return spawned;
|
||
}
|
||
|
||
/**
|
||
* Check collection completion bonuses
|
||
*/
|
||
checkCompletionBonus() {
|
||
const stats = this.getCollectionStats();
|
||
|
||
// 100% completion
|
||
if (stats.percentage === 100 && !this.completionBonusGiven) {
|
||
this.completionBonusGiven = true;
|
||
|
||
this.scene.events.emit('notification', {
|
||
title: '🎉 BUG MASTER!',
|
||
message: 'Completed entire bug collection! +10000g bonus!',
|
||
icon: '🏆'
|
||
});
|
||
|
||
if (this.scene.player) {
|
||
this.scene.player.gold += 10000;
|
||
}
|
||
|
||
return true;
|
||
}
|
||
|
||
return false;
|
||
}
|
||
}
|