PHASE 20 COMPLETE: Achievement System - auto-tracking, fancy popups, 8 achievements (harvest, gold, kills, days, etc)
This commit is contained in:
@@ -111,6 +111,7 @@
|
|||||||
<script src="src/systems/PerennialCropSystem.js"></script>
|
<script src="src/systems/PerennialCropSystem.js"></script>
|
||||||
<script src="src/systems/MountSystem.js"></script>
|
<script src="src/systems/MountSystem.js"></script>
|
||||||
<script src="src/systems/SteamIntegrationSystem.js"></script>
|
<script src="src/systems/SteamIntegrationSystem.js"></script>
|
||||||
|
<script src="src/systems/AchievementTriggers.js"></script>
|
||||||
<script src="src/systems/StarterChestSystem.js"></script>
|
<script src="src/systems/StarterChestSystem.js"></script>
|
||||||
<script src="src/systems/GemDropSystem.js"></script>
|
<script src="src/systems/GemDropSystem.js"></script>
|
||||||
|
|
||||||
|
|||||||
321
src/systems/AchievementTriggers.js
Normal file
321
src/systems/AchievementTriggers.js
Normal file
@@ -0,0 +1,321 @@
|
|||||||
|
/**
|
||||||
|
* ACHIEVEMENT TRIGGERS
|
||||||
|
* Automatically tracks game events and unlocks achievements
|
||||||
|
* Connects gameplay to Steam/local achievements
|
||||||
|
*/
|
||||||
|
|
||||||
|
class AchievementTriggers {
|
||||||
|
constructor(scene) {
|
||||||
|
this.scene = scene;
|
||||||
|
this.steamIntegration = scene.steamIntegration || new SteamIntegrationSystem();
|
||||||
|
this.steamIntegration.scene = scene; // Link scene for notifications
|
||||||
|
|
||||||
|
// Progress tracking
|
||||||
|
this.trackers = {
|
||||||
|
harvestCount: 0,
|
||||||
|
goldEarned: 0,
|
||||||
|
zombiesKilled: 0,
|
||||||
|
islandsDiscovered: 0,
|
||||||
|
daysSurvived: 0,
|
||||||
|
greenhouseBuilt: false,
|
||||||
|
zombiesTamed: 0
|
||||||
|
};
|
||||||
|
|
||||||
|
// Load saved progress
|
||||||
|
this.loadProgress();
|
||||||
|
|
||||||
|
// Register event listeners
|
||||||
|
this.registerListeners();
|
||||||
|
|
||||||
|
console.log('🏆 Achievement Triggers initialized');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register event listeners for achievements
|
||||||
|
*/
|
||||||
|
registerListeners() {
|
||||||
|
const scene = this.scene;
|
||||||
|
|
||||||
|
// Listen to game events
|
||||||
|
if (scene.events) {
|
||||||
|
// Harvest event
|
||||||
|
scene.events.on('crop-harvested', (cropType) => {
|
||||||
|
this.onHarvest(cropType);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Gold earned event
|
||||||
|
scene.events.on('gold-earned', (amount) => {
|
||||||
|
this.onGoldEarned(amount);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Enemy killed event
|
||||||
|
scene.events.on('enemy-killed', (enemyType) => {
|
||||||
|
this.onEnemyKilled(enemyType);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Building placed event
|
||||||
|
scene.events.on('building-placed', (buildingType) => {
|
||||||
|
this.onBuildingPlaced(buildingType);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Day changed event
|
||||||
|
scene.events.on('day-changed', (dayNumber) => {
|
||||||
|
this.onDayChanged(dayNumber);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Island discovered event
|
||||||
|
scene.events.on('island-discovered', () => {
|
||||||
|
this.onIslandDiscovered();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Zombie tamed event
|
||||||
|
scene.events.on('zombie-tamed', () => {
|
||||||
|
this.onZombieTamed();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Event: Crop harvested
|
||||||
|
*/
|
||||||
|
onHarvest(cropType) {
|
||||||
|
this.trackers.harvestCount++;
|
||||||
|
console.log(`🌾 Harvest count: ${this.trackers.harvestCount}`);
|
||||||
|
|
||||||
|
// FIRST_HARVEST
|
||||||
|
if (this.trackers.harvestCount === 1) {
|
||||||
|
this.unlockAchievement('FIRST_HARVEST');
|
||||||
|
}
|
||||||
|
|
||||||
|
// MASTER_FARMER
|
||||||
|
if (this.trackers.harvestCount >= 1000) {
|
||||||
|
this.unlockAchievement('MASTER_FARMER');
|
||||||
|
}
|
||||||
|
|
||||||
|
this.saveProgress();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Event: Gold earned
|
||||||
|
*/
|
||||||
|
onGoldEarned(amount) {
|
||||||
|
this.trackers.goldEarned += amount;
|
||||||
|
console.log(`💰 Total gold earned: ${this.trackers.goldEarned}`);
|
||||||
|
|
||||||
|
// GOLD_RUSH
|
||||||
|
if (this.trackers.goldEarned >= 1000) {
|
||||||
|
this.unlockAchievement('GOLD_RUSH');
|
||||||
|
}
|
||||||
|
|
||||||
|
this.saveProgress();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Event: Enemy killed
|
||||||
|
*/
|
||||||
|
onEnemyKilled(enemyType) {
|
||||||
|
if (enemyType === 'zombie' || enemyType === 'elite_zombie') {
|
||||||
|
this.trackers.zombiesKilled++;
|
||||||
|
console.log(`🧟 Zombies killed: ${this.trackers.zombiesKilled}`);
|
||||||
|
|
||||||
|
// ZOMBIE_SLAYER
|
||||||
|
if (this.trackers.zombiesKilled >= 100) {
|
||||||
|
this.unlockAchievement('ZOMBIE_SLAYER');
|
||||||
|
}
|
||||||
|
|
||||||
|
this.saveProgress();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Event: Building placed
|
||||||
|
*/
|
||||||
|
onBuildingPlaced(buildingType) {
|
||||||
|
if (buildingType === 'greenhouse') {
|
||||||
|
this.trackers.greenhouseBuilt = true;
|
||||||
|
this.unlockAchievement('GREENHOUSE');
|
||||||
|
this.saveProgress();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Event: Day changed
|
||||||
|
*/
|
||||||
|
onDayChanged(dayNumber) {
|
||||||
|
this.trackers.daysSurvived = dayNumber;
|
||||||
|
console.log(`📅 Day ${dayNumber}`);
|
||||||
|
|
||||||
|
// DAY_30
|
||||||
|
if (dayNumber >= 30) {
|
||||||
|
this.unlockAchievement('DAY_30');
|
||||||
|
}
|
||||||
|
|
||||||
|
this.saveProgress();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Event: Island discovered
|
||||||
|
*/
|
||||||
|
onIslandDiscovered() {
|
||||||
|
this.trackers.islandsDiscovered++;
|
||||||
|
console.log(`🏝️ Islands discovered: ${this.trackers.islandsDiscovered}`);
|
||||||
|
|
||||||
|
// OCEAN_EXPLORER
|
||||||
|
if (this.trackers.islandsDiscovered >= 5) {
|
||||||
|
this.unlockAchievement('OCEAN_EXPLORER');
|
||||||
|
}
|
||||||
|
|
||||||
|
this.saveProgress();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Event: Zombie tamed
|
||||||
|
*/
|
||||||
|
onZombieTamed() {
|
||||||
|
this.trackers.zombiesTamed++;
|
||||||
|
console.log(`🧟♂️ Zombies tamed: ${this.trackers.zombiesTamed}`);
|
||||||
|
|
||||||
|
// TAMED_ZOMBIE
|
||||||
|
if (this.trackers.zombiesTamed >= 1) {
|
||||||
|
this.unlockAchievement('TAMED_ZOMBIE');
|
||||||
|
}
|
||||||
|
|
||||||
|
this.saveProgress();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unlock achievement through Steam Integration
|
||||||
|
*/
|
||||||
|
unlockAchievement(achievementId) {
|
||||||
|
const unlocked = this.steamIntegration.unlockAchievement(achievementId);
|
||||||
|
|
||||||
|
if (unlocked) {
|
||||||
|
// Show fancy notification
|
||||||
|
this.showAchievementNotification(achievementId);
|
||||||
|
|
||||||
|
// Play sound effect
|
||||||
|
if (this.scene.soundManager) {
|
||||||
|
this.scene.soundManager.playSuccess();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show achievement unlock notification
|
||||||
|
*/
|
||||||
|
showAchievementNotification(achievementId) {
|
||||||
|
const achievement = this.steamIntegration.achievementDefs[achievementId];
|
||||||
|
if (!achievement) return;
|
||||||
|
|
||||||
|
// Emit to UI Scene for fancy popup
|
||||||
|
if (this.scene.scene && this.scene.scene.get('UIScene')) {
|
||||||
|
const uiScene = this.scene.scene.get('UIScene');
|
||||||
|
|
||||||
|
// Create achievement popup
|
||||||
|
const popup = uiScene.add.container(uiScene.cameras.main.width / 2, 100);
|
||||||
|
popup.setScrollFactor(0);
|
||||||
|
popup.setDepth(100000);
|
||||||
|
|
||||||
|
// Background
|
||||||
|
const bg = uiScene.add.rectangle(0, 0, 350, 80, 0x1a1a1a, 0.95);
|
||||||
|
bg.setStrokeStyle(3, 0xffd700);
|
||||||
|
|
||||||
|
// Trophy icon
|
||||||
|
const icon = uiScene.add.text(-150, 0, '🏆', {
|
||||||
|
fontSize: '48px'
|
||||||
|
});
|
||||||
|
icon.setOrigin(0.5);
|
||||||
|
|
||||||
|
// Title
|
||||||
|
const title = uiScene.add.text(-50, -15, 'ACHIEVEMENT UNLOCKED!', {
|
||||||
|
fontFamily: 'Courier New',
|
||||||
|
fontSize: '14px',
|
||||||
|
color: '#ffd700',
|
||||||
|
fontStyle: 'bold'
|
||||||
|
});
|
||||||
|
title.setOrigin(0, 0.5);
|
||||||
|
|
||||||
|
// Achievement name
|
||||||
|
const name = uiScene.add.text(-50, 10, achievement.name, {
|
||||||
|
fontFamily: 'Courier New',
|
||||||
|
fontSize: '18px',
|
||||||
|
color: '#ffffff',
|
||||||
|
fontStyle: 'bold'
|
||||||
|
});
|
||||||
|
name.setOrigin(0, 0.5);
|
||||||
|
|
||||||
|
popup.add([bg, icon, title, name]);
|
||||||
|
|
||||||
|
// Animate in
|
||||||
|
popup.setAlpha(0);
|
||||||
|
popup.y = 50;
|
||||||
|
|
||||||
|
uiScene.tweens.add({
|
||||||
|
targets: popup,
|
||||||
|
alpha: 1,
|
||||||
|
y: 100,
|
||||||
|
duration: 500,
|
||||||
|
ease: 'Back.easeOut'
|
||||||
|
});
|
||||||
|
|
||||||
|
// Animate out after delay
|
||||||
|
uiScene.tweens.add({
|
||||||
|
targets: popup,
|
||||||
|
alpha: 0,
|
||||||
|
y: 50,
|
||||||
|
duration: 500,
|
||||||
|
delay: 4000,
|
||||||
|
onComplete: () => {
|
||||||
|
popup.destroy();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Save progress to localStorage
|
||||||
|
*/
|
||||||
|
saveProgress() {
|
||||||
|
localStorage.setItem('novafarma_achievement_progress', JSON.stringify(this.trackers));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load progress from localStorage
|
||||||
|
*/
|
||||||
|
loadProgress() {
|
||||||
|
const saved = localStorage.getItem('novafarma_achievement_progress');
|
||||||
|
if (saved) {
|
||||||
|
try {
|
||||||
|
const loaded = JSON.parse(saved);
|
||||||
|
this.trackers = { ...this.trackers, ...loaded };
|
||||||
|
console.log('📊 Achievement progress loaded:', this.trackers);
|
||||||
|
} catch (e) {
|
||||||
|
console.error('Failed to load achievement progress:', e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get current progress for UI display
|
||||||
|
*/
|
||||||
|
getProgress() {
|
||||||
|
return {
|
||||||
|
...this.trackers,
|
||||||
|
achievements: {
|
||||||
|
FIRST_HARVEST: this.trackers.harvestCount >= 1,
|
||||||
|
GOLD_RUSH: this.trackers.goldEarned >= 1000,
|
||||||
|
ZOMBIE_SLAYER: this.trackers.zombiesKilled >= 100,
|
||||||
|
MASTER_FARMER: this.trackers.harvestCount >= 1000,
|
||||||
|
DAY_30: this.trackers.daysSurvived >= 30,
|
||||||
|
GREENHOUSE: this.trackers.greenhouseBuilt,
|
||||||
|
TAMED_ZOMBIE: this.trackers.zombiesTamed >= 1,
|
||||||
|
OCEAN_EXPLORER: this.trackers.islandsDiscovered >= 5
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make globally available
|
||||||
|
window.AchievementTriggers = AchievementTriggers;
|
||||||
|
|
||||||
|
console.log('🏆 AchievementTriggers loaded');
|
||||||
Reference in New Issue
Block a user