📚 DOCUMENTATION COMPLETE: AUDIO_ASSET_MANIFEST.md (61 files detailed) and VFX_IMPLEMENTATION_GUIDE.md (6 systems with code examples). Ready for asset production phase.

This commit is contained in:
2026-01-05 19:29:14 +01:00
parent 370c527fcd
commit 1e74086fa3
10 changed files with 2168 additions and 4 deletions

View File

@@ -0,0 +1,179 @@
/**
* CITY GRATITUDE QUEST DATA
* Related to CityGratitudeSystem and NPCSettlementSystem
*/
export const CityGratitudeQuests = {
// QUEST 1: Growing Community
growing_community: {
id: 'growing_community',
name: 'Growing Community',
category: 'city',
npc: 'mayor',
description: 'Attract 10 settlers to build a small community.',
objectives: [
{
type: 'population',
target: 10,
description: 'Reach 10 population'
}
],
rewards: {
xp: 500,
currency: 1000,
items: [
{ id: 'community_hoe', amount: 1 },
{ id: 'welcome_banner', amount: 1 }
],
reputation: 50,
gratitudeTier: 1
},
dialogue: {
start: 'mayor_growing_community_start',
complete: 'mayor_growing_community_complete'
},
autoComplete: true // Auto-completes when population reached
},
// QUEST 2: Village Leader
village_leader: {
id: 'village_leader',
name: 'Village Leader',
category: 'city',
npc: 'mayor',
requires: 'growing_community',
description: 'Grow your settlement to 25 people and unlock the Town Hall.',
objectives: [
{
type: 'population',
target: 25,
description: 'Reach 25 population'
},
{
type: 'build_structure',
target: 'town_hall',
description: 'Build the Town Hall'
}
],
rewards: {
xp: 1500,
currency: 3000,
items: [
{ id: 'village_axe', amount: 1 },
{ id: 'mayor_blessing', amount: 1 }
],
reputation: 100,
gratitudeTier: 2,
unlocks: ['town_hall', 'village_services']
},
dialogue: {
start: 'mayor_village_leader_start',
complete: 'mayor_village_leader_complete'
}
},
// QUEST 3: City Builder
city_builder: {
id: 'city_builder',
name: 'City Builder',
category: 'city',
npc: 'mayor',
requires: 'village_leader',
description: 'Transform your village into a thriving city of 100 people.',
objectives: [
{
type: 'population',
target: 100,
description: 'Reach 100 population'
},
{
type: 'build_structure',
target: 'advanced_workshop',
description: 'Build advanced workshop'
},
{
type: 'settler_happiness',
target: 75,
description: 'Maintain 75% average settler happiness'
}
],
rewards: {
xp: 5000,
currency: 15000,
items: [
{ id: 'legendary_pickaxe', amount: 1 },
{ id: 'city_crown', amount: 1 },
{ id: 'citizens_gratitude', amount: 1 }
],
reputation: 500,
gratitudeTier: 3,
achievement: 'city_builder',
unlocks: ['city_monument'],
permanentBuff: {
name: 'Citizens\' Eternal Gratitude',
effect: '+25% all production and efficiency'
}
},
dialogue: {
start: 'mayor_city_builder_start',
progress: 'mayor_city_builder_progress',
complete: 'mayor_city_builder_complete'
}
},
// QUEST 4: Metropolis King
metropolis_king: {
id: 'metropolis_king',
name: 'Metropolis King',
category: 'city',
npc: 'mayor',
requires: 'city_builder',
description: 'Build a legendary metropolis of 200 people. The ultimate achievement!',
objectives: [
{
type: 'population',
target: 200,
description: 'Reach 200 population'
},
{
type: 'build_structure',
target: 'palace',
description: 'Build the Palace'
},
{
type: 'city_reputation',
target: 1000,
description: 'Reach 1000 city reputation'
},
{
type: 'all_services_active',
description: 'Have all city services operational'
}
],
rewards: {
xp: 10000,
currency: 50000,
items: [
{ id: 'omega_tool_set', amount: 1 },
{ id: 'metropolis_throne', amount: 1 },
{ id: 'eternal_crown', amount: 1 }
],
reputation: 1000,
gratitudeTier: 4,
achievement: 'metropolis_king',
unlocks: ['palace', 'royal_services'],
permanentBuff: {
name: 'King\'s Authority',
effect: 'All workers +100% efficiency, unlimited building queue'
},
specialBonus: 'Unlock New Game+ mode'
},
dialogue: {
start: 'mayor_metropolis_king_start',
progress: 'mayor_metropolis_king_progress',
complete: 'mayor_metropolis_king_complete',
special: 'mayor_metropolis_king_coronation' // Special coronation cutscene
},
cutscene: 'coronation_ceremony'
}
};

