Files
TetaRdPG/src/common/zone-access.ts
Tetardtek 4beb1b2ed9 feat: Phase 3 Lore & Contenu — L'Odyssée d'un têtard
Lore Bible (canon narratif complet) + Engine Design (séparation moteur/univers).

4 nouvelles zones (Ruisseau Miroir, Marais des Murmures, Torrent Brisé, Source du Courant)
dans la chaîne d'unlock après desert (niv 16-25+).

Module NPC complet (entity, service, controller) — 8 PNJ avec dialogues évolutifs
par palier de niveau : Gorn (niv 1-15), Pierre-Mémoire (niv 16+), Mira, Vell,
La Batracienne, Le Forgeron, Le Marchand.

20 monstres lore-friendly, 12 matériaux, 15 items (dont Bâton de Gorn légendaire).

17 quêtes narratives (4 arcs ch.9-12) avec textes acceptText/completeText
qui racontent l'Odyssée. Nouveau type story_event pour les moments narratifs purs.
3 quêtes répétables optionnelles.

Seed runner : npm run seed:odyssee

Tout est additif — zéro impact sur le contenu existant niv 1-15.
2026-03-25 00:52:14 +01:00

49 lines
1.9 KiB
TypeScript

import { Repository } from 'typeorm';
import { PlayerQuestArc } from '../quest/player-quest-arc.entity';
import { QuestArc } from '../quest/quest-arc.entity';
// Zone unlock chain: each zone requires completing the previous zone's arc
// marais → always open (L'Étang — niv 1-5)
// egouts → requires "Les Marais du Têtard" arc (L'Étang profond — niv 6-10)
// desert → requires egouts arc (L'Étang Brisé — niv 11-15)
// ruisseau_miroir → requires desert arc (Ruisseau Miroir — niv 16-18)
// marais_murmures → requires ruisseau_miroir arc (Marais des Murmures — niv 19-21)
// torrent_brise → requires marais_murmures arc (Torrent Brisé — niv 22-24)
// source_courant → requires torrent_brise arc (Source du Courant — niv 25+)
const ZONE_ORDER = ['marais', 'egouts', 'desert', 'ruisseau_miroir', 'marais_murmures', 'torrent_brise', 'source_courant'];
export async function getUnlockedZones(
characterId: string,
arcRepo: Repository<QuestArc>,
playerArcRepo: Repository<PlayerQuestArc>,
): Promise<string[]> {
const unlocked: string[] = ['marais']; // always accessible
// Get all completed arcs for this character
const completedArcs = await playerArcRepo.find({
where: { characterId, completed: true },
relations: ['questArc'],
});
const completedArcZones = new Set(completedArcs.map(pa => pa.questArc?.zone).filter(Boolean));
// Check zone chain: each zone unlocks the next
for (let i = 0; i < ZONE_ORDER.length - 1; i++) {
const currentZone = ZONE_ORDER[i];
const nextZone = ZONE_ORDER[i + 1];
// Find arc for current zone
const arc = await arcRepo.findOne({ where: { zone: currentZone } });
if (!arc) continue;
// If this zone's arc is completed, unlock the next zone
const isCompleted = completedArcs.some(pa => pa.questArcId === arc.id);
if (isCompleted) {
unlocked.push(nextZone);
} else {
break; // Can't skip zones
}
}
return unlocked;
}