317 lines
9.1 KiB
JavaScript
317 lines
9.1 KiB
JavaScript
/**
|
|
* SCHOOL BUFF SYSTEM
|
|
* Learning skills from Teacher NPC
|
|
* Temporary and permanent buffs
|
|
*/
|
|
|
|
export class SchoolBuffSystem {
|
|
constructor(scene) {
|
|
this.scene = scene;
|
|
|
|
// Available lessons
|
|
this.lessons = new Map();
|
|
this.learnedSkills = new Set();
|
|
|
|
// Active buffs
|
|
this.activeBuffs = new Map();
|
|
|
|
// Teacher NPC reference
|
|
this.teacher = null;
|
|
|
|
this.init();
|
|
}
|
|
|
|
init() {
|
|
this.initializeLessons();
|
|
}
|
|
|
|
/**
|
|
* Initialize all available lessons
|
|
*/
|
|
initializeLessons() {
|
|
// FARMING LESSONS
|
|
this.registerLesson({
|
|
id: 'basic_farming',
|
|
name: 'Basic Farming',
|
|
category: 'farming',
|
|
cost: 100,
|
|
duration: 'permanent',
|
|
description: '+10% crop yield',
|
|
effect: () => this.scene.gameState.buffs.crop_yield = (this.scene.gameState.buffs.crop_yield || 1.0) * 1.1
|
|
});
|
|
|
|
this.registerLesson({
|
|
id: 'advanced_farming',
|
|
name: 'Advanced Farming',
|
|
category: 'farming',
|
|
cost: 500,
|
|
requires: 'basic_farming',
|
|
duration: 'permanent',
|
|
description: '+20% crop growth speed',
|
|
effect: () => this.scene.gameState.buffs.crop_growth_speed = (this.scene.gameState.buffs.crop_growth_speed || 1.0) * 1.2
|
|
});
|
|
|
|
this.registerLesson({
|
|
id: 'fertilizer_mastery',
|
|
name: 'Fertilizer Mastery',
|
|
category: 'farming',
|
|
cost: 300,
|
|
duration: 'permanent',
|
|
description: 'Fertilizer lasts 2x longer',
|
|
effect: () => this.scene.gameState.buffs.fertilizer_duration = 2.0
|
|
});
|
|
|
|
// COMBAT LESSONS
|
|
this.registerLesson({
|
|
id: 'basic_combat',
|
|
name: 'Basic Combat',
|
|
category: 'combat',
|
|
cost: 200,
|
|
duration: 'permanent',
|
|
description: '+5 damage to all attacks',
|
|
effect: () => this.scene.player.attackDamage += 5
|
|
});
|
|
|
|
this.registerLesson({
|
|
id: 'defense_training',
|
|
name: 'Defense Training',
|
|
category: 'combat',
|
|
cost: 400,
|
|
duration: 'permanent',
|
|
description: '+15% damage resistance',
|
|
effect: () => this.scene.player.damageResistance = (this.scene.player.damageResistance || 0) + 0.15
|
|
});
|
|
|
|
this.registerLesson({
|
|
id: 'weapon_mastery',
|
|
name: 'Weapon Mastery',
|
|
category: 'combat',
|
|
cost: 800,
|
|
requires: 'basic_combat',
|
|
duration: 'permanent',
|
|
description: '+20% critical hit chance',
|
|
effect: () => this.scene.player.critChance = (this.scene.player.critChance || 0) + 0.2
|
|
});
|
|
|
|
// SURVIVAL LESSONS
|
|
this.registerLesson({
|
|
id: 'herbalism',
|
|
name: 'Herbalism',
|
|
category: 'survival',
|
|
cost: 250,
|
|
duration: 'permanent',
|
|
description: 'Healing items restore 50% more HP',
|
|
effect: () => this.scene.gameState.buffs.healing_bonus = 1.5
|
|
});
|
|
|
|
this.registerLesson({
|
|
id: 'scavenging',
|
|
name: 'Scavenging',
|
|
category: 'survival',
|
|
cost: 350,
|
|
duration: 'permanent',
|
|
description: '+25% loot from containers',
|
|
effect: () => this.scene.gameState.buffs.loot_bonus = 1.25
|
|
});
|
|
|
|
this.registerLesson({
|
|
id: 'endurance',
|
|
name: 'Endurance Training',
|
|
category: 'survival',
|
|
cost: 600,
|
|
duration: 'permanent',
|
|
description: '+20 max stamina',
|
|
effect: () => this.scene.player.maxStamina += 20
|
|
});
|
|
|
|
// TEMPORARY BUFFS (Study Sessions)
|
|
this.registerLesson({
|
|
id: 'focus_boost',
|
|
name: 'Focus Boost',
|
|
category: 'temporary',
|
|
cost: 50,
|
|
duration: 300000, // 5 minutes
|
|
description: '+50% XP gain for 5 minutes',
|
|
effect: () => this.applyTemporaryBuff('xp_boost', 1.5, 300000)
|
|
});
|
|
|
|
this.registerLesson({
|
|
id: 'energy_surge',
|
|
name: 'Energy Surge',
|
|
category: 'temporary',
|
|
cost: 75,
|
|
duration: 180000, // 3 minutes
|
|
description: '+100% stamina regen for 3 minutes',
|
|
effect: () => this.applyTemporaryBuff('stamina_regen', 2.0, 180000)
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Register a lesson
|
|
*/
|
|
registerLesson(lessonData) {
|
|
this.lessons.set(lessonData.id, {
|
|
...lessonData,
|
|
learned: false
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Learn a skill from Teacher
|
|
*/
|
|
learnSkill(lessonId) {
|
|
const lesson = this.lessons.get(lessonId);
|
|
if (!lesson) return false;
|
|
|
|
// Check if already learned (permanent skills only)
|
|
if (lesson.duration === 'permanent' && lesson.learned) {
|
|
console.warn(`Already learned: ${lesson.name}`);
|
|
return false;
|
|
}
|
|
|
|
// Check prerequisites
|
|
if (lesson.requires && !this.learnedSkills.has(lesson.requires)) {
|
|
const required = this.lessons.get(lesson.requires);
|
|
console.warn(`Must learn ${required.name} first`);
|
|
return false;
|
|
}
|
|
|
|
// Check cost
|
|
const currency = this.scene.economySystem?.getCurrency() || 0;
|
|
if (currency < lesson.cost) {
|
|
console.warn(`Insufficient funds: need ${lesson.cost}, have ${currency}`);
|
|
return false;
|
|
}
|
|
|
|
// Pay cost
|
|
this.scene.economySystem.addCurrency(-lesson.cost);
|
|
|
|
// Apply effect
|
|
lesson.effect();
|
|
|
|
// Mark as learned
|
|
if (lesson.duration === 'permanent') {
|
|
lesson.learned = true;
|
|
this.learnedSkills.add(lessonId);
|
|
}
|
|
|
|
// Notification
|
|
this.scene.uiSystem?.showNotification(
|
|
`Learned: ${lesson.name}!`,
|
|
'success',
|
|
{ description: lesson.description }
|
|
);
|
|
|
|
// Teacher dialogue
|
|
this.scene.dialogueSystem?.startDialogue('teacher', 'lesson_complete', { skill: lesson.name });
|
|
|
|
console.log(`📚 Learned: ${lesson.name} (-${lesson.cost} coins)`);
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Apply temporary buff
|
|
*/
|
|
applyTemporaryBuff(buffId, multiplier, duration) {
|
|
// Store buff
|
|
this.activeBuffs.set(buffId, {
|
|
multiplier,
|
|
expiresAt: Date.now() + duration
|
|
});
|
|
|
|
// VFX
|
|
this.scene.vfxSystem?.playEffect('buff_applied', this.scene.player.x, this.scene.player.y);
|
|
|
|
// Remove after duration
|
|
this.scene.time.delayedCall(duration, () => {
|
|
this.activeBuffs.delete(buffId);
|
|
this.scene.uiSystem?.showNotification(`${buffId} expired`, 'info');
|
|
console.log(`⏱️ Buff expired: ${buffId}`);
|
|
});
|
|
|
|
console.log(`✨ Applied buff: ${buffId} (${duration / 1000}s)`);
|
|
}
|
|
|
|
/**
|
|
* Check if buff is active
|
|
*/
|
|
hasActiveBuff(buffId) {
|
|
const buff = this.activeBuffs.get(buffId);
|
|
if (!buff) return false;
|
|
|
|
const now = Date.now();
|
|
if (now > buff.expiresAt) {
|
|
this.activeBuffs.delete(buffId);
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Get buff multiplier
|
|
*/
|
|
getBuffMultiplier(buffId) {
|
|
const buff = this.activeBuffs.get(buffId);
|
|
return buff ? buff.multiplier : 1.0;
|
|
}
|
|
|
|
/**
|
|
* Get lessons by category
|
|
*/
|
|
getLessonsByCategory(category) {
|
|
return Array.from(this.lessons.values()).filter(l => l.category === category);
|
|
}
|
|
|
|
/**
|
|
* Get available lessons (can be learned now)
|
|
*/
|
|
getAvailableLessons() {
|
|
return Array.from(this.lessons.values()).filter(l => {
|
|
if (l.duration === 'permanent' && l.learned) return false;
|
|
if (l.requires && !this.learnedSkills.has(l.requires)) return false;
|
|
return true;
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Get learned skills
|
|
*/
|
|
getLearnedSkills() {
|
|
return Array.from(this.lessons.values()).filter(l => l.learned);
|
|
}
|
|
|
|
/**
|
|
* Save/Load
|
|
*/
|
|
getSaveData() {
|
|
return {
|
|
learnedSkills: Array.from(this.learnedSkills),
|
|
activeBuffs: Array.from(this.activeBuffs.entries())
|
|
};
|
|
}
|
|
|
|
loadSaveData(data) {
|
|
this.learnedSkills = new Set(data.learnedSkills || []);
|
|
|
|
// Mark lessons as learned
|
|
this.learnedSkills.forEach(skillId => {
|
|
const lesson = this.lessons.get(skillId);
|
|
if (lesson) {
|
|
lesson.learned = true;
|
|
lesson.effect(); // Re-apply permanent effects
|
|
}
|
|
});
|
|
|
|
// Restore active buffs
|
|
if (data.activeBuffs) {
|
|
data.activeBuffs.forEach(([buffId, buffData]) => {
|
|
const remaining = buffData.expiresAt - Date.now();
|
|
if (remaining > 0) {
|
|
this.applyTemporaryBuff(buffId, buffData.multiplier, remaining);
|
|
}
|
|
});
|
|
}
|
|
}
|
|
}
|