142
src/quests/DefenseQuests.js Normal file
View File

@@ -0,0 +1,142 @@
/**
* DEFENSE QUEST DATA
* Related to FarmRaidSystem and DefenseSystem
*/
export const DefenseQuests = {
// QUEST 1: First Defense
first_defense: {
id: 'first_defense',
name: 'First Blood',
category: 'defense',
npc: 'mayor',
description: 'Your farm is under attack! Defend against the first raider wave.',
objectives: [
{
type: 'survive_raid',
target: 1,
description: 'Survive the first raid'
}
],
rewards: {
xp: 300,
currency: 500,
items: [
{ id: 'basic_weapon', amount: 1 },
{ id: 'defense_plans', amount: 1 }
],
unlocks: ['defense_system']
},
dialogue: {
start: 'mayor_first_defense_start',
complete: 'mayor_first_defense_complete'
},
autoStart: true, // Triggers automatically on first raid
priority: 'urgent'
},
// QUEST 2: Build Walls
build_walls: {
id: 'build_walls',
name: 'Fortify the Farm',
category: 'defense',
npc: 'mayor',
requires: 'first_defense',
description: 'Build wooden walls around your farm to improve defenses.',
objectives: [
{
type: 'build_structure',
target: 'wooden_wall',
amount: 20,
description: 'Build 20 wooden wall segments'
}
],
rewards: {
xp: 500,
currency: 1000,
items: [{ id: 'wall_upgrade_plans', amount: 1 }],
unlocks: ['stone_walls']
},
dialogue: {
start: 'mayor_walls_start',
complete: 'mayor_walls_complete'
}
},
// QUEST 3: Raid Master
raid_master: {
id: 'raid_master',
name: 'Raid Master',
category: 'defense',
npc: 'mayor',
requires: 'build_walls',
description: 'Successfully defend against 5 raids without losing any buildings.',
objectives: [
{
type: 'defend_raids',
amount: 5,
condition: 'no_building_loss',
description: 'Defend 5 raids with 0 building losses'
}
],
rewards: {
xp: 2000,
currency: 5000,
items: [
{ id: 'fortress_plans', amount: 1 },
{ id: 'defender_medal', amount: 1 }
],
achievement: 'raid_master',
reputation: 200
},
dialogue: {
start: 'mayor_raid_master_start',
complete: 'mayor_raid_master_complete'
}
},
// QUEST 4: Ultimate Defense
ultimate_defense: {
id: 'ultimate_defense',
name: 'Impenetrable Fortress',
category: 'defense',
npc: 'mayor',
requires: 'raid_master',
description: 'Build the ultimate defense: stone walls, watchtowers, and fortress gates.',
objectives: [
{
type: 'build_structure',
target: 'stone_wall',
amount: 40,
description: 'Build 40 stone wall segments'
},
{
type: 'build_structure',
target: 'watchtower',
amount: 4,
description: 'Build 4 watchtowers'
},
{
type: 'build_structure',
target: 'fortress_gate',
amount: 1,
description: 'Build 1 fortress gate'
}
],
rewards: {
xp: 5000,
currency: 15000,
items: [
{ id: 'legendary_fortress_blueprint', amount: 1 },
{ id: 'general_armor', amount: 1 }
],
achievement: 'impenetrable_fortress',
reputation: 500,
specialBonus: 'Raids 50% less likely'
},
dialogue: {
start: 'mayor_ultimate_defense_start',
complete: 'mayor_ultimate_defense_complete'
}
}
};

