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