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 roomRef = dungeon.rooms[session.currentRoomIndex];
const rawRoom = DatapackLoader.getRoom(roomRef.id);
if (!rawRoom) return null;
const roomData = rawRoom;
const hostiles = (roomData.hostiles || [])
.map((hId) => {
return DatapackLoader.getEnemy(hId);
})
const hostiles = (rawRoom.hostiles || [])
.map((hId) => DatapackLoader.getEnemy(hId))
.filter(Boolean);
return {
roomIndex: session.currentRoomIndex,
totalRooms: dungeon.rooms.length,
config: roomData,
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;
@ -53,43 +83,46 @@ class DungeonManager {
const roomRef = dungeon.rooms[session.currentRoomIndex];
const rawRoom = DatapackLoader.getRoom(roomRef.id);
if (rawRoom && rawRoom.room) {
const room = rawRoom.room;
session.rewards.xp += room.gainXp || 0;
session.rewards.credits += room.credits || 0;
if (room.loot && Array.isArray(room.loot)) {
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,
});
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));
}
}
session.currentEnemyHp = undefined;
if (session.currentRoomIndex < dungeon.rooms.length - 1) {
session.currentRoomIndex++;
return this.getCurrentRoomData(playerId);
}
session.isFinished = true;
return {
status: "completed",
rewards: session.rewards,
};
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) {

View File

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