124
src/quests/MuseumQuests.js Normal file
View File

@@ -0,0 +1,124 @@
/**
* MUSEUM QUEST DATA
* Related to MuseumEvolutionSystem
*/
export const MuseumQuests = {
// QUEST 1: First Artifact
first_artifact: {
id: 'first_artifact',
name: 'Kustos\'s First Find',
category: 'museum',
npc: 'kustos',
description: 'Kustos needs you to find and donate your first artifact to start the museum collection.',
objectives: [
{
type: 'collect',
target: 'any_artifact',
amount: 1,
description: 'Find any artifact'
},
{
type: 'donate',
target: 'museum',
description: 'Donate artifact to Kustos'
}
],
rewards: {
xp: 100,
currency: 200,
items: [{ id: 'basic_shovel', amount: 1 }],
unlocks: ['artifact_detection']
},
dialogue: {
start: 'kustos_first_artifact_start',
progress: 'kustos_first_artifact_progress',
complete: 'kustos_first_artifact_complete'
}
},
// QUEST 2: Category Completion
complete_prehistory: {
id: 'complete_prehistory',
name: 'Prehistoric Collection',
category: 'museum',
npc: 'kustos',
requires: 'first_artifact',
description: 'Complete the Prehistoric Era collection by donating all 3 artifacts.',
objectives: [
{
type: 'donate_category',
target: 'prehistory',
amount: 3,
description: 'Donate 3 prehistoric artifacts (Dino Skull, Ancient Vase, Fossil)'
}
],
rewards: {
xp: 500,
currency: 1000,
items: [{ id: 'rare_excavation_kit', amount: 1 }],
reputation: 50
},
dialogue: {
start: 'kustos_prehistory_start',
complete: 'kustos_prehistory_complete'
}
},
// QUEST 3: Museum Stage 2
museum_stage_2: {
id: 'museum_stage_2',
name: 'Advanced Exhibition',
category: 'museum',
npc: 'kustos',
description: 'Help Kustos evolve the museum to Stage 2 by donating 8 artifacts total.',
objectives: [
{
type: 'museum_stage',
target: 2,
description: 'Donate 8 artifacts to reach Museum Stage 2'
}
],
rewards: {
xp: 1000,
currency: 2500,
items: [{ id: 'artifact_radar', amount: 1 }],
unlocks: ['lore_system'],
reputation: 100
},
dialogue: {
start: 'kustos_stage2_start',
complete: 'kustos_stage2_complete'
}
},
// QUEST 4: Master Curator
master_curator: {
id: 'master_curator',
name: 'Master Curator',
category: 'museum',
npc: 'kustos',
description: 'Complete the entire museum collection - all 12 artifacts.',
objectives: [
{
type: 'museum_stage',
target: 3,
description: 'Donate all 12 artifacts to reach Museum Stage 3'
}
],
rewards: {
xp: 3000,
currency: 10000,
items: [
{ id: 'legendary_excavator', amount: 1 },
{ id: 'curator_badge', amount: 1 }
],
achievement: 'master_curator',
reputation: 500
},
dialogue: {
start: 'kustos_master_start',
complete: 'kustos_master_complete'
}
}
};

155
src/quests/SchoolQuests.js Normal file
View File

