feat: arc quests accept from arc panel + side quests only in available
All checks were successful
CI/CD — Build & Deploy / Build & Deploy (push) Successful in 35s
All checks were successful
CI/CD — Build & Deploy / Build & Deploy (push) Successful in 35s
Arc panel: boutons Accepter/Réclamer directement sur chaque quête d'arc,
progress affiché (3/5), arcs lockés avec 🔒 et opacity réduite.
Quêtes disponibles: seulement les secondaires (pas les arcs).
Quêtes d'arc abandonnées: ré-acceptables depuis le panel arc.
Zone locking respecté dans getArcs (zoneUnlocked flag).
This commit is contained in:
@@ -50,9 +50,8 @@ 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;
|
||||
// Arc quests managed from arc panel — not in available
|
||||
if (q.arcId) return false;
|
||||
|
||||
const status = questStatusMap.get(q.id);
|
||||
if (status === 'active' || status === 'completed') return false;
|
||||
@@ -287,6 +286,11 @@ export class QuestService {
|
||||
// --- Arcs ---
|
||||
|
||||
async getArcs(characterId: string) {
|
||||
const character = await this.characterRepo.findOne({ where: { id: characterId } });
|
||||
const playerLevel = character?.level ?? 1;
|
||||
|
||||
const unlockedZones = await getUnlockedZones(characterId, this.arcRepo, this.playerArcRepo);
|
||||
|
||||
const arcs = await this.arcRepo.find({
|
||||
relations: ['quests'],
|
||||
order: { sortOrder: 'ASC' },
|
||||
@@ -297,24 +301,35 @@ export class QuestService {
|
||||
|
||||
const playerQuests = await this.playerQuestRepo.find({
|
||||
where: { characterId },
|
||||
select: ['questId', 'status'],
|
||||
select: ['questId', 'status', 'id', 'progress'],
|
||||
});
|
||||
const questStatusMap = new Map(playerQuests.map((pq) => [pq.questId, pq.status]));
|
||||
const questDataMap = new Map(playerQuests.map((pq) => [pq.questId, pq]));
|
||||
|
||||
return arcs.map((arc) => ({
|
||||
...arc,
|
||||
completed: arcMap.get(arc.id)?.completed ?? false,
|
||||
completedAt: arcMap.get(arc.id)?.completedAt ?? null,
|
||||
quests: arc.quests
|
||||
.sort((a, b) => a.arcOrder - b.arcOrder)
|
||||
.map((q) => ({
|
||||
...q,
|
||||
playerStatus: questStatusMap.get(q.id) ?? 'available',
|
||||
})),
|
||||
progress: {
|
||||
completed: arc.quests.filter((q) => questStatusMap.get(q.id) === 'claimed').length,
|
||||
total: arc.quests.length,
|
||||
},
|
||||
}));
|
||||
return arcs.map((arc) => {
|
||||
const zoneUnlocked = !arc.zone || unlockedZones.includes(arc.zone);
|
||||
return {
|
||||
...arc,
|
||||
zoneUnlocked,
|
||||
completed: arcMap.get(arc.id)?.completed ?? false,
|
||||
completedAt: arcMap.get(arc.id)?.completedAt ?? null,
|
||||
quests: arc.quests
|
||||
.sort((a, b) => a.arcOrder - b.arcOrder)
|
||||
.map((q) => {
|
||||
const pq = questDataMap.get(q.id);
|
||||
return {
|
||||
...q,
|
||||
playerStatus: pq?.status ?? 'available',
|
||||
playerQuestId: pq?.id ?? null,
|
||||
progress: pq?.progress ?? 0,
|
||||
canAccept: zoneUnlocked && !pq && q.minLevel <= playerLevel,
|
||||
levelOk: q.minLevel <= playerLevel,
|
||||
};
|
||||
}),
|
||||
progress: {
|
||||
completed: arc.quests.filter((q) => questDataMap.get(q.id)?.status === 'claimed').length,
|
||||
total: arc.quests.length,
|
||||
},
|
||||
};
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user