This commit is contained in:
2025-12-07 21:31:44 +01:00
parent 4a0ca267ea
commit 974141c08c
52 changed files with 2485 additions and 397 deletions

197
src/systems/QuestSystem.js Normal file
View File

@@ -0,0 +1,197 @@
class QuestSystem {
constructor(scene) {
this.scene = scene;
// Quest Definitions
this.questDB = {
'q1_start': {
id: 'q1_start',
title: 'Survival Basics',
description: 'Collect Wood and Stone to build your first defense.',
objectives: [
{ type: 'collect', item: 'wood', amount: 5, current: 0, done: false },
{ type: 'collect', item: 'stone', amount: 3, current: 0, done: false }
],
reward: { gold: 10, xp: 50 },
nextQuest: 'q2_farm',
giver: 'villager'
},
'q2_farm': {
id: 'q2_farm',
title: 'The Farmer',
description: 'Plant some seeds to grow food. You will need it.',
objectives: [
{ type: 'action', action: 'plant', amount: 3, current: 0, done: false }
],
reward: { gold: 20, item: 'wood', amount: 10 },
nextQuest: 'q3_defense',
giver: 'villager'
},
'q3_defense': {
id: 'q3_defense',
title: 'Fortification',
description: 'Build a Fence to keep zombies out.',
objectives: [
{ type: 'action', action: 'build_fence', amount: 2, current: 0, done: false }
],
reward: { gold: 50, item: 'sword', amount: 1 },
nextQuest: 'q4_slayer',
giver: 'merchant'
},
'q4_slayer': {
id: 'q4_slayer',
title: 'Zombie Slayer',
description: 'Kill 3 Zombies using your new sword.',
objectives: [
{ type: 'kill', target: 'zombie', amount: 3, current: 0, done: false }
],
reward: { gold: 100, item: 'gold', amount: 50 },
nextQuest: null,
giver: 'villager'
}
};
this.activeQuest = null;
this.completedQuests = [];
}
getAvailableQuest(npcType) {
const chain = ['q1_start', 'q2_farm', 'q3_defense', 'q4_slayer'];
let targetId = null;
for (const id of chain) {
if (!this.completedQuests.includes(id)) {
targetId = id;
break;
}
}
if (!targetId) return null;
if (this.activeQuest && this.activeQuest.id === targetId) return null;
const q = this.questDB[targetId];
if (q.giver === npcType) return q;
return null;
}
startQuest(id) {
if (this.completedQuests.includes(id)) return;
const template = this.questDB[id];
if (!template) return;
this.activeQuest = JSON.parse(JSON.stringify(template));
console.log(`📜 Quest Started: ${this.activeQuest.title}`);
this.updateUI();
// Notification
this.scene.events.emit('show-floating-text', {
x: this.scene.player.x,
y: this.scene.player.y - 50,
text: "Quest Accepted!",
color: '#FFFF00'
});
}
update(delta) {
if (!this.activeQuest) return;
let changed = false;
let allDone = true;
if (this.scene.inventorySystem) {
const inv = this.scene.inventorySystem;
for (const obj of this.activeQuest.objectives) {
if (obj.done) continue;
if (obj.type === 'collect') {
const count = inv.getItemCount(obj.item);
if (count !== obj.current) {
obj.current = count;
changed = true;
}
if (obj.current >= obj.amount) {
obj.done = true;
this.scene.events.emit('show-floating-text', { x: this.scene.player.x, y: this.scene.player.y, text: "Objective Complete!" });
}
}
}
}
for (const obj of this.activeQuest.objectives) {
if (!obj.done) allDone = false;
}
if (changed) this.updateUI();
if (allDone) {
this.completeQuest();
}
}
trackAction(actionType, amount = 1) {
if (!this.activeQuest) return;
let changed = false;
for (const obj of this.activeQuest.objectives) {
if (obj.done) continue;
if (obj.type === 'action' && obj.action === actionType) {
obj.current += amount;
changed = true;
if (obj.current >= obj.amount) {
obj.done = true;
changed = true;
}
}
if (obj.type === 'kill' && obj.target === actionType) {
obj.current += amount;
changed = true;
if (obj.current >= obj.amount) {
obj.done = true;
changed = true;
}
}
}
if (changed) this.updateUI();
}
completeQuest() {
console.log(`🏆 Quest Complete: ${this.activeQuest.title}`);
if (this.activeQuest.reward) {
const r = this.activeQuest.reward;
if (r.gold && this.scene.inventorySystem) {
this.scene.inventorySystem.addGold(r.gold);
}
if (r.item && this.scene.inventorySystem) {
this.scene.inventorySystem.addItem(r.item, r.amount || 1);
}
}
this.scene.events.emit('show-floating-text', {
x: this.scene.player.x,
y: this.scene.player.y - 50,
text: "Quest Complete!",
color: '#00FF00'
});
this.completedQuests.push(this.activeQuest.id);
const next = this.activeQuest.nextQuest;
this.activeQuest = null;
this.updateUI();
if (next) {
console.log('Next quest available at NPC.');
}
}
updateUI() {
const ui = this.scene.scene.get('UIScene');
if (ui && ui.updateQuestTracker) {
ui.updateQuestTracker(this.activeQuest);
}
}
}