@@ -0,0 +1,155 @@
/**
* SCHOOL QUEST DATA
* Related to SchoolBuffSystem and Teacher NPC
*/
export const SchoolQuests = {
// QUEST 1: School Opening
school_opening: {
id: 'school_opening',
name: 'School Days',
category: 'education',
npc: 'teacher',
description: 'Help Teacher restore the school building and start lessons.',
objectives: [
{
type: 'repair_building',
target: 'school',
description: 'Repair the school building'
},
{
type: 'gather_materials',
items: [
{ id: 'wood', amount: 50 },
{ id: 'stone', amount: 30 },
{ id: 'books', amount: 10 }
],
description: 'Gather materials for school restoration'
}
],
rewards: {
xp: 400,
currency: 800,
items: [{ id: 'student_handbook', amount: 1 }],
unlocks: ['school_system'],
freeLesson: 'basic_farming'
},
dialogue: {
start: 'teacher_school_opening_start',
progress: 'teacher_school_opening_progress',
complete: 'teacher_school_opening_complete'
}
},
// QUEST 2: Star Student
star_student: {
id: 'star_student',
name: 'Star Student',
category: 'education',
npc: 'teacher',
requires: 'school_opening',
description: 'Learn 5 different skills from Teacher.',
objectives: [
{
type: 'learn_skills',
amount: 5,
description: 'Learn 5 skills from Teacher'
}
],
rewards: {
xp: 1000,
currency: 2000,
items: [{ id: 'honor_student_badge', amount: 1 }],
reputation: 100,
specialBonus: '25% discount on all future lessons'
},
dialogue: {
start: 'teacher_star_student_start',
complete: 'teacher_star_student_complete'
}
},
// QUEST 3: Master Scholar
master_scholar: {
id: 'master_scholar',
name: 'Master Scholar',
category: 'education',
npc: 'teacher',
requires: 'star_student',
description: 'Learn all permanent skills from Teacher (Farming, Combat, Survival).',
objectives: [
{
type: 'learn_category',
target: 'farming',
description: 'Learn all farming skills'
},
{
type: 'learn_category',
target: 'combat',
description: 'Learn all combat skills'
},
{
type: 'learn_category',
target: 'survival',
description: 'Learn all survival skills'
}
],
rewards: {
xp: 3000,
currency: 7500,
items: [
{ id: 'master_diploma', amount: 1 },
{ id: 'wisdom_amulet', amount: 1 }
],
achievement: 'master_scholar',
reputation: 300,
permanentBuff: {
name: 'Master\'s Wisdom',
effect: '+10% to all skill effectiveness'
}
},
dialogue: {
start: 'teacher_master_scholar_start',
complete: 'teacher_master_scholar_complete'
}
},
// QUEST 4: Successor
successor: {
id: 'successor',
name: 'The Successor',
category: 'education',
npc: 'teacher',
requires: 'master_scholar',
description: 'Teacher sees potential in you. Prove you can teach others.',
objectives: [
{
type: 'teach_npcs',
amount: 10,
description: 'Teach skills to 10 different NPCs'
},
{
type: 'reach_level',
target: 20,
description: 'Reach Level 20'
}
],
rewards: {
xp: 5000,
currency: 20000,
items: [
{ id: 'teacher_robes', amount: 1 },
{ id: 'staff_of_knowledge', amount: 1 }
],
achievement: 'successor',
reputation: 500,
unlocks: ['teaching_system'],
specialBonus: 'Can now teach skills to NPCs for reputation'
},
dialogue: {
start: 'teacher_successor_start',
progress: 'teacher_successor_progress',
complete: 'teacher_successor_complete'
}
}
};

View File

