Fixed Dungeon Rewards. Updated DungeonManager

This commit is contained in:
MaksSlyzar 2026-04-18 16:33:47 +03:00
parent 3307503086
commit e7f98d1228
2 changed files with 90 additions and 135 deletions

View File

@ -26,25 +26,55 @@ class DungeonManager {
const dungeon = DatapackLoader.getDungeon(session.dungeonId); const dungeon = DatapackLoader.getDungeon(session.dungeonId);
const roomRef = dungeon.rooms[session.currentRoomIndex]; const roomRef = dungeon.rooms[session.currentRoomIndex];
const rawRoom = DatapackLoader.getRoom(roomRef.id); const rawRoom = DatapackLoader.getRoom(roomRef.id);
if (!rawRoom) return null; if (!rawRoom) return null;
const roomData = rawRoom; const hostiles = (rawRoom.hostiles || [])
const hostiles = (roomData.hostiles || []) .map((hId) => DatapackLoader.getEnemy(hId))
.map((hId) => {
return DatapackLoader.getEnemy(hId);
})
.filter(Boolean); .filter(Boolean);
return { return {
roomIndex: session.currentRoomIndex, roomIndex: session.currentRoomIndex,
totalRooms: dungeon.rooms.length, totalRooms: dungeon.rooms.length,
config: roomData, config: rawRoom,
hostiles, 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) { moveToNextRoom(playerId) {
const session = this.activeSessions.get(playerId); const session = this.activeSessions.get(playerId);
if (!session || session.isFinished) return null; if (!session || session.isFinished) return null;
@ -53,32 +83,22 @@ class DungeonManager {
const roomRef = dungeon.rooms[session.currentRoomIndex]; const roomRef = dungeon.rooms[session.currentRoomIndex];
const rawRoom = DatapackLoader.getRoom(roomRef.id); const rawRoom = DatapackLoader.getRoom(roomRef.id);
if (rawRoom && rawRoom.room) { if (rawRoom) {
const room = rawRoom.room; if (rawRoom.hostiles) {
rawRoom.hostiles.forEach((hId) => {
session.rewards.xp += room.gainXp || 0; const enemy = DatapackLoader.getEnemy(hId);
session.rewards.credits += room.credits || 0; if (enemy) {
session.rewards.xp += enemy.gainXp || 0;
if (room.loot && Array.isArray(room.loot)) { session.rewards.credits += enemy.credits || 0;
room.loot.forEach((lootEntry) => {
const roll = Math.random();
if (roll <= (lootEntry.chance || 1.0)) {
session.rewards.items.push({
id: lootEntry.id,
count:
typeof lootEntry.count === "object"
? Math.floor(
Math.random() *
(lootEntry.count.max - lootEntry.count.min + 1),
) + lootEntry.count.min
: lootEntry.count || 1,
});
} }
}); });
} }
session.rewards.xp += rawRoom.gainXp || 0;
session.rewards.credits += rawRoom.credits || 0;
if (rawRoom.loot) {
session.rewards.items.push(...this._generateLoot(rawRoom.loot));
}
} }
session.currentEnemyHp = undefined;
if (session.currentRoomIndex < dungeon.rooms.length - 1) { if (session.currentRoomIndex < dungeon.rooms.length - 1) {
session.currentRoomIndex++; session.currentRoomIndex++;
@ -86,10 +106,23 @@ class DungeonManager {
} }
session.isFinished = true; session.isFinished = true;
return { return { status: "completed", rewards: session.rewards };
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) { leaveDungeon(playerId) {

View File

@ -9,25 +9,16 @@ module.exports = (io, socket) => {
try { try {
if (!userId) return; if (!userId) return;
const dungeon = DatapackLoader.getDungeon(dungeonId); const dungeon = DatapackLoader.getDungeon(dungeonId);
if (!dungeon) {
return socket.emit("error", { message: "Dungeon not found" });
}
const player = await Player.findByPk(userId); const player = await Player.findByPk(userId);
const energyCost = dungeon.meta?.energyCost || 0; const energyCost = dungeon?.meta?.energyCost || 0;
if (player.energy < energyCost) { if (!dungeon)
return socket.emit("error", { message: "Dungeon not found" });
if (player.energy < energyCost)
return socket.emit("error", { message: "Insufficient energy" }); return socket.emit("error", { message: "Insufficient energy" });
}
await player.decrement("energy", { by: energyCost }); await player.decrement("energy", { by: energyCost });
const firstRoom = dungeonManager.startDungeon(userId, dungeonId); const firstRoom = dungeonManager.startDungeon(userId, dungeonId);
if (!firstRoom) {
return socket.emit("error", {
message: "Failed to initialize dungeon",
});
}
socket.emit("dungeon:started", { socket.emit("dungeon:started", {
dungeonId: dungeon.id, dungeonId: dungeon.id,
@ -38,92 +29,34 @@ module.exports = (io, socket) => {
remainingEnergy: player.energy - energyCost, remainingEnergy: player.energy - energyCost,
}); });
} catch (err) { } catch (err) {
console.error("Dungeon Start Error:", err);
socket.emit("error", { message: "Critical deployment failure" }); socket.emit("error", { message: "Critical deployment failure" });
} }
}); });
socket.on("dungeon:combat_step", async ({ enemyId }) => { socket.on("dungeon:combat_step", async ({ enemyId }) => {
try { const result = dungeonManager.processCombatStep(userId, enemyId);
if (!userId) return; if (!result) return;
const session = dungeonManager.activeSessions.get(userId);
if (!session || session.isFinished) return;
const rawEnemy = DatapackLoader.getEnemy(enemyId);
if (!rawEnemy) {
return socket.emit("error", { message: "Target data corrupted" });
}
const enemy = rawEnemy;
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 && enemy.loot) {
enemy.loot.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;
const drop = { id: entry.id, count };
lootDropped.push(drop);
session.rewards.items.push(drop);
}
});
}
socket.emit("dungeon:combat_result", { socket.emit("dungeon:combat_result", {
damageDealt: damage, ...result,
enemyHp: Math.max(0, session.currentEnemyHp), message: result.targetDefeated
targetDefeated: isDefeated, ? "Enemy eliminated!"
loot: lootDropped, : `Strike successful. Dealt ${result.damageDealt} damage.`,
message: isDefeated
? `Enemy eliminated!`
: `Strike successful. Dealt ${damage} damage.`,
}); });
if (isDefeated) {
session.currentEnemyHp = undefined;
}
} catch (err) {
console.error("Combat Error:", err);
}
}); });
socket.on("dungeon:next_room", async () => { socket.on("dungeon:next_room", async () => {
try { try {
if (!userId) return;
const nextRoom = dungeonManager.moveToNextRoom(userId); const nextRoom = dungeonManager.moveToNextRoom(userId);
if (!nextRoom) { if (!nextRoom)
return socket.emit("error", { return socket.emit("error", { message: "Navigation error" });
message: "Could not proceed to next room",
});
}
if (nextRoom.status === "completed") { if (nextRoom.status === "completed") {
await finalizeDungeon(socket, nextRoom.rewards); await finalizeDungeon(socket, nextRoom.rewards);
} else { } else {
socket.emit("dungeon:room_update", { socket.emit("dungeon:room_update", nextRoom);
room: nextRoom.config,
hostiles: nextRoom.hostiles,
roomIndex: nextRoom.roomIndex,
});
} }
} catch (err) { } catch (err) {
console.error("Dungeon Progress Error:", err);
socket.emit("error", { message: "Navigation system error" }); socket.emit("error", { message: "Navigation system error" });
} }
}); });
@ -138,44 +71,33 @@ async function finalizeDungeon(socket, sessionRewards) {
try { try {
const player = await Player.findByPk(userId); const player = await Player.findByPk(userId);
if (sessionRewards.credits > 0) { if (sessionRewards.credits > 0)
await player.increment("credits", { by: sessionRewards.credits }); await player.increment("credits", { by: sessionRewards.credits });
} if (sessionRewards.xp > 0)
await player.increment("experience", { by: sessionRewards.xp });
if (sessionRewards.xp > 0) {
await player.increment("xp", { by: sessionRewards.xp });
}
if (sessionRewards.items.length > 0) { if (sessionRewards.items.length > 0) {
const consolidatedItems = sessionRewards.items.reduce((acc, curr) => { const consolidated = sessionRewards.items.reduce((acc, curr) => {
acc[curr.id] = (acc[curr.id] || 0) + curr.count; acc[curr.id] = (acc[curr.id] || 0) + curr.count;
return acc; return acc;
}, {}); }, {});
for (const [itemId, totalCount] of Object.entries(consolidatedItems)) { for (const [itemId, totalCount] of Object.entries(consolidated)) {
const [invItem] = await Inventory.findOrCreate({ const [invItem] = await Inventory.findOrCreate({
where: { playerId: userId, itemId: itemId }, where: { playerId: userId, itemId: itemId },
defaults: { quantity: 0 }, defaults: { quantity: 0 },
}); });
await invItem.increment("quantity", { by: totalCount }); await invItem.increment("quantity", { by: totalCount });
} }
sessionRewards.items = Object.entries(consolidatedItems).map( sessionRewards.items = Object.entries(consolidated).map(
([id, count]) => ({ ([id, count]) => ({ id, count }),
id,
count,
}),
); );
} }
socket.emit("dungeon:completed", { socket.emit("dungeon:completed", { rewards: sessionRewards });
rewards: sessionRewards,
message: "Mission successful. All objectives secured.",
});
} catch (err) { } catch (err) {
console.error("Finalize Error:", err); socket.emit("error", { message: "Failed to save rewards" });
socket.emit("error", { message: "Failed to save mission rewards" });
} finally { } finally {
dungeonManager.leaveDungeon(userId); dungeonManager.leaveDungeon(userId);
} }