diff --git a/src/quest/quest.service.ts b/src/quest/quest.service.ts index 5acefbc..7277130 100644 --- a/src/quest/quest.service.ts +++ b/src/quest/quest.service.ts @@ -8,6 +8,7 @@ import { QuestArc } from './quest-arc.entity'; import { PlayerQuest } from './player-quest.entity'; import { PlayerQuestArc } from './player-quest-arc.entity'; import { Character } from '../character/entities/character.entity'; +import { getUnlockedZones } from '../common/zone-access'; const MAX_ACTIVE_QUESTS = 3; @@ -39,6 +40,9 @@ export class QuestService { }); const questStatusMap = new Map(playerQuests.map((pq) => [pq.questId, pq.status])); + // Zone locking — only show quests from unlocked zones + const unlockedZones = await getUnlockedZones(characterId, this.arcRepo, this.playerArcRepo); + const quests = await this.questRepo.find({ relations: ['arc'], order: { arcOrder: 'ASC' }, @@ -47,10 +51,11 @@ export class QuestService { return quests.filter((q) => { if (q.minLevel > character.level) return false; + // Zone filter: if quest belongs to an arc with a zone, check zone is unlocked + if (q.arc?.zone && !unlockedZones.includes(q.arc.zone)) return false; + const status = questStatusMap.get(q.id); - // Already active or completed (waiting claim) → not available if (status === 'active' || status === 'completed') return false; - // Already claimed and not repeatable → not available if (status === 'claimed' && !q.repeatable) return false; return true;