@@ -0,0 +1,331 @@
/**
* CITY GRATITUDE GIFT SYSTEM
* Population milestone rewards
* Unique equipment and bonuses
*/
export class CityGratitudeSystem {
constructor(scene) {
this.scene = scene;
// Milestone tracking
this.milestones = new Map();
this.claimedMilestones = new Set();
// City reputation
this.reputation = 0;
this.init();
}
init() {
this.initializeMilestones();
// Check milestones when population changes
this.scene.events.on('population_changed', () => this.checkMilestones());
}
/**
* Initialize population milestones
*/
initializeMilestones() {
this.registerMilestone({
population: 10,
name: 'Small Community',
rewards: {
items: [{ id: 'starter_hoe', name: 'Community Hoe', rarity: 'uncommon' }],
currency: 500,
reputation: 50
},
description: '10 settlers joined your farm!'
});
this.registerMilestone({
population: 25,
name: 'Growing Village',
rewards: {
items: [
{ id: 'village_axe', name: 'Village Axe', rarity: 'rare' },
{ id: 'mayor_blessing', name: 'Mayor\'s Blessing', rarity: 'rare', type: 'buff' }
],
currency: 1500,
reputation: 100,
unlock: 'town_hall'
},
description: '25 settlers! The village recognizes your leadership.'
});
this.registerMilestone({
population: 50,
name: 'Thriving Town',
rewards: {
items: [
{ id: 'master_scythe', name: 'Master Scythe', rarity: 'epic' },
{ id: 'town_armor', name: 'Town Guardian Armor', rarity: 'epic' }
],
currency: 5000,
reputation: 250,
unlock: 'advanced_workshop'
},
description: '50 settlers! Your town flourishes.'
});
this.registerMilestone({
population: 100,
name: 'Major City',
rewards: {
items: [
{ id: 'legendary_pickaxe', name: 'Pickaxe of Prosperity', rarity: 'legendary' },
{ id: 'city_crown', name: 'Crown of the People', rarity: 'legendary' },
{ id: 'citizens_gratitude', name: 'Citizens\' Eternal Gratitude', rarity: 'legendary', type: 'permanent_buff' }
],
currency: 15000,
reputation: 500,
unlock: 'city_monument'
},
description: '100 settlers! You\'ve built a magnificent city!'
});
this.registerMilestone({
population: 200,
name: 'Metropolis',
rewards: {
items: [
{ id: 'omega_tool_set', name: 'Omega Tool Set', rarity: 'mythic' },
{ id: 'metropolis_throne', name: 'Throne of Dominion', rarity: 'mythic' }
],
currency: 50000,
reputation: 1000,
unlock: 'palace',
specialBonus: 'All workers +100% efficiency'
},
description: '200 settlers! Your metropolis is legendary!'
});
}
/**
* Register a milestone
*/
registerMilestone(milestoneData) {
this.milestones.set(milestoneData.population, {
...milestoneData,
claimed: false
});
}
/**
* Check if any milestones reached
*/
checkMilestones() {
const currentPopulation = this.scene.gameState?.population || 0;
this.milestones.forEach((milestone, requiredPop) => {
if (currentPopulation >= requiredPop && !this.claimedMilestones.has(requiredPop)) {
this.triggerMilestone(requiredPop);
}
});
}
/**
* Trigger milestone reward
*/
triggerMilestone(population) {
const milestone = this.milestones.get(population);
if (!milestone) return;
// Mark as claimed
this.claimedMilestones.add(population);
milestone.claimed = true;
// Grant rewards
this.grantRewards(milestone.rewards);
// Special bonuses
if (milestone.specialBonus) {
this.applySpecialBonus(milestone.specialBonus);
}
// Reputation
this.reputation += milestone.rewards.reputation || 0;
// Cinematic notification
this.scene.uiSystem?.showMilestoneNotification(
milestone.name,
milestone.description,
milestone.rewards
);
// VFX: Celebration
this.scene.vfxSystem?.playEffect('city_celebration', 400, 300);
this.scene.cameras.main.flash(2000, 255, 215, 0);
// SFX
this.scene.soundSystem?.play('milestone_fanfare');
console.log(`🎉 MILESTONE REACHED: ${milestone.name} (${population} population)`);
}
/**
* Grant milestone rewards
*/
grantRewards(rewards) {
// Currency
if (rewards.currency) {
this.scene.economySystem?.addCurrency(rewards.currency);
console.log(`+${rewards.currency} coins`);
}
// Items
if (rewards.items) {
rewards.items.forEach(item => {
this.scene.inventorySystem?.addItem(item.id, 1);
console.log(`Received: ${item.name} (${item.rarity})`);
// Special item effects
if (item.type === 'buff') {
this.applyItemBuff(item);
} else if (item.type === 'permanent_buff') {
this.applyPermanentBuff(item);
}
});
}
// Unlocks
if (rewards.unlock) {
this.scene.gameState.unlocks[rewards.unlock] = true;
console.log(`Unlocked: ${rewards.unlock}`);
}
}
/**
* Apply item buff
*/
applyItemBuff(item) {
switch (item.id) {
case 'mayor_blessing':
this.scene.gameState.buffs.mayor_blessing = {
crop_yield: 1.25,
building_speed: 1.25,
duration: Infinity // Permanent
};
break;
}
}
/**
* Apply permanent buff
*/
applyPermanentBuff(item) {
switch (item.id) {
case 'citizens_gratitude':
// Permanent +25% to all production
this.scene.gameState.buffs.citizens_gratitude = {
all_production: 1.25,
all_efficiency: 1.25
};
break;
}
}
/**
* Apply special bonus
*/
applySpecialBonus(bonus) {
if (bonus === 'All workers +100% efficiency') {
this.scene.npcSettlementSystem?.settledNPCs.forEach((npc, npcId) => {
const currentEff = this.scene.npcSettlementSystem.npcEfficiency.get(npcId) || 1.0;
this.scene.npcSettlementSystem.npcEfficiency.set(npcId, currentEff * 2.0);
});
}
}
/**
* Get next milestone
*/
getNextMilestone() {
const currentPopulation = this.scene.gameState?.population || 0;
for (const [reqPop, milestone] of this.milestones.entries()) {
if (reqPop > currentPopulation) {
return {
population: reqPop,
...milestone,
progress: Math.min(100, (currentPopulation / reqPop) * 100)
};
}
}
return null; // All milestones claimed
}
/**
* Get all milestones
*/
getAllMilestones() {
return Array.from(this.milestones.entries()).map(([pop, milestone]) => ({
population: pop,
...milestone,
claimed: this.claimedMilestones.has(pop)
}));
}
/**
* Get claimed milestones
*/
getClaimedMilestones() {
return this.getAllMilestones().filter(m => m.claimed);
}
/**
* Get city reputation
*/
getReputation() {
return this.reputation;
}
/**
* Get reputation tier
*/
getReputationTier() {
if (this.reputation >= 1000) return 'Legendary';
if (this.reputation >= 500) return 'Renowned';
if (this.reputation >= 250) return 'Well-Known';
if (this.reputation >= 100) return 'Respected';
if (this.reputation >= 50) return 'Known';
return 'Unknown';
}
/**
* Manual milestone trigger (for testing)
*/
triggerMilestoneManual(population) {
if (!this.claimedMilestones.has(population)) {
this.triggerMilestone(population);
}
}
/**
* Save/Load
*/
getSaveData() {
return {
claimedMilestones: Array.from(this.claimedMilestones),
reputation: this.reputation
};
}
loadSaveData(data) {
this.claimedMilestones = new Set(data.claimedMilestones || []);
this.reputation = data.reputation || 0;
// Mark milestones as claimed
this.claimedMilestones.forEach(pop => {
const milestone = this.milestones.get(pop);
if (milestone) {
milestone.claimed = true;
// Re-apply permanent buffs
this.grantRewards(milestone.rewards);
}
});
}
}

