Fixed Dungeon Rewards. Updated DungeonManager
This commit is contained in:
parent
3307503086
commit
e7f98d1228
@ -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) {
|
||||||
|
|||||||
@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user