134 lines
3.7 KiB
JavaScript
134 lines
3.7 KiB
JavaScript
const DatapackLoader = require("./DatapackLoader");
|
|
|
|
class DungeonManager {
|
|
constructor() {
|
|
this.activeSessions = new Map();
|
|
}
|
|
|
|
startDungeon(playerId, dungeonId) {
|
|
const dungeon = DatapackLoader.getDungeon(dungeonId);
|
|
if (!dungeon || !dungeon.rooms?.length) return null;
|
|
|
|
const session = {
|
|
dungeonId,
|
|
currentRoomIndex: 0,
|
|
isFinished: false,
|
|
currentEnemyHp: undefined,
|
|
rewards: { xp: 0, credits: 0, items: [] },
|
|
};
|
|
this.activeSessions.set(playerId, session);
|
|
return this.getCurrentRoomData(playerId);
|
|
}
|
|
|
|
getCurrentRoomData(playerId) {
|
|
const session = this.activeSessions.get(playerId);
|
|
if (!session) return null;
|
|
|
|
const dungeon = DatapackLoader.getDungeon(session.dungeonId);
|
|
const roomRef = dungeon.rooms[session.currentRoomIndex];
|
|
const rawRoom = DatapackLoader.getRoom(roomRef.id);
|
|
|
|
if (!rawRoom) return null;
|
|
|
|
const hostiles = (rawRoom.hostiles || [])
|
|
.map((hId) => DatapackLoader.getEnemy(hId))
|
|
.filter(Boolean);
|
|
|
|
return {
|
|
roomIndex: session.currentRoomIndex,
|
|
totalRooms: dungeon.rooms.length,
|
|
config: rawRoom,
|
|
hostiles,
|
|
};
|
|
}
|
|
|
|
processCombatStep(playerId, enemyId) {
|
|
const session = this.activeSessions.get(playerId);
|
|
if (!session || session.isFinished) return null;
|
|
|
|
const enemy = DatapackLoader.getEnemy(enemyId);
|
|
if (!enemy) return null;
|
|
|
|
if (session.currentEnemyHp === undefined) {
|
|
session.currentEnemyHp = enemy.stats?.health || 100;
|
|
}
|
|
|
|
const damage = Math.floor(Math.random() * 10) + 20;
|
|
session.currentEnemyHp -= damage;
|
|
|
|
const isDefeated = session.currentEnemyHp <= 0;
|
|
let lootDropped = [];
|
|
|
|
if (isDefeated) {
|
|
if (enemy.loot) {
|
|
lootDropped = this._generateLoot(enemy.loot);
|
|
session.rewards.items.push(...lootDropped);
|
|
}
|
|
session.currentEnemyHp = undefined;
|
|
}
|
|
|
|
return {
|
|
damageDealt: damage,
|
|
enemyHp: Math.max(0, session.currentEnemyHp || 0),
|
|
targetDefeated: isDefeated,
|
|
loot: lootDropped,
|
|
};
|
|
}
|
|
|
|
moveToNextRoom(playerId) {
|
|
const session = this.activeSessions.get(playerId);
|
|
if (!session || session.isFinished) return null;
|
|
|
|
const dungeon = DatapackLoader.getDungeon(session.dungeonId);
|
|
const roomRef = dungeon.rooms[session.currentRoomIndex];
|
|
const rawRoom = DatapackLoader.getRoom(roomRef.id);
|
|
|
|
if (rawRoom) {
|
|
if (rawRoom.hostiles) {
|
|
rawRoom.hostiles.forEach((hId) => {
|
|
const enemy = DatapackLoader.getEnemy(hId);
|
|
if (enemy) {
|
|
session.rewards.xp += enemy.gainXp || 0;
|
|
session.rewards.credits += enemy.credits || 0;
|
|
}
|
|
});
|
|
}
|
|
session.rewards.xp += rawRoom.gainXp || 0;
|
|
session.rewards.credits += rawRoom.credits || 0;
|
|
if (rawRoom.loot) {
|
|
session.rewards.items.push(...this._generateLoot(rawRoom.loot));
|
|
}
|
|
}
|
|
|
|
if (session.currentRoomIndex < dungeon.rooms.length - 1) {
|
|
session.currentRoomIndex++;
|
|
return this.getCurrentRoomData(playerId);
|
|
}
|
|
|
|
session.isFinished = true;
|
|
return { status: "completed", rewards: session.rewards };
|
|
}
|
|
|
|
_generateLoot(lootTable) {
|
|
const dropped = [];
|
|
lootTable.forEach((entry) => {
|
|
if (Math.random() <= (entry.chance || 1.0)) {
|
|
const count =
|
|
typeof entry.count === "object"
|
|
? Math.floor(
|
|
Math.random() * (entry.count.max - entry.count.min + 1),
|
|
) + entry.count.min
|
|
: entry.count || 1;
|
|
dropped.push({ id: entry.id, count });
|
|
}
|
|
});
|
|
return dropped;
|
|
}
|
|
|
|
leaveDungeon(playerId) {
|
|
this.activeSessions.delete(playerId);
|
|
}
|
|
}
|
|
|
|
module.exports = new DungeonManager();
|