View File

@@ -0,0 +1,341 @@
/**
* NPC SETTLEMENT SYSTEM (Magic Helpers)
* NPCs auto-assist with tasks
* Worker efficiency, happiness, housing
*/
export class NPCSettlementSystem {
constructor(scene) {
this.scene = scene;
// Settled NPCs
this.settledNPCs = new Map();
// Worker assignments
this.assignments = new Map(); // npcId → task
// NPC stats
this.npcHappiness = new Map(); // npcId → happiness (0-100)
this.npcEfficiency = new Map(); // npcId → efficiency (0.5-2.0)
// Housing
this.npcHomes = new Map(); // npcId → buildingId
this.housingCapacity = 0;
// Task types
this.taskTypes = ['farming', 'building', 'crafting', 'defense', 'gathering'];
this.init();
}
init() {
// Update worker tasks periodically
this.scene.time.addEvent({
delay: 5000, // Every 5s
callback: () => this.updateWorkers(),
loop: true
});
// Update happiness hourly
this.scene.time.addEvent({
delay: 3600000, // 1 hour
callback: () => this.updateHappiness(),
loop: true
});
}
/**
* Settle an NPC (they join the town)
*/
settleNPC(npcId, npcData) {
if (this.settledNPCs.has(npcId)) return false;
//Check housing availability
if (this.settledNPCs.size >= this.housingCapacity) {
console.warn('No housing available');
return false;
}
this.settledNPCs.set(npcId, {
id: npcId,
name: npcData.name,
skills: npcData.skills || [],
assignedTask: null,
...npcData
});
// Initial stats
this.npcHappiness.set(npcId, 75); // Start at 75% happiness
this.npcEfficiency.set(npcId, 1.0); // Base efficiency
// Notification
this.scene.uiSystem?.showNotification(
`${npcData.name} has joined the settlement!`,
'success',
{ icon: 'npc_join' }
);
console.log(`🏘️ ${npcData.name} settled in town`);
return true;
}
/**
* Assign NPC to task
*/
assignTask(npcId, taskType, taskData) {
const npc = this.settledNPCs.get(npcId);
if (!npc) return false;
// Check if NPC has skill for task
if (!npc.skills.includes(taskType)) {
console.warn(`${npc.name} lacks skill: ${taskType}`);
return false;
}
// Assign
npc.assignedTask = taskType;
this.assignments.set(npcId, {
type: taskType,
data: taskData,
startTime: Date.now()
});
console.log(`👷 ${npc.name} assigned to ${taskType}`);
return true;
}
/**
* Unassign NPC from task
*/
unassignTask(npcId) {
const npc = this.settledNPCs.get(npcId);
if (!npc) return false;
npc.assignedTask = null;
this.assignments.delete(npcId);
console.log(`${npc.name} unassigned`);
return true;
}
/**
* Update all worker tasks
*/
updateWorkers() {
this.assignments.forEach((assignment, npcId) => {
const npc = this.settledNPCs.get(npcId);
const efficiency = this.npcEfficiency.get(npcId) || 1.0;
switch (assignment.type) {
case 'farming':
this.performFarming(npc, efficiency, assignment.data);
break;
case 'building':
this.performBuilding(npc, efficiency, assignment.data);
break;
case 'crafting':
this.performCrafting(npc, efficiency, assignment.data);
break;
case 'defense':
this.performDefense(npc, efficiency);
break;
case 'gathering':
this.performGathering(npc, efficiency);
break;
}
});
}
/**
* WORKER TASKS
*/
performFarming(npc, efficiency, data) {
// Auto-tend crops
const crops = this.scene.crops || [];
const tendsPerCycle = Math.floor(2 * efficiency);
for (let i = 0; i < tendsPerCycle && i < crops.length; i++) {
const crop = crops[i];
crop.water?.();
crop.fertilize?.();
}
// Chance to auto-harvest
if (Math.random() < 0.1 * efficiency) {
const harvestable = crops.find(c => c.isHarvestable);
if (harvestable) {
this.scene.farmingSystem?.harvestCrop(harvestable);
console.log(`${npc.name} harvested crop`);
}
}
}
performBuilding(npc, efficiency, data) {
// Speed up construction
const building = data.buildingId ? this.scene.buildingSystem?.getBuilding(data.buildingId) : null;
if (building && building.isUnderConstruction) {
const progressBonus = 5 * efficiency;
building.constructionProgress += progressBonus;
if (building.constructionProgress >= 100) {
this.scene.buildingSystem?.completeConstruction(building.id);
console.log(`${npc.name} completed building: ${building.name}`);
}
}
}
performCrafting(npc, efficiency, data) {
// Auto-craft items
if (data.recipe) {
const canCraft = this.scene.craftingSystem?.canCraft(data.recipe);
if (canCraft && Math.random() < 0.2 * efficiency) {
this.scene.craftingSystem?.craft(data.recipe);
console.log(`${npc.name} crafted ${data.recipe}`);
}
}
}
performDefense(npc, efficiency) {
// Patrol and defend
// Increased detection range for raids
this.scene.gameState.buffs.raid_detection_range = (this.scene.gameState.buffs.raid_detection_range || 1.0) + (0.1 * efficiency);
// Auto-repair walls/defenses
const defenses = this.scene.defenseSystem?.getAllDefenses() || [];
defenses.forEach(defense => {
if (defense.health < defense.maxHealth && Math.random() < 0.05 * efficiency) {
defense.health = Math.min(defense.maxHealth, defense.health + 10);
console.log(`${npc.name} repaired ${defense.name}`);
}
});
}
performGathering(npc, efficiency) {
// Auto-gather resources
const gatherChance = 0.15 * efficiency;
if (Math.random() < gatherChance) {
const resources = ['wood', 'stone', 'berries', 'herbs'];
const resource = Phaser.Utils.Array.GetRandom(resources);
const amount = Math.floor(Phaser.Math.Between(1, 3) * efficiency);
this.scene.inventorySystem?.addItem(resource, amount);
console.log(`${npc.name} gathered ${amount} ${resource}`);
}
}
/**
* Update NPC happiness
*/
updateHappiness() {
this.settledNPCs.forEach((npc, npcId) => {
let happiness = this.npcHappiness.get(npcId) || 50;
// Factors affecting happiness
const hasHome = this.npcHomes.has(npcId);
const hasTask = npc.assignedTask !== null;
const isOverworked = hasTask && this.assignments.get(npcId)?.overworked;
// Adjustments
if (hasHome) happiness += 5;
if (hasTask) happiness += 2;
if (isOverworked) happiness -= 10;
if (!hasHome && this.settledNPCs.size > this.housingCapacity) happiness -= 15;
// Natural decay
happiness -= 1;
// Clamp
happiness = Math.max(0, Math.min(100, happiness));
this.npcHappiness.set(npcId, happiness);
// Update efficiency based on happiness
const efficiency = 0.5 + (happiness / 100) * 1.5; // 0.5-2.0
this.npcEfficiency.set(npcId, efficiency);
// Low happiness warning
if (happiness < 30) {
this.scene.uiSystem?.showNotification(
`${npc.name} is unhappy!`,
'warning'
);
console.warn(`${npc.name} happiness: ${happiness}`);
}
});
}
/**
* Assign NPC to home
*/
assignHome(npcId, buildingId) {
this.npcHomes.set(npcId, buildingId);
// Happiness boost
const happiness = this.npcHappiness.get(npcId) || 50;
this.npcHappiness.set(npcId, Math.min(100, happiness + 20));
console.log(`${this.settledNPCs.get(npcId).name} moved into home`);
}
/**
* Increase housing capacity
*/
addHousing(capacity) {
this.housingCapacity += capacity;
console.log(`Housing capacity: ${this.housingCapacity}`);
}
/**
* Get settlement statistics
*/
getSettlementStats() {
const npcs = Array.from(this.settledNPCs.values());
const avgHappiness = npcs.reduce((sum, npc) => sum + (this.npcHappiness.get(npc.id) || 0), 0) / npcs.length || 0;
const avgEfficiency = npcs.reduce((sum, npc) => sum + (this.npcEfficiency.get(npc.id) || 1), 0) / npcs.length || 1;
return {
population: npcs.length,
housingCapacity: this.housingCapacity,
averageHappiness: Math.round(avgHappiness),
averageEfficiency: avgEfficiency.toFixed(2),
assignedWorkers: this.assignments.size,
unemployed: npcs.length - this.assignments.size
};
}
/**
* Get NPCs by skill
*/
getNPCsBySkill(skill) {
return Array.from(this.settledNPCs.values()).filter(npc => npc.skills.includes(skill));
}
/**
* Save/Load
*/
getSaveData() {
return {
settledNPCs: Array.from(this.settledNPCs.entries()),
assignments: Array.from(this.assignments.entries()),
npcHappiness: Array.from(this.npcHappiness.entries()),
npcHomes: Array.from(this.npcHomes.entries()),
housingCapacity: this.housingCapacity
};
}
loadSaveData(data) {
this.settledNPCs = new Map(data.settledNPCs || []);
this.assignments = new Map(data.assignments || []);
this.npcHappiness = new Map(data.npcHappiness || []);
this.npcHomes = new Map(data.npcHomes || []);
this.housingCapacity = data.housingCapacity || 0;
// Recalculate efficiency
this.npcHappiness.forEach((happiness, npcId) => {
const efficiency = 0.5 + (happiness / 100) * 1.5;
this.npcEfficiency.set(npcId, efficiency);
});
}
}

View File

@@ -0,0 +1,316 @@
/**
* 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);
}
});
